チャット · チャットUI

マンガの吹き出しで進むサポートチャット

保存した一覧を見る 0 →

このブラウザー内に保存します。別の端末との同期はなく、サイトデータを消すと保存も消えます。

印刷時は見本を静止画にし、プロンプトと解説を出力します。PDF保存はブラウザーの印刷画面から選べます。

Vibehaus · デザイン資料
https://vibe.itlibra.com/design/comic-support-chat/
完全無料・著作権フリー(CC0)· 料金¥0 · 商用利用・改変自由

プレビュー

画面に合わせる

指定幅で実際に組み替えて表示します。表示領域より広い場合は、この枠の中で横へスクロールできます。

vibe.itlibra.com/preview/comic-support-chat/

AIへの指示文

カスタマーサポートのチャット画面を、マンガの吹き出し表現で作ってください。

要件:
- 配色: 生成りの紙 #fbf7ee、黒 #171412、トーン地 #e8e1d3、朱色 #ff5a3c、青 #2f6df6。
- 背景に -45度の細い網掛け(repeating-linear-gradient、不透明度0.045)を敷いてスクリーントーンを再現する。
- 全体を4pxの黒枠で囲み、右下に10pxのベタ影(box-shadow のオフセットのみ、ぼかし0)を落とす。
- 吹き出しは角丸20px + 3pxの黒輪郭。尻尾は疑似要素2枚(黒い三角の上に背景色の三角を重ねる)で作る。
- 相手の吹き出しは左に尻尾、自分の吹き出しは右に尻尾+グレー地。
- 解決した瞬間の1コマだけ「叫び吹き出し」にする: 朱色ベタ、白抜き太字、-1.2度の傾き、角の一つだけ尖らせる。
- 擬音(ドン!)を斜めに配置し、朱色の極太で置く。
- ヘッダーに担当者アバター(CSSだけで目と口を描く)、名前、平均返信時間、「EP.12 / P.3」のページ番号。
- 定型返答のボタンはピル型・3px輪郭・3pxのベタ影、押すと影が消えて沈む。
- フォントは丸ゴシック優先。日本語の letter-spacing は0、本文の行間1.8。

バリエーション

4コマ完結版

吹き出しを4つに固定し、縦に均等な4コマとして枠線で仕切る。
よくある質問の回答を4コマで見せる用途に使う。

モノクロ劇画版

朱色を捨てて黒白のみにし、網掛けを濃くする。
吹き出しの輪郭を手描き風の不均一な太さにして、深刻な問い合わせにも耐える硬さを出す。

このプレビューのコード

HTMLとCSSの1ファイルです。外部依存・広告・解析コードはありません。マンガ風のサポート画面の表示見本です。選択肢・送信・請求書再発行・メール配信は実装していません。

CC0 · 改変・商用利用自由 · revision a1be2d485a60

コードを表示
<!doctype html>
<!-- Vibehaus — CC0。外部依存なし。請求書・メールを扱わない架空の表示見本。 -->
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="robots" content="noindex" />
    <title>マンガの吹き出しで進むサポートチャット — Vibehaus プレビュー</title>
    <style>
      :root {
        --paper: #fbf7ee;
        --ink: #171412;
        --tone: #e8e1d3;
        --accent: #ff5a3c;
        --accent-2: #2f6df6;
        --dim: #6f6759;
      }
      * { box-sizing: border-box; }
      html, body { margin: 0; padding: 0; }
      body {
        min-height: 100vh;
        font-family: "Hiragino Maru Gothic ProN", "Hiragino Kaku Gothic ProN",
          "Noto Sans JP", "Yu Gothic", "Meiryo", "Inter", sans-serif;
        color: var(--ink);
        line-height: 1.8;
        background:
          repeating-linear-gradient(
            -45deg,
            rgba(23, 20, 18, 0.045) 0 2px,
            transparent 2px 7px
          ),
          var(--paper);
        display: flex;
        justify-content: center;
        padding: clamp(1rem, 3vw, 2rem);
        -webkit-font-smoothing: antialiased;
      }

      .book {
        width: min(720px, 100%);
        background: var(--paper);
        border: 4px solid var(--ink);
        box-shadow: 10px 10px 0 0 var(--ink);
        display: flex;
        flex-direction: column;
      }

      header.strip {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding: 0.75rem 1rem;
        border-bottom: 4px solid var(--ink);
        background: var(--accent);
        color: var(--paper);
      }
      header .who { display: flex; align-items: center; gap: 0.6rem; }
      .avatar {
        width: 34px; height: 34px;
        border: 3px solid var(--ink);
        border-radius: 50%;
        background: var(--paper);
        position: relative;
      }
      .avatar::before, .avatar::after {
        content: "";
        position: absolute;
        top: 11px;
        width: 4px; height: 5px;
        background: var(--ink);
        border-radius: 2px;
      }
      .avatar::before { left: 8px; }
      .avatar::after  { right: 8px; }
      .avatar i {
        position: absolute;
        bottom: 7px; left: 50%;
        transform: translateX(-50%);
        width: 12px; height: 6px;
        border: 3px solid var(--ink);
        border-top: 0;
        border-radius: 0 0 12px 12px;
      }
      header .name { font-weight: 800; font-size: 0.95rem; line-height: 1.5; }
      header .status { font-size: 0.72rem; line-height: 1.6; opacity: 0.9; }
      header .page {
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.68rem;
        letter-spacing: 0.14em;
      }

      .panels {
        padding: 1.1rem 1rem 0.5rem;
        display: grid;
        gap: 1.1rem;
      }

      .turn { display: grid; gap: 0.35rem; }
      .turn .meta {
        font-family: "JetBrains Mono", ui-monospace, monospace;
        font-size: 0.68rem;
        letter-spacing: 0; /* 話者名は和文。トラッキングを開かない */
        color: var(--dim);
      }

      /* Speech balloon — hard outline + a tail cut from two triangles. */
      .balloon {
        position: relative;
        max-width: 86%;
        padding: 0.85rem 1.05rem;
        border: 3px solid var(--ink);
        border-radius: 20px;
        background: var(--paper);
        font-size: 0.95rem;
        line-height: 1.8;
      }
      .balloon::before, .balloon::after {
        content: "";
        position: absolute;
        bottom: -17px;
        width: 0; height: 0;
        border-style: solid;
      }
      /* agent (left) */
      .agent .balloon { background: #fff; }
      .agent .balloon::before {
        left: 26px;
        border-width: 17px 15px 0 0;
        border-color: var(--ink) transparent transparent transparent;
      }
      .agent .balloon::after {
        left: 30px;
        bottom: -12px;
        border-width: 12px 10px 0 0;
        border-color: #fff transparent transparent transparent;
      }
      /* user (right) */
      .user { justify-items: end; }
      .user .meta { text-align: right; }
      .user .balloon {
        background: var(--tone);
        border-radius: 20px;
      }
      .user .balloon::before {
        right: 26px;
        border-width: 17px 0 0 15px;
        border-color: var(--ink) transparent transparent transparent;
      }
      .user .balloon::after {
        right: 30px;
        bottom: -12px;
        border-width: 12px 0 0 10px;
        border-color: var(--tone) transparent transparent transparent;
      }

      /* Shout balloon for the resolved moment. */
      .shout .balloon {
        background: var(--accent);
        color: var(--paper);
        border-width: 4px;
        border-radius: 26px 26px 26px 6px;
        font-weight: 800;
        transform: rotate(-1.2deg);
      }
      .shout .balloon::after { border-color: var(--accent) transparent transparent transparent; }

      /* The sound effect sits outside the balloon, the way it does on a
         printed page — never squeezed into the line of dialogue. */
      .shout { position: relative; }
      .sfx {
        position: absolute;
        right: 4px;
        top: 6px;
        font-weight: 900;
        font-size: clamp(1.3rem, 4vw, 1.8rem);
        line-height: 1.4;
        color: var(--accent);
        -webkit-text-stroke: 2px var(--ink);
        paint-order: stroke fill;
        transform: rotate(-8deg);
      }

      .choices {
        display: flex;
        gap: 0.5rem;
        flex-wrap: wrap;
        padding: 0.25rem 1rem 1rem;
      }
      .choice {
        font: inherit;
        font-size: 0.85rem;
        line-height: 1.6;
        font-weight: 700;
        padding: 0.5rem 0.95rem;
        border: 3px solid var(--ink);
        border-radius: 999px;
        background: var(--paper);
        cursor: pointer;
        box-shadow: 3px 3px 0 0 var(--ink);
        transition: transform 0.08s, box-shadow 0.08s, background 0.15s;
      }
      .choice:hover { background: #ffe9a8; }
      .choice:active { transform: translate(3px, 3px); box-shadow: none; }

      .composer {
        display: flex;
        gap: 0.6rem;
        padding: 0.85rem 1rem;
        border-top: 4px solid var(--ink);
        background: var(--tone);
      }
      .composer input {
        flex: 1;
        font: inherit;
        font-size: 0.95rem;
        line-height: 1.7;
        padding: 0.6rem 0.9rem;
        border: 3px solid var(--ink);
        border-radius: 999px;
        background: var(--paper);
        color: var(--ink);
      }
      .composer input:focus { outline: none; box-shadow: 0 0 0 3px rgba(255, 90, 60, 0.35); }
      .composer button {
        font: inherit;
        font-size: 0.9rem;
        font-weight: 800;
        padding: 0.6rem 1.2rem;
        border: 3px solid var(--ink);
        border-radius: 999px;
        background: var(--accent-2);
        color: var(--paper);
        cursor: pointer;
        box-shadow: 3px 3px 0 0 var(--ink);
      }
      .composer button:active { transform: translate(3px, 3px); box-shadow: none; }

      @media (max-width: 520px) {
        .book { box-shadow: 6px 6px 0 0 var(--ink); }
        .balloon { max-width: 94%; }
      }
      button { min-height:44px; }
      :focus-visible { outline:3px solid var(--accent-2); outline-offset:3px; }
      .composer input { min-width:0; }
      .balloon { overflow-wrap:anywhere; }
      .demo-note { margin:0; padding:8px 16px; font-size:12px; line-height:1.8; }
      @media (prefers-reduced-motion:reduce) { .choice { transition:none; } }
    </style>
  </head>
  <body>
    <div class="book">
      <header class="strip">
        <div class="who">
          <span class="avatar" aria-hidden="true"><i></i></span>
          <div>
            <div class="name">サポートの ばん さん</div>
            <div class="status">ただいま対応中 · 平均返信 40秒</div>
          </div>
        </div>
        <span class="page">EP.12 / P.3</span>
      </header>
      <p class="demo-note">架空の対話の表示見本です。選択肢・送信は未実装で、請求書やメールは扱いません。</p>

      <div class="panels">
        <div class="turn agent">
          <span class="meta">ばん · 16:02</span>
          <div class="balloon">こんにちは! 今日はどうされましたか?</div>
        </div>

        <div class="turn user">
          <span class="meta">あなた · 16:03</span>
          <div class="balloon">先月の請求書がダウンロードできなくて困っています……</div>
        </div>

        <div class="turn agent">
          <span class="meta">ばん · 16:03</span>
          <div class="balloon">
            承知しました! 請求書は「設定 → お支払い」から取得できます。該当の月は 2026年7月 でお間違いないですか?
          </div>
        </div>

        <div class="turn user">
          <span class="meta">あなた · 16:04</span>
          <div class="balloon">はい、7月分です。</div>
        </div>

        <div class="turn agent shout">
          <span class="meta">ばん · 16:04</span>
          <span class="sfx" aria-hidden="true">ドン!</span>
          <div class="balloon">
            見つかりました! いま再発行して、登録のメールにお送りしました
          </div>
        </div>
      </div>

      <div class="choices">
        <button class="choice" type="button">届きました、ありがとう</button>
        <button class="choice" type="button">まだ届きません</button>
        <button class="choice" type="button">別の件も聞きたい</button>
      </div>

      <form class="composer" onsubmit="return false;">
        <input type="text" placeholder="メッセージを入力…" aria-label="メッセージ" />
        <button type="submit">送る</button>
      </form>
    </div>
  </body>
</html>

2026年10月14日、Chromiumで320・390・768・1280pxの描画とキーボードのフォーカス表示を確認しました。他のブラウザは未確認です。利用先のブラウザと実データでも確認してください。

概要

日本のマンガは、吹き出しの形だけで声の質を描き分けてきました。丸い輪郭は通常の会話、爆発形は叫び、点線は内心、四角はナレーション。読者はこの記号体系を教わることなく身につけています。チャットUIにこれを持ち込むと、文字量を増やさずに感情の起伏を表現できます。

均一な吹き出しが失うもの

一般的なチャットUIでは、すべての発言が同じ形の角丸長方形で並びます。整然としていますが、対話の中で最も重要な瞬間——問題が解決した一言——も、事務的な確認と同じ見た目で流れていきます。この設計では、解決の1コマだけを叫び吹き出しに切り替えます。朱色のベタ、白抜きの太字、わずかな傾き、そして斜めの擬音。同じテキストでも、読んだ側の記憶への残り方が変わります。サポートの満足度は解決までの時間だけでは決まりません。解決したと感じられたかで決まります。

紙の質感が担保する人間味

背景の網掛けはスクリーントーンの再現です。無地の白背景よりわずかに情報量が増え、画面が印刷物に近づきます。4pxの黒枠と、ぼかしのないベタ影も同じ方向の意匠で、画面をコマとして扱う宣言になっています。ヘッダーの担当者アバターをCSSの図形だけで描いているのは、写真のアイコンより記号的な顔の方が親しみやすいためです。人は抽象化された顔に自分の期待を投影します。

仕上げの判断軸

向かないのは障害報告と解約の窓口です。困っている度合いが強い相手にマンガの軽さを当てると、真剣に扱われていないと読まれます。

同じ意匠でも彩度を落としたモノクロ版に切り替えるか、通常のチャットUIを併用してください。擬音の文字表現はマンガ文化圏の外では読み解けないため、装飾として置き、意味を担わせないこと。網掛けの不透明度は0.05前後が上限で、それ以上は本文の可読性を削ります。

1コマ叫び吹き出しにする発言。増やすと強調が効かなくなる
4pxコマの黒枠。ぼかしのないベタ影と対で画面を紙に寄せる
0.05網掛けの不透明度の上限。超えると本文が読みにくくなる

チャットの構成要素

チャットの構成要素 相手 ── 左・淡い面 自分 ── 右・濃い面 入力欄は下に固定 左右と色の2つで区別する ── 色だけだと区別が付かない人がいる 新しい発言は読み上げにも伝える(aria-live)。時刻と既読は小さく、邪魔しない位置に
チャットは誰の発言かが一瞬で分かることが最優先です。左右の位置と面の濃さを両方使えば、色に頼らずに区別できます。

使いどころ

  • 個人向けサービスのサポート窓口
  • オンボーディング中のガイド対話
  • エンタメ・ゲーム系プロダクトの問い合わせ
  • チャットボットの回答画面
  • 若年層が主要層のサービス

このデザインの分類

カテゴリ
チャット
スタイル
コミック / プレイフル / ボールド / ウォーム / ハンドクラフト

背景と狙いどころ

よくある質問

吹き出しの尻尾はどう作りますか?
疑似要素を2枚重ねます。黒い三角を先に置き、その上に少し小さい背景色の三角を重ねると、輪郭線付きの尻尾になります。
深刻な問い合わせに軽すぎませんか?
障害報告や解約の窓口には向きません。モノクロ劇画版のように彩度を落とすか、通常のチャットUIに切り替える設計が要ります。
擬音は日本語以外でも通じますか?
効果音の文字表現はマンガ文化圏では通じますが、地域によっては読み解けません。多言語展開する場合は装飾扱いにして意味を担わせないでください。
網掛け背景は読みにくくなりませんか?
不透明度0.05前後が上限です。吹き出し自体は不透明の紙色で塗るので、本文が網に重なることはありません。

この画面を実装する

動くサンプルとコピペできるコードを、技術別にまとめています。