ストーリーズ風リング
未読のアバターだけ回転するグラデーションリングが輝き、既読になるとリングは静かなグレーへ変わります。クリックすると即座に既読状態へ切り替わります。
ライブデモ
コード
HTML
<!-- ストーリーズ風リング: 未読は回転するグラデーションリングが輝き、既読はグレーに。クリックで既読化 -->
<ul class="stories" aria-label="ストーリーズ一覧">
<li>
<button type="button" class="story" data-read="false">
<span class="story__ring"><img class="story__avatar" src="https://picsum.photos/id/64/200/200" alt="つむぎのストーリー" width="58" height="58"></span>
<span class="story__name">つむぎ</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="false">
<span class="story__ring"><img class="story__avatar" src="https://picsum.photos/id/91/200/200" alt="陽菜のストーリー" width="58" height="58"></span>
<span class="story__name">陽菜</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="true">
<span class="story__ring"><img class="story__avatar" src="https://picsum.photos/id/1027/200/200" alt="蓮のストーリー" width="58" height="58"></span>
<span class="story__name">蓮</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="false">
<span class="story__ring"><span class="story__avatar story__avatar--letter" aria-hidden="true">碧</span></span>
<span class="story__name">碧</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="true">
<span class="story__ring"><span class="story__avatar story__avatar--letter" aria-hidden="true">澪</span></span>
<span class="story__name">澪</span>
</button>
</li>
</ul>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
padding: 28px;
font-family: "Hiragino Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
background:
radial-gradient(circle at 82% 18%, rgba(236, 72, 153, .14) 0%, transparent 42%),
radial-gradient(circle at 12% 88%, rgba(250, 204, 21, .1) 0%, transparent 45%),
#0c0c10;
color: #f3f0eb;
}
.stories {
list-style: none;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 13px;
margin: 0;
padding: 24px 18px;
max-width: 480px;
border-radius: 22px;
background: rgba(255, 255, 255, .04);
border: 1px solid rgba(255, 255, 255, .08);
box-shadow: 0 26px 60px -28px rgba(0, 0, 0, .75);
}
/* ボタンをリセットしつつ、内側の要素はgridで縦積み */
.story {
all: unset;
cursor: pointer;
display: grid;
justify-items: center;
gap: 8px;
padding: 4px;
border-radius: 14px;
}
.story:focus-visible {
outline: 2px solid #fff;
outline-offset: 3px;
}
.story__ring {
position: relative;
display: inline-flex;
width: 64px;
height: 64px;
border-radius: 50%;
padding: 3px;
}
/* 未読: 虹色グラデーションのリングがゆっくり回転して「生きている」ことを示す */
.story__ring::before {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
background: conic-gradient(from 0deg, #f59e0b, #ec4899, #8b5cf6, #38bdf8, #f59e0b);
animation: story-spin 3.2s linear infinite;
}
/* 既読: リングは静かなグレーに変わり、回転も止まる */
.story[data-read="true"] .story__ring::before {
background: #4b5563;
animation: none;
}
.story__avatar {
position: relative;
z-index: 1;
width: 58px;
height: 58px;
border-radius: 50%;
object-fit: cover;
display: block;
border: 3px solid #131317;
}
.story__avatar--letter {
display: grid;
place-items: center;
background: linear-gradient(155deg, #38bdf8, #6366f1);
color: #fff;
font-weight: 700;
font-size: 18px;
}
.story:hover .story__avatar {
filter: brightness(1.08);
}
.story__name {
font-size: 11.5px;
letter-spacing: .02em;
color: rgba(243, 240, 235, .65);
}
.story[data-read="true"] .story__name {
color: rgba(243, 240, 235, .4);
}
@keyframes story-spin {
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.story__ring::before { animation: none; }
}
@media (max-width: 480px) {
.stories { gap: 14px; padding: 20px 16px; }
.story__ring { width: 56px; height: 56px; }
.story__avatar { width: 50px; height: 50px; }
}
JavaScript
// ストーリーズ風リング: クリックしたアバターを既読状態にする(data-read属性を切り替えるだけでCSSが見た目を変える)
(() => {
const stories = document.querySelectorAll('.story');
if (!stories.length) return; // null安全
stories.forEach((btn) => {
btn.addEventListener('click', () => {
btn.dataset.read = 'true';
});
});
})();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「ストーリーズ風リング」の効果を追加してください。
# 追加してほしい効果
ストーリーズ風リング(バッジ & アバター)
未読のアバターだけ回転するグラデーションリングが輝き、既読になるとリングは静かなグレーへ変わります。クリックすると即座に既読状態へ切り替わります。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- ストーリーズ風リング: 未読は回転するグラデーションリングが輝き、既読はグレーに。クリックで既読化 -->
<ul class="stories" aria-label="ストーリーズ一覧">
<li>
<button type="button" class="story" data-read="false">
<span class="story__ring"><img class="story__avatar" src="https://picsum.photos/id/64/200/200" alt="つむぎのストーリー" width="58" height="58"></span>
<span class="story__name">つむぎ</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="false">
<span class="story__ring"><img class="story__avatar" src="https://picsum.photos/id/91/200/200" alt="陽菜のストーリー" width="58" height="58"></span>
<span class="story__name">陽菜</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="true">
<span class="story__ring"><img class="story__avatar" src="https://picsum.photos/id/1027/200/200" alt="蓮のストーリー" width="58" height="58"></span>
<span class="story__name">蓮</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="false">
<span class="story__ring"><span class="story__avatar story__avatar--letter" aria-hidden="true">碧</span></span>
<span class="story__name">碧</span>
</button>
</li>
<li>
<button type="button" class="story" data-read="true">
<span class="story__ring"><span class="story__avatar story__avatar--letter" aria-hidden="true">澪</span></span>
<span class="story__name">澪</span>
</button>
</li>
</ul>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
padding: 28px;
font-family: "Hiragino Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
background:
radial-gradient(circle at 82% 18%, rgba(236, 72, 153, .14) 0%, transparent 42%),
radial-gradient(circle at 12% 88%, rgba(250, 204, 21, .1) 0%, transparent 45%),
#0c0c10;
color: #f3f0eb;
}
.stories {
list-style: none;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 13px;
margin: 0;
padding: 24px 18px;
max-width: 480px;
border-radius: 22px;
background: rgba(255, 255, 255, .04);
border: 1px solid rgba(255, 255, 255, .08);
box-shadow: 0 26px 60px -28px rgba(0, 0, 0, .75);
}
/* ボタンをリセットしつつ、内側の要素はgridで縦積み */
.story {
all: unset;
cursor: pointer;
display: grid;
justify-items: center;
gap: 8px;
padding: 4px;
border-radius: 14px;
}
.story:focus-visible {
outline: 2px solid #fff;
outline-offset: 3px;
}
.story__ring {
position: relative;
display: inline-flex;
width: 64px;
height: 64px;
border-radius: 50%;
padding: 3px;
}
/* 未読: 虹色グラデーションのリングがゆっくり回転して「生きている」ことを示す */
.story__ring::before {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
background: conic-gradient(from 0deg, #f59e0b, #ec4899, #8b5cf6, #38bdf8, #f59e0b);
animation: story-spin 3.2s linear infinite;
}
/* 既読: リングは静かなグレーに変わり、回転も止まる */
.story[data-read="true"] .story__ring::before {
background: #4b5563;
animation: none;
}
.story__avatar {
position: relative;
z-index: 1;
width: 58px;
height: 58px;
border-radius: 50%;
object-fit: cover;
display: block;
border: 3px solid #131317;
}
.story__avatar--letter {
display: grid;
place-items: center;
background: linear-gradient(155deg, #38bdf8, #6366f1);
color: #fff;
font-weight: 700;
font-size: 18px;
}
.story:hover .story__avatar {
filter: brightness(1.08);
}
.story__name {
font-size: 11.5px;
letter-spacing: .02em;
color: rgba(243, 240, 235, .65);
}
.story[data-read="true"] .story__name {
color: rgba(243, 240, 235, .4);
}
@keyframes story-spin {
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.story__ring::before { animation: none; }
}
@media (max-width: 480px) {
.stories { gap: 14px; padding: 20px 16px; }
.story__ring { width: 56px; height: 56px; }
.story__avatar { width: 50px; height: 50px; }
}
【JavaScript】
// ストーリーズ風リング: クリックしたアバターを既読状態にする(data-read属性を切り替えるだけでCSSが見た目を変える)
(() => {
const stories = document.querySelectorAll('.story');
if (!stories.length) return; // null安全
stories.forEach((btn) => {
btn.addEventListener('click', () => {
btn.dataset.read = 'true';
});
});
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。