Initials Avatar
Initials on a colour computed from the name - the same person gets the same colour on every page, with no image involved.
4 個のフレームワーク中級
The two states of "no face yet": a shimmering skeleton while loading, and an SVG glyph for the user with no photo.
<!--
Two states of "no data yet": still loading (shimmer, role="status" so the
wait is announced) and loaded-but-anonymous (an inline SVG glyph - the user
who exists but never uploaded a face).
-->
<span class="avatar-skeleton" role="status">
<span class="avatar-skeleton__shimmer" aria-hidden="true"></span>
<span class="sr-only">Loading user</span>
</span>
<span class="avatar-anon" role="img" aria-label="Unknown user">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor" width="24" height="24">
<path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-3.9 0-7 2.2-7 5v1h14v-1c0-2.8-3.1-5-7-5Z" />
</svg>
</span>| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
loading | boolean | true | true の間はスピナーを表示し、入力をブロックします。 |
name | string | 'Unknown user' | 見出しとして表示されるプラン名。 |
className | string | - | ルート要素にマージされる追加クラス。 |
The two states mean different things and carry different ARIA: while loading, the wrapper is `role="status"` so the wait itself is announced, and the shimmer is only its decoration - which is exactly why `motion-reduce:animate-none` can drop the sweep and lose nothing, the classic skeleton mistake being to make the animation the signal. Once loaded-but-anonymous, it flips to `role="img"` with a name, because "Unknown user" is content, not a wait state. The sweep animates `transform` on a translucent gradient overlay, which stays on the compositor; animating `background-position` would repaint every frame - and the dark theme drops the sweep from `white/60` to `white/10` because a bright flash over a near-black disc reads as a glitch, not a shimmer. The keyframes travel with the component in a `<style>` tag, so there is nothing to add to your Tailwind config. Match the `h-10 w-10` to whatever avatar the skeleton stands in for - a skeleton that is 2px off from its content causes the exact layout shift it exists to prevent.