Repository Public
1<!--2 ============================================================3 SVGarden — https://www.svgarden.dev4 Author : Simon-Pierre Boucher5 Contact: contact@spboucher.ai6 File : snippets/interactive/rating-stars-fluid.html7 Desc : Five-star rating with fluid fill and pop, radio-powered, zero JS8 ============================================================9-->10<!--svgarden11title: Fluid star rating12slug: rating-stars-fluid13category: interactive14tags: [interactive, rating, stars, radio, form]15difficulty: advanced16techniques: [radio-group, "row-reverse", sibling-combinator, ":checked", "@keyframes"]17how_it_works: >18 The rating is a plain radio group — the browser remembers which star is19 chosen, CSS just paints it. The classic trick is DOM order: stars are written20 5→1 and the fieldset is flex row-reverse, so the general sibling combinator21 (which only reaches *forward* in the DOM) selects the stars that appear to22 the *left* of the checked one, and :checked ~ label fills exactly the right23 amount. The freshly picked star gets its own + selector, which newly matches24 on selection and therefore restarts a pop keyframe (springy scale plus a25 fading dotted ring). Radios stay focusable, so arrow keys change the rating26 natively.27customizable:28 - { var: "--sg-color", label: "Star color", type: color, default: "#EFBB33" }29 - { var: "--sg-size", label: "Star size", type: range, min: 20, max: 64, default: 36, unit: px }30 - { var: "--sg-duration", label: "Pop speed", type: range, min: 0.2, max: 1.2, step: 0.05, default: 0.5, unit: s }31created: 2026-08-1032-->33<fieldset class="sg-rating-stars-fluid" style="--sg-color:#EFBB33; --sg-size:36px; --sg-duration:0.5s;">34 <legend class="sg-rating-stars-fluid-sr">Rate this from one to five stars</legend>35 <input class="sg-rating-stars-fluid-in" type="radio" name="sg-rating-stars-fluid" id="sg-rating-stars-fluid-5" value="5" />36 <label class="sg-rating-stars-fluid-star" for="sg-rating-stars-fluid-5" aria-label="5 stars">37 <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">38 <circle class="sg-rating-stars-fluid-pop" cx="12" cy="12" r="10" />39 <polygon points="12,2.5 14.9,9 22,9.7 16.7,14.5 18.2,21.5 12,17.8 5.8,21.5 7.3,14.5 2,9.7 9.1,9" />40 </svg>41 </label>42 <input class="sg-rating-stars-fluid-in" type="radio" name="sg-rating-stars-fluid" id="sg-rating-stars-fluid-4" value="4" />43 <label class="sg-rating-stars-fluid-star" for="sg-rating-stars-fluid-4" aria-label="4 stars">44 <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">45 <circle class="sg-rating-stars-fluid-pop" cx="12" cy="12" r="10" />46 <polygon points="12,2.5 14.9,9 22,9.7 16.7,14.5 18.2,21.5 12,17.8 5.8,21.5 7.3,14.5 2,9.7 9.1,9" />47 </svg>48 </label>49 <input class="sg-rating-stars-fluid-in" type="radio" name="sg-rating-stars-fluid" id="sg-rating-stars-fluid-3" value="3" />50 <label class="sg-rating-stars-fluid-star" for="sg-rating-stars-fluid-3" aria-label="3 stars">51 <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">52 <circle class="sg-rating-stars-fluid-pop" cx="12" cy="12" r="10" />53 <polygon points="12,2.5 14.9,9 22,9.7 16.7,14.5 18.2,21.5 12,17.8 5.8,21.5 7.3,14.5 2,9.7 9.1,9" />54 </svg>55 </label>56 <input class="sg-rating-stars-fluid-in" type="radio" name="sg-rating-stars-fluid" id="sg-rating-stars-fluid-2" value="2" />57 <label class="sg-rating-stars-fluid-star" for="sg-rating-stars-fluid-2" aria-label="2 stars">58 <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">59 <circle class="sg-rating-stars-fluid-pop" cx="12" cy="12" r="10" />60 <polygon points="12,2.5 14.9,9 22,9.7 16.7,14.5 18.2,21.5 12,17.8 5.8,21.5 7.3,14.5 2,9.7 9.1,9" />61 </svg>62 </label>63 <input class="sg-rating-stars-fluid-in" type="radio" name="sg-rating-stars-fluid" id="sg-rating-stars-fluid-1" value="1" />64 <label class="sg-rating-stars-fluid-star" for="sg-rating-stars-fluid-1" aria-label="1 star">65 <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">66 <circle class="sg-rating-stars-fluid-pop" cx="12" cy="12" r="10" />67 <polygon points="12,2.5 14.9,9 22,9.7 16.7,14.5 18.2,21.5 12,17.8 5.8,21.5 7.3,14.5 2,9.7 9.1,9" />68 </svg>69 </label>70</fieldset>71<style>72 .sg-rating-stars-fluid {73 display: flex;74 flex-direction: row-reverse;75 justify-content: center;76 gap: 0.3rem;77 border: 0;78 margin: 0;79 padding: 0;80 }81 .sg-rating-stars-fluid-sr {82 position: absolute;83 width: 1px;84 height: 1px;85 overflow: hidden;86 clip-path: inset(50%);87 white-space: nowrap;88 }89 .sg-rating-stars-fluid-in {90 position: absolute;91 opacity: 0;92 width: 1px;93 height: 1px;94 }95 .sg-rating-stars-fluid-star {96 width: var(--sg-size);97 cursor: pointer;98 }99 .sg-rating-stars-fluid-star svg {100 display: block;101 width: 100%;102 overflow: visible;103 }104 .sg-rating-stars-fluid-star polygon {105 fill: transparent;106 stroke: rgba(128, 128, 128, 0.55);107 stroke-width: 1.4;108 stroke-linejoin: round;109 transform-box: fill-box;110 transform-origin: center;111 transition: fill 0.15s ease, stroke 0.15s ease;112 }113 .sg-rating-stars-fluid-star:hover polygon,114 .sg-rating-stars-fluid-star:hover ~ .sg-rating-stars-fluid-star polygon,115 .sg-rating-stars-fluid-in:checked + .sg-rating-stars-fluid-star polygon,116 .sg-rating-stars-fluid-in:checked ~ .sg-rating-stars-fluid-star polygon {117 fill: var(--sg-color);118 stroke: var(--sg-color);119 }120 .sg-rating-stars-fluid-in:checked + .sg-rating-stars-fluid-star polygon {121 animation: sg-rating-stars-fluid-spring var(--sg-duration) cubic-bezier(0.3, 1.8, 0.5, 1);122 }123 .sg-rating-stars-fluid-pop {124 fill: none;125 stroke: var(--sg-color);126 stroke-width: 1.2;127 stroke-dasharray: 1.5 5;128 opacity: 0;129 transform-box: fill-box;130 transform-origin: center;131 }132 .sg-rating-stars-fluid-in:checked + .sg-rating-stars-fluid-star .sg-rating-stars-fluid-pop {133 animation: sg-rating-stars-fluid-burst var(--sg-duration) ease-out;134 }135 .sg-rating-stars-fluid-in:focus-visible + .sg-rating-stars-fluid-star {136 outline: 2px solid var(--sg-color);137 outline-offset: 2px;138 border-radius: 6px;139 }140 @keyframes sg-rating-stars-fluid-spring {141 0% { transform: scale(0.6); }142 100% { transform: scale(1); }143 }144 @keyframes sg-rating-stars-fluid-burst {145 0% { opacity: 0.9; transform: scale(0.5); }146 100% { opacity: 0; transform: scale(1.5); }147 }148</style>149