星評価入力
ホバーで星がプレビュー表示され、クリックで評価が確定する5段階の星評価入力。選択後は「満足」などの評価ラベルが表示されます。
ライブデモ
コード
HTML
<div class="stage">
<div class="sr-card">
<p class="sr-question">今回のサービスに満足しましたか?</p>
<div class="sr-stars" role="radiogroup" aria-label="評価(5段階)" id="sr-stars">
<label class="sr-star" data-value="5">
<input type="radio" name="sr-rating" value="5" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">5:大変満足</span>
</label>
<label class="sr-star" data-value="4">
<input type="radio" name="sr-rating" value="4" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">4:満足</span>
</label>
<label class="sr-star" data-value="3">
<input type="radio" name="sr-rating" value="3" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">3:普通</span>
</label>
<label class="sr-star" data-value="2">
<input type="radio" name="sr-rating" value="2" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">2:やや不満</span>
</label>
<label class="sr-star" data-value="1">
<input type="radio" name="sr-rating" value="1" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">1:不満</span>
</label>
</div>
<p class="sr-feedback" id="sr-feedback" role="status">星を選択してください</p>
</div>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
padding: 24px;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
/* 上品なローズ系グラデ背景 */
background: linear-gradient(135deg, #fff1f2 0%, #ffe4e6 50%, #fce7f3 100%);
color: #1f2937;
}
.stage { width: 100%; display: grid; place-items: center; }
.sr-card {
width: min(340px, 92vw);
padding: 32px 28px 26px;
background: #fff;
border-radius: 20px;
box-shadow: 0 24px 56px -26px rgba(190, 24, 93, 0.3);
text-align: center;
}
.sr-question {
margin: 0 0 20px;
font-size: 0.98rem;
font-weight: 600;
color: #4a1d2a;
}
/* DOMは5→1の逆順。row-reverseで見た目を1→5に戻し、
後続セレクタで「選択/ホバーした星までを塗る」古典テクニックを使う */
.sr-stars {
display: flex;
flex-direction: row-reverse;
justify-content: center;
gap: 6px;
}
.sr-star {
position: relative;
cursor: pointer;
line-height: 1;
}
.sr-input {
position: absolute;
opacity: 0;
width: 1px;
height: 1px;
}
.sr-icon {
display: block;
font-size: 2.1rem;
color: #e2d4d8;
transition: color 0.16s ease, transform 0.12s ease;
}
/* ホバー中:ホバー星+それより手前(DOM上で後ろ)の星も塗る */
.sr-star:hover .sr-icon,
.sr-star:hover ~ .sr-star .sr-icon {
color: #f59e0b;
}
.sr-star:hover .sr-icon { transform: scale(1.12); }
/* 確定済み:チェックされた星+それより手前の星も塗る */
.sr-star:has(.sr-input:checked) .sr-icon,
.sr-star:has(.sr-input:checked) ~ .sr-star .sr-icon {
color: #f59e0b;
}
.sr-input:focus-visible ~ .sr-icon {
outline: none;
box-shadow: 0 0 0 3px rgba(244, 63, 94, 0.35);
border-radius: 6px;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.sr-feedback {
margin: 18px 0 0;
font-size: 0.86rem;
font-weight: 600;
color: #9d174d;
transition: transform 0.18s ease;
}
.sr-feedback.is-confirmed { animation: sr-pop 0.28s ease; }
@keyframes sr-pop {
0% { transform: scale(0.9); }
60% { transform: scale(1.06); }
100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
.sr-icon, .sr-feedback { transition: none; }
.sr-feedback.is-confirmed { animation: none; }
}
JavaScript
// 星評価入力:クリックで確定した値に応じて評価ラベルを表示する
(function () {
var group = document.getElementById("sr-stars");
var feedback = document.getElementById("sr-feedback");
if (!group || !feedback) return;
var labels = {
1: "不満",
2: "やや不満",
3: "普通",
4: "満足",
5: "大変満足",
};
group.addEventListener("change", function (e) {
var target = e.target;
if (!target || !target.classList || !target.classList.contains("sr-input")) return;
var value = parseInt(target.value, 10);
var label = labels[value] || "";
feedback.textContent = "評価:" + label + "(" + value + "/5)";
feedback.classList.remove("is-confirmed");
void feedback.offsetWidth;
feedback.classList.add("is-confirmed");
});
})();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「星評価入力」の効果を追加してください。
# 追加してほしい効果
星評価入力(フォーム & 入力)
ホバーで星がプレビュー表示され、クリックで評価が確定する5段階の星評価入力。選択後は「満足」などの評価ラベルが表示されます。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<div class="stage">
<div class="sr-card">
<p class="sr-question">今回のサービスに満足しましたか?</p>
<div class="sr-stars" role="radiogroup" aria-label="評価(5段階)" id="sr-stars">
<label class="sr-star" data-value="5">
<input type="radio" name="sr-rating" value="5" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">5:大変満足</span>
</label>
<label class="sr-star" data-value="4">
<input type="radio" name="sr-rating" value="4" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">4:満足</span>
</label>
<label class="sr-star" data-value="3">
<input type="radio" name="sr-rating" value="3" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">3:普通</span>
</label>
<label class="sr-star" data-value="2">
<input type="radio" name="sr-rating" value="2" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">2:やや不満</span>
</label>
<label class="sr-star" data-value="1">
<input type="radio" name="sr-rating" value="1" class="sr-input">
<span class="sr-icon" aria-hidden="true">★</span>
<span class="sr-only">1:不満</span>
</label>
</div>
<p class="sr-feedback" id="sr-feedback" role="status">星を選択してください</p>
</div>
</div>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
padding: 24px;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
/* 上品なローズ系グラデ背景 */
background: linear-gradient(135deg, #fff1f2 0%, #ffe4e6 50%, #fce7f3 100%);
color: #1f2937;
}
.stage { width: 100%; display: grid; place-items: center; }
.sr-card {
width: min(340px, 92vw);
padding: 32px 28px 26px;
background: #fff;
border-radius: 20px;
box-shadow: 0 24px 56px -26px rgba(190, 24, 93, 0.3);
text-align: center;
}
.sr-question {
margin: 0 0 20px;
font-size: 0.98rem;
font-weight: 600;
color: #4a1d2a;
}
/* DOMは5→1の逆順。row-reverseで見た目を1→5に戻し、
後続セレクタで「選択/ホバーした星までを塗る」古典テクニックを使う */
.sr-stars {
display: flex;
flex-direction: row-reverse;
justify-content: center;
gap: 6px;
}
.sr-star {
position: relative;
cursor: pointer;
line-height: 1;
}
.sr-input {
position: absolute;
opacity: 0;
width: 1px;
height: 1px;
}
.sr-icon {
display: block;
font-size: 2.1rem;
color: #e2d4d8;
transition: color 0.16s ease, transform 0.12s ease;
}
/* ホバー中:ホバー星+それより手前(DOM上で後ろ)の星も塗る */
.sr-star:hover .sr-icon,
.sr-star:hover ~ .sr-star .sr-icon {
color: #f59e0b;
}
.sr-star:hover .sr-icon { transform: scale(1.12); }
/* 確定済み:チェックされた星+それより手前の星も塗る */
.sr-star:has(.sr-input:checked) .sr-icon,
.sr-star:has(.sr-input:checked) ~ .sr-star .sr-icon {
color: #f59e0b;
}
.sr-input:focus-visible ~ .sr-icon {
outline: none;
box-shadow: 0 0 0 3px rgba(244, 63, 94, 0.35);
border-radius: 6px;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.sr-feedback {
margin: 18px 0 0;
font-size: 0.86rem;
font-weight: 600;
color: #9d174d;
transition: transform 0.18s ease;
}
.sr-feedback.is-confirmed { animation: sr-pop 0.28s ease; }
@keyframes sr-pop {
0% { transform: scale(0.9); }
60% { transform: scale(1.06); }
100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
.sr-icon, .sr-feedback { transition: none; }
.sr-feedback.is-confirmed { animation: none; }
}
【JavaScript】
// 星評価入力:クリックで確定した値に応じて評価ラベルを表示する
(function () {
var group = document.getElementById("sr-stars");
var feedback = document.getElementById("sr-feedback");
if (!group || !feedback) return;
var labels = {
1: "不満",
2: "やや不満",
3: "普通",
4: "満足",
5: "大変満足",
};
group.addEventListener("change", function (e) {
var target = e.target;
if (!target || !target.classList || !target.classList.contains("sr-input")) return;
var value = parseInt(target.value, 10);
var label = labels[value] || "";
feedback.textContent = "評価:" + label + "(" + value + "/5)";
feedback.classList.remove("is-confirmed");
void feedback.offsetWidth;
feedback.classList.add("is-confirmed");
});
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。