Chat
チャットの会話のような見た目でコンテンツを表示する UI の実装例です。Lism の primitives と少量の CSS(b--chat)で構成します。
Overview
ロレム・イプサムの座り雨。目まぐるしい文章の流れの中で、それは静かに歩く仮の言葉です。Elitも穏やかに続いていきますが、積み重ねられてきた「LiberroyとFoogの取り組み」は、余白のようなものです。
<Grid class="b--chat b--chat--speak" data-chat-dir="start"> <Frame class="b--chat_avatar" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/EkABPzB34XR7.webp" alt="" width="60" height="60" decoding="async" /> </Frame> <Lism class="b--chat_name">Taro</Lism> <Lism class="b--chat_body"> <Decorator class="b--chat_deco" util="cbox" isSkipFlow /> <Flow class="b--chat_content" util="cbox"> <p> ロレム・イプサムの座り雨。目まぐるしい文章の流れの中で、それは静かに歩く仮の言葉です。Elitも穏やかに続いていきますが、積み重ねられてきた「LiberroyとFoogの取り組み」は、余白のようなものです。 </p> </Flow> </Lism></Grid><div class="b--chat b--chat--speak l--grid" data-chat-dir="start"> <div class="b--chat_avatar l--frame" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/EkABPzB34XR7.webp" alt="" width="60" height="60" decoding="async" /> </div> <div class="b--chat_name">Taro</div> <div class="b--chat_body"> <div class="b--chat_deco a--decorator is--skipFlow u--cbox" aria-hidden="true"></div> <div class="b--chat_content l--flow u--cbox"> <p> ロレム・イプサムの座り雨。目まぐるしい文章の流れの中で、それは静かに歩く仮の言葉です。Elitも穏やかに続いていきますが、積み重ねられてきた「LiberroyとFoogの取り組み」は、余白のようなものです。 </p> </div> </div></div>Styles
Chat のベーススタイルは、以下の CSS で定義されています。この CSS をプロジェクトにコピーして利用してください。
@layer lism-block のままコピーすると、コア CSS のレイヤー順にそのまま組み込まれ、lism-custom レイヤーから上書きできます。
@layer lism-block {
.b--chat {
--cbox-bgPct: 8%;
--keycolor: var(--gray);
gap: 0 calc(var(--deco-size) + 1px);
grid-template-areas: 'avatar name' 'avatar body';
grid-template-columns: auto 1fr;
grid-template-rows: minmax(1.5rem, auto) auto;
justify-items: start;
--avator-size: clamp(48px, 32px + 5cqw, 64px); /* @320px:40px ~ @640:64px */
--deco-size: calc(min(var(--avator-size), 80px) / 4 + 0.25rem);
--deco-mask: none;
--deco-t: 0;
--deco-scale: 1;
--deco-inset-x: 0;
}
.b--chat_avatar {
grid-area: avatar;
width: var(--avator-size);
aspect-ratio: 1/1;
border-radius: var(--bdrs--99);
background-color: var(--base);
}
.b--chat_name {
grid-area: name;
align-self: end;
padding-block: var(--s5);
padding-inline: var(--s10);
color: var(--text-2);
font-size: var(--fz--2xs);
font-style: italic;
--hl: 0px;
}
.b--chat_body {
grid-area: body;
position: relative;
}
.b--chat_content {
justify-self: start;
max-width: var(--sz--s);
padding: var(--s20);
border-radius: var(--bdrs--30);
--hl: var(--hl--s);
/* 吹き出し内の flow 間隔は控えめに(l--flow が参照する --flow--base を上書き) */
--flow--base: var(--flow--s);
}
.b--chat_deco {
position: absolute;
top: var(--deco-t);
inset-inline: var(--deco-inset-x);
width: var(--deco-size);
height: var(--deco-size);
scale: var(--deco-scale);
mask: var(--deco-mask) center / contain no-repeat;
}
.b--chat--speak {
--deco-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><path d="M8,8L8,8C7.4,4.8,5.4,2,2.6,0.4L2,0h6V8z"/></svg>');
}
.b--chat--think {
--deco-t: min(calc(var(--avator-size) / 3), 1.5rem);
--deco-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><circle cx="1.5" cy="1.7" r="1.5"/><circle cx="4.5" cy="5.2" r="2.5"/></svg>');
}
[data-chat-dir='start'] {
--deco-inset-x: auto calc(100% - 1px);
}
[data-chat-dir='end'] {
--deco-scale: -1 1;
--deco-inset-x: calc(100% - 1px) auto;
grid-template-areas: 'name avatar' 'body avatar';
grid-template-columns: 1fr auto;
justify-items: end;
}
[data-chat-dir='end'] .b--chat_content {
justify-self: end;
}
}
/* NOTE: 以下は @layer 外に配置(セレクタの詳細度を確保するため) */
/* speak バリアントの角丸調整: 左側 */
.b--chat--speak[data-chat-dir='start'] > div > .b--chat_content {
border-start-start-radius: 0;
}
/* speak バリアントの角丸調整: 右側 */
.b--chat--speak[data-chat-dir='end'] > div > .b--chat_content {
border-start-end-radius: 0;
} Markup
マークアップは以下のクラス・属性で構成します。
| クラス / 属性 | 説明 |
|---|---|
b--chat |
ルート要素。l--grid と併用し、b--chat--speak(発言)または b--chat--think(思考)のモディファイアを付与します。 |
data-chat-dir |
表示位置。start(アバターが左)または end(アバターが右)を指定します。 |
b--chat_avatar |
アバター画像を表示する要素(l--frame と併用。省略可)。 |
b--chat_name |
名前を表示する要素(省略可)。 |
b--chat_body |
吹き出し部分のラッパー要素。 |
b--chat_deco |
吹き出しのしっぽ装飾(a--decorator + u--cbox と併用)。 |
b--chat_content |
コンテンツを配置する要素(l--flow + u--cbox と併用)。 |
--keycolor |
吹き出しのキーカラー。style 属性などで上書きできます(デフォルトは var(--gray))。 |
Examples
ロレム・イプサムの座り雨。目まぐるしい文章の流れの中で、それは静かに歩く仮の言葉です。Elitも穏やかに続いていきますが、積み重ねられてきた「LiberroyとFoogの取り組み」は、余白のようなものです。
ロレム・イプサムの座り雨、それは静かに歩く仮の言葉です。長いあいだ積み重ねられてきたLiberroyとFoogの取り組み」は、私たちに一定の示唆を与えてくれます。
ロレム・イプサムの座り雨。目まぐるしい文章の流れの中で、それは静かに歩く仮の言葉です。Elitも穏やかに続いていきますが、積み重ねられてきた「LiberroyとFoogの取り組み」は、余白のようなものです。
<Grid class="b--chat b--chat--speak" data-chat-dir="start"> <Frame class="b--chat_avatar" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/EkABPzB34XR7.webp" alt="" width="60" height="60" decoding="async" /> </Frame> <Lism class="b--chat_name">Taro</Lism> <Lism class="b--chat_body"> <Decorator class="b--chat_deco" util="cbox" isSkipFlow /> <Flow class="b--chat_content" util="cbox"> <p>ロレム・イプサムの座り雨。...</p> </Flow> </Lism></Grid><Grid class="b--chat b--chat--speak" keycolor="green" data-chat-dir="end"> <Frame class="b--chat_avatar" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/of5v8rPFMI8F.webp" alt="" width="60" height="60" decoding="async" /> </Frame> <Lism class="b--chat_name">Hanako</Lism> <Lism class="b--chat_body"> <Decorator class="b--chat_deco" util="cbox" isSkipFlow /> <Flow class="b--chat_content" util="cbox"> <p>ロレム・イプサムの<i>座り雨</i>、それは...</p> <p>ロレム・イプサムの座り雨。...</p> </Flow> </Lism></Grid><div class="b--chat b--chat--speak l--grid" data-chat-dir="start"> <div class="b--chat_avatar l--frame" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/EkABPzB34XR7.webp" alt="" width="60" height="60" decoding="async" /> </div> <div class="b--chat_name">Taro</div> <div class="b--chat_body"> <div class="b--chat_deco a--decorator is--skipFlow u--cbox" aria-hidden="true"></div> <div class="b--chat_content l--flow u--cbox"> <p>ロレム・イプサムの座り雨。...</p> </div> </div></div><div class="b--chat b--chat--speak l--grid" style="--keycolor:var(--green)" data-chat-dir="end"> <div class="b--chat_avatar l--frame" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/of5v8rPFMI8F.webp" alt="" width="60" height="60" decoding="async" /> </div> <div class="b--chat_name">Hanako</div> <div class="b--chat_body"> <div class="b--chat_deco a--decorator is--skipFlow u--cbox" aria-hidden="true"></div> <div class="b--chat_content l--flow u--cbox"> <p>ロレム・イプサムの<i>座り雨</i>、それは...</p> <p>ロレム・イプサムの座り雨。...</p> </div> </div></div>思考スタイル(b--chat--think)
b--chat--speak の代わりに b--chat--think を指定すると、発言ではなく心の中で思っていることを表現するスタイルになります。
b--chat--thinkLorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet. consectetur adipisicing elit, sed do eiusmod tempor. Non facere Laudantium ex eos doloribus aut dolore nisi provident.
<Grid class="b--chat b--chat--think" keycolor="blue" data-chat-dir="start"> <Frame class="b--chat_avatar" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/EkABPzB34XR7.webp" alt="" width="60" height="60" decoding="async" /> </Frame> <Lism class="b--chat_name">Name B</Lism> <Lism class="b--chat_body"> <Decorator class="b--chat_deco" util="cbox" isSkipFlow /> <Flow class="b--chat_content" util="cbox"> <p>Lorem ipsum dolor sit amet.</p> </Flow> </Lism></Grid><Grid class="b--chat b--chat--think" keycolor="purple" data-chat-dir="end"> <Frame class="b--chat_avatar" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/of5v8rPFMI8F.webp" alt="" width="60" height="60" decoding="async" /> </Frame> <Lism class="b--chat_name">Name B</Lism> <Lism class="b--chat_body"> <Decorator class="b--chat_deco" util="cbox" isSkipFlow /> <Flow class="b--chat_content" util="cbox"> <p>Lorem ipsum dolor <i>sit amet</i>. ...</p> </Flow> </Lism></Grid><div class="b--chat b--chat--think l--grid" style="--keycolor:var(--blue)" data-chat-dir="start"> <div class="b--chat_avatar l--frame" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/EkABPzB34XR7.webp" alt="" width="60" height="60" decoding="async" /> </div> <div class="b--chat_name">Name B</div> <div class="b--chat_body"> <div class="b--chat_deco a--decorator is--skipFlow u--cbox" aria-hidden="true"></div> <div class="b--chat_content l--flow u--cbox"> <p>Lorem ipsum dolor sit amet.</p> </div> </div></div><div class="b--chat b--chat--think l--grid" style="--keycolor:var(--purple)" data-chat-dir="end"> <div class="b--chat_avatar l--frame" aria-hidden="true"> <img src="https://cdn.lism-css.com/img/avatar/of5v8rPFMI8F.webp" alt="" width="60" height="60" decoding="async" /> </div> <div class="b--chat_name">Name B</div> <div class="b--chat_body"> <div class="b--chat_deco a--decorator is--skipFlow u--cbox" aria-hidden="true"></div> <div class="b--chat_content l--flow u--cbox"> <p>Lorem ipsum dolor <i>sit amet</i>. ...</p> </div> </div></div>