ゼロから作る、簡単WebチャットUIの作り方

この記事は[31億市場!?  チャットの作り方[1日コース]](https://qiita.com/st5757/items/c2c5cf21c97fe242a4c0)の2コマ目の記事です。

## 今回やること
まずはUIをhtmlとcssだけで作っていきます。
内容は初歩的な内容なので、初心者の方以外は読み飛ばてください。

![Cmesseイメージ2.png](https://qiita-image-store.s3.amazonaws.com/0/13827/cd167eed-fe3c-8809-c4ec-0ebf6e7d7c8e.png)


## これができると何が良い？
チャットUIを作ることで、チャットに必要なHTMLとCSSの構造がだいたい理解できます。

## 大枠のhtmlを作る
今回は、まずHTMLとCSSだけでチャットUIを作ってみます。

エディタは[VS Code](https://code.visualstudio.com/)使ってます。
新規ファイルを作成して`index.html`とします。
コードを入れていきましょう。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>チャットサンプル</title>
</head>
<body>
    <!-- 自分やユーザーの情報 -->
    <div id="your_container">
        <!-- チャットの外側部分① -->
            <!-- ヘッダー部分② -->
                <!--ステータス-->
                <!--ユーザー名-->
            <!-- タイムライン部分③ -->
                <!--メッセージ１-->
                <!--メッセージ２-->
            <!-- テキストボックス、送信ボタン④ -->
    </div>
</body>
</html>
```

### ※【おまけ】VS Codeを初めて使う人向け
VS Codeの拡張機能に`HTML Snippets`というのがあるので、これを使うのがオススメです。
こんな感じでhtmlの雛形を一発で生成してくれるのでミスなくスピーデイに開発できます。
![vscode_snipet.gif](https://qiita-image-store.s3.amazonaws.com/0/13827/76e49e5a-a3db-4345-a1a8-0589dd57c685.gif)

話を戻します。
`<body></body>`内は↓こんな感じ。
後々スタイルや処理を当てていくので、htmlにはタグにidを付けつつ作ってます。
なお、idには接頭語を付けておきます。
**ビ**ジネス向け**メッセ**ージツールを想定してつくったので、接頭語は`bms_`にしました。
別にビジネスじゃなくても使えますのでそこはあんまり気にしないでください。

```html
<body>
    <!-- 自分やユーザーの情報 -->
    <h3 id="me" user_id="1">あなたはユーザー1です</h3>
    <h3 id="partner" thread_id="1">相手</h3>
    <div id="users">
        <button class="user" user_id="2">ユーザー2</button>
    </div>
    <br>
    <div id="your_container">

        <!-- チャットの外側部分① -->
        <div id="bms_messages_container">
            <!-- ヘッダー部分② -->
            <div id="bms_chat_header">
                <!--ステータス-->
                <div id="bms_chat_user_status">
                    <!--ステータスアイコン-->
                    <div id="bms_status_icon">●</div>
                    <!--ユーザー名-->
                    <div id="bms_chat_user_name">ユーザー</div>
                </div>
            </div>
  
            <!-- タイムライン部分③ -->
            <div id="bms_messages">
  
                <!--メッセージ１（左側）-->
                <div class="bms_message bms_left">
                    <div class="bms_message_box">
                        <div class="bms_message_content">
                            <div class="bms_message_text">ほうほうこりゃー便利じゃないか</div>
                        </div>
                    </div>
                </div>
                <div class="bms_clear"></div><!-- 回り込みを解除（スタイルはcssで充てる） -->

                <!--メッセージ２（右側）-->
                <div class="bms_message bms_right">
                    <div class="bms_message_box">
                        <div class="bms_message_content">
                            <div class="bms_message_text">うん、まあまあいけとるな</div>
                        </div>
                    </div>
                </div>
                <div class="bms_clear"></div><!-- 回り込みを解除（スタイルはcssで充てる） -->
            </div>
  
            <!-- テキストボックス、送信ボタン④ -->
            <div id="bms_send">
                <textarea id="bms_send_message"></textarea>
                <div id="bms_send_btn">送信</div>
            </div>
        </div>
    </div>
</body>
```
### ●ヘッダー部分②
`your_container`と①については後ほどcss内コメントで説明
②は相手のステータス`bms_chat_user_status`と、名前`bms_chat_user_name`があるだけです。
左寄せで横並びにするので`bms_chat_user_status`で囲ってます

### ●タイムライン部分③
③はタイムライン自体が`bms_messages`で、その中にメッセージが入れられるようになってます。
メッセージは何度も出てくるので、idでなくclassを充てています。
メッセージ１の外枠部分は、左側には`bms_message`クラスと`bms_left`クラスを、右側にも同じ様に入れてます。
後々、既読の時間表示したいので、既読表示とメッセージを分けるために`bms_message_box`にメッセージをまとめてます。
で、その中にテキスト部分の`bms_message_text`があります。後々画像や動画なんかも`bms_message_text`と同じ階層に表示するでしょうから、さらに`bms_message_content`で囲っている形です。

### ●テキストボックス、送信ボタン④
テキストボックスと、送信ボタンは横並びのスタイルになるので、その外側に`bms_send`を作ってスタイルを充てられる様にしてます。
htmlにはボタン専用の`<button>`タグが用意されていますが、使い慣れている`<div>`タグを使っています。


①〜④やると、こんな感じになります。
![チャットui開発1.png](https://qiita-image-store.s3.amazonaws.com/0/13827/acb7aad2-3004-2cc6-fd92-387925c301a0.png)


じゃぁスタイル充てていきましょう！

## スタイルを充てる
### ●チャットの枠にスタイルを充てる
スタイルのファイル`bmesse.css`を作って、`index.html`のhead要素内で読み込みます。

```html
<head>
    ・・・
    <link type="text/css" rel="stylesheet" href="bmesse.css" />
</head>
```

一気に書いていきますね。
説明はコード内にコメントとして記述してます。

```css
#your_container{
    /* 高さや幅など、好きな様に設定
    bms_messages_containerの方で、縦横いっぱいに広がってくれるので、
    ここで充てた高さと横幅がそのままスタイルになる仕組み */

    height:600px;/*ここはご自由に*/
    width: 50%;/*ここはご自由に*/
}
/* チャットの外側部分① */
#bms_messages_container{
    height: 100%;/*your_containerに対して100%になる */
    width: 100%;/*your_containerに対して100%になる */
    background-color: #eee;
}

/* ヘッダー部分② */
#bms_chat_header {
    padding: 6px;/*隙間調整*/
    font-size: 16px;
    height: 34px;
    background: #ddd;
    border: 1px solid #ccc;
}
    /* ステータスマークとユーザー名 */
    #bms_chat_user_status {
        float: left;/* bms_chat_headerに対して左寄せ */
    }
    /* ステータスマーク */
    #bms_status_icon {
        float: left;/* bms_chat_user_statusに対して左寄せ */
        line-height: 2em;/*高さ調整*/
    }
    /* ユーザー名 */
    #bms_chat_user_name {
        float: left;/* bms_chat_user_statusに対して左寄せ */
        line-height: 2em;/*高さ調整*/
        padding-left: 8px;
    }

/* タイムライン部分③ */
#bms_messages {
    overflow: auto;/* スクロールを効かせつつ、メッセージがタイムラインの外に出ないようにする */
    height:100%;/*テキストエリアが下に張り付く様にする*/
    border-right: 1px solid #ddd;
    border-left: 1px solid #ddd;
    background-color: #eee;
    box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.2) inset;/*ヘッダーの下に影を入れる*/
}
    /* メッセージ全般のスタイル */
    .bms_message {
        margin: 0px;
        padding: 0 14px;/*吹き出しがタイムラインの側面にひっつかない様に隙間を開ける*/
        font-size: 16px;
        word-wrap: break-word;/* 吹き出し内で自動で改行 */
        white-space: normal;/*指定widthに合わせて、文字を自動的に改行*/
    }
    /* メッセージ１（左側） */
    .bms_left {
        float: left;/*吹き出しをbms_messagesに対して左寄せ*/
        line-height: 1.3em;
    }
    /* メッセージ２（右側） */
    .bms_right {
        float: right;/*吹き出しをbms_messagesに対して右寄せ*/
        line-height: 1.3em;
    }
    /* 回り込みを解除 */
    .bms_clear {
        clear: both; /* 左メッセージと右メッセージの回り込み(float)の効果の干渉を防ぐために必要（これが無いと、自分より下のメッセージにfloatが影響する） */

    }

/* テキストエリア、送信ボタン④ */
#bms_send {
    background-color:#eee;/*タイムラインの色と同じにする*/
    border-right: 1px solid #ddd;
    border-left: 1px solid #ddd;
    border-bottom: 1px solid #ddd;
    height: 48px;
    padding: 4px;
}
    #bms_send_message{
        width: calc(100% - 75px);/*常に送信ボタンの横幅を引いたサイズに動的に計算*/
        line-height: 16px;
        height: 48px;
        padding: 14px 6px 0px 6px;/*文字がテキストエリアの中心になる様に隙間調整*/
        border: 1px solid #ccc;
        border-radius: 4px;/*角丸*/
        text-align: left;/*文字を左寄せ*/
        box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.2) inset;/*内側に影を入れてテキストエリアらしくした*/
        box-sizing: border-box;/*paddingとborderの要素の高さと幅の影響をなくす（要素に高さと幅を含める）*/

    }
    #bms_send_btn {
        width: 72px;
        height: 48px;
        font-size: 16px;
        line-height: 3em;
        float: right;/*bms_sendに対して右寄せ*/
        color: #fff;
        font-weight: bold;
        background: #bcbcbc;
        text-align: center;/*文字をボタン中央に表示*/
        border: 1px solid #bbb;
        border-radius: 4px;/*角丸*/
        box-sizing: border-box;/*paddingとborderの要素の高さと幅の影響をなくす（要素に高さと幅を含める）*/
    }
    #bms_send_btn:hover {
        background: #13178E; /*マウスポインタを当てた時にアクティブな色になる*/
        cursor: pointer;/*マウスポインタを当てた時に、カーソルが指の形になる*/
    }
```
こんな感じになります。
![チャットui開発2.png](https://qiita-image-store.s3.amazonaws.com/0/13827/7c25723b-4fb2-74d5-25bf-dc98598a7913.png)


最後に吹き出しのスタイルを充てればOKですね
それをやっていきます。

### ●チャットの吹き出しのスタイルを作り込む
`.bms_message`の下に追加していきます

```css
    .bms_message {
        ・・・
    }
        /*
         *追加
         */
        .bms_message_box{
            margin-top: 20px;/*上下の吹き出しがひっつかない様に隙間を入れる*/
            max-width: 100%;/*文字が長くなった時に吹き出しがタイムラインからはみ出さない様にする*/
            font-size: 16px;
        }
            /*
            *追加
            */
            .bms_message_content{
                padding: 20px;/*文字や画像（コンテンツ）の外側に隙間を入れる*/
            }

        /* メッセージ１（左側） */
        .bms_left {
            float: left;/*吹き出しをbms_messagesに対して左寄せ*/
            line-height: 1.3em;
        }
            /*
            *追加
            */
            .bms_left .bms_message_box {
                color: #333;/*テキストを黒にする*/
                background: #fff;
                border: 2px solid #13178E;
                border-radius: 30px 30px 30px 0px;/*左下だけ尖らせて吹き出し感を出す*/
                margin-right: 50px;/*左側の発言だとわかる様に、吹き出し右側に隙間を入れる*/
            }

        /* メッセージ２（右側） */
        .bms_right {
            float: right;/*吹き出しをbms_messagesに対して右寄せ*/
            line-height: 1.3em;
        }
            /*
            *追加
            */
            .bms_right .bms_message_box {
                color: #fff;/*テキストを白にする*/
                background: #13178E;
                border: 2px solid #13178E;
                border-radius: 30px 30px 0px 30px;/*右下だけ尖らせて吹き出し感を出す*/
                margin-left: 50px;/*右側の発言だとわかる様に、吹き出し左側に隙間を入れる*/
            }
```

![Cmesseイメージ2.png](https://qiita-image-store.s3.amazonaws.com/0/13827/cd167eed-fe3c-8809-c4ec-0ebf6e7d7c8e.png)


出来上がったコードは[ここ](https://firebasestorage.googleapis.com/v0/b/chatservicesample.appspot.com/o/day2.zip?alt=media&token=12256585-0382-4b76-a913-548c447daf7f)に置いておきますね。

次回は、「3コマ目： htmlをJavascriptで組み立てる方法」です。
今回作ったhtmlを、javascriptから動的に組み立てるようにしてみましょう〜。

（※連載一覧は[こちら](https://qiita.com/st5757/items/c2c5cf21c97fe242a4c0#機能としてはこんな感じです)）