SPB Git

Repository Public

rating-stars-fluid.html 6.3 KB 149 lines html

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
Files main
Menu

Theme