WEBLEB
Accueil
Éditeur
Connexion
Pro
Français
English
Français
Español
Português
Deutsch
Italiano
हिंदी
Modèle de notation des étoiles animées
3206
code_rating
Ouvrir dans l'éditeur
Publiez votre code
Recommandé
18 October 2025
Bouton HTML avec effet de survol (WEBLEB)
13 June 2025
Un code de Metehan
18 February 2024
Générateur de citations aléatoires avec votre nom
HTML
Copy
Animated Stars Rating
1 star—Terrible
2 stars—Bad
3 stars—OK
4 stars—Good
5 stars—Excellent
Terrible
Bad
OK
Good
Excellent
CSS
Copy
* { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --bg: #e3e4e8; --fg: #17181c; --primary: #255ff4; --yellow: #f4a825; --yellow-t: rgba(244, 168, 37, 0); --bezier: cubic-bezier(0.42,0,0.58,1); --trans-dur: 0.3s; font-size: calc(24px + (30 - 24) * (100vw - 320px) / (1280 - 320)); } body { background-color: var(--bg); color: var(--fg); font: 1em/1.5 "DM Sans", sans-serif; display: flex; height: 100vh; transition: background-color var(--trans-dur), color var(--trans-dur); } .rating { margin: auto; } .rating__display { font-size: 1em; font-weight: 500; min-height: 1.25em; position: absolute; top: 100%; width: 100%; text-align: center; } .rating__stars { display: flex; padding-bottom: 0.375em; position: relative; } .rating__star { display: block; overflow: visible; pointer-events: none; width: 2em; height: 2em; } .rating__star-ring, .rating__star-fill, .rating__star-line, .rating__star-stroke { animation-duration: 1s; animation-timing-function: ease-in-out; animation-fill-mode: forwards; } .rating__star-ring, .rating__star-fill, .rating__star-line { stroke: var(--yellow); } .rating__star-fill { fill: var(--yellow); transform: scale(0); transition: fill var(--trans-dur) var(--bezier), transform var(--trans-dur) var(--bezier); } .rating__star-line { stroke-dasharray: 12 13; stroke-dashoffset: -13; } .rating__star-stroke { stroke: #c7cad1; transition: stroke var(--trans-dur); } .rating__label { cursor: pointer; padding: 0.125em; } .rating__label--delay1 .rating__star-ring, .rating__label--delay1 .rating__star-fill, .rating__label--delay1 .rating__star-line, .rating__label--delay1 .rating__star-stroke { animation-delay: 0.05s; } .rating__label--delay2 .rating__star-ring, .rating__label--delay2 .rating__star-fill, .rating__label--delay2 .rating__star-line, .rating__label--delay2 .rating__star-stroke { animation-delay: 0.1s; } .rating__label--delay3 .rating__star-ring, .rating__label--delay3 .rating__star-fill, .rating__label--delay3 .rating__star-line, .rating__label--delay3 .rating__star-stroke { animation-delay: 0.15s; } .rating__label--delay4 .rating__star-ring, .rating__label--delay4 .rating__star-fill, .rating__label--delay4 .rating__star-line, .rating__label--delay4 .rating__star-stroke { animation-delay: 0.2s; } .rating__input { position: absolute; -webkit-appearance: none; appearance: none; } .rating__input:hover ~ [data-rating]:not([hidden]) { display: none; } .rating__input-1:hover ~ [data-rating="1"][hidden], .rating__input-2:hover ~ [data-rating="2"][hidden], .rating__input-3:hover ~ [data-rating="3"][hidden], .rating__input-4:hover ~ [data-rating="4"][hidden], .rating__input-5:hover ~ [data-rating="5"][hidden], .rating__input:checked:hover ~ [data-rating]:not([hidden]) { display: block; } .rating__input-1:hover ~ .rating__label:first-of-type .rating__star-stroke, .rating__input-2:hover ~ .rating__label:nth-of-type(-n + 2) .rating__star-stroke, .rating__input-3:hover ~ .rating__label:nth-of-type(-n + 3) .rating__star-stroke, .rating__input-4:hover ~ .rating__label:nth-of-type(-n + 4) .rating__star-stroke, .rating__input-5:hover ~ .rating__label:nth-of-type(-n + 5) .rating__star-stroke { stroke: var(--yellow); transform: scale(1); } .rating__input-1:checked ~ .rating__label:first-of-type .rating__star-ring, .rating__input-2:checked ~ .rating__label:nth-of-type(-n + 2) .rating__star-ring, .rating__input-3:checked ~ .rating__label:nth-of-type(-n + 3) .rating__star-ring, .rating__input-4:checked ~ .rating__label:nth-of-type(-n + 4) .rating__star-ring, .rating__input-5:checked ~ .rating__label:nth-of-type(-n + 5) .rating__star-ring { animation-name: starRing; } .rating__input-1:checked ~ .rating__label:first-of-type .rating__star-stroke, .rating__input-2:checked ~ .rating__label:nth-of-type(-n + 2) .rating__star-stroke, .rating__input-3:checked ~ .rating__label:nth-of-type(-n + 3) .rating__star-stroke, .rating__input-4:checked ~ .rating__label:nth-of-type(-n + 4) .rating__star-stroke, .rating__input-5:checked ~ .rating__label:nth-of-type(-n + 5) .rating__star-stroke { animation-name: starStroke; } .rating__input-1:checked ~ .rating__label:first-of-type .rating__star-line, .rating__input-2:checked ~ .rating__label:nth-of-type(-n + 2) .rating__star-line, .rating__input-3:checked ~ .rating__label:nth-of-type(-n + 3) .rating__star-line, .rating__input-4:checked ~ .rating__label:nth-of-type(-n + 4) .rating__star-line, .rating__input-5:checked ~ .rating__label:nth-of-type(-n + 5) .rating__star-line { animation-name: starLine; } .rating__input-1:checked ~ .rating__label:first-of-type .rating__star-fill, .rating__input-2:checked ~ .rating__label:nth-of-type(-n + 2) .rating__star-fill, .rating__input-3:checked ~ .rating__label:nth-of-type(-n + 3) .rating__star-fill, .rating__input-4:checked ~ .rating__label:nth-of-type(-n + 4) .rating__star-fill, .rating__input-5:checked ~ .rating__label:nth-of-type(-n + 5) .rating__star-fill { animation-name: starFill; } .rating__input-1:not(:checked):hover ~ .rating__label:first-of-type .rating__star-fill, .rating__input-2:not(:checked):hover ~ .rating__label:nth-of-type(2) .rating__star-fill, .rating__input-3:not(:checked):hover ~ .rating__label:nth-of-type(3) .rating__star-fill, .rating__input-4:not(:checked):hover ~ .rating__label:nth-of-type(4) .rating__star-fill, .rating__input-5:not(:checked):hover ~ .rating__label:nth-of-type(5) .rating__star-fill { fill: var(--yellow-t); } .rating__sr { clip: rect(1px, 1px, 1px, 1px); overflow: hidden; position: absolute; width: 1px; height: 1px; } @media (prefers-color-scheme: dark) { :root { --bg: #17181c; --fg: #e3e4e8; } .rating { margin: auto; } .rating__star-stroke { stroke: #454954; } } @keyframes starRing { from, 20% { animation-timing-function: ease-in; opacity: 1; r: 8px; stroke-width: 16px; transform: scale(0); } 35% { animation-timing-function: ease-out; opacity: 0.5; r: 8px; stroke-width: 16px; transform: scale(1); } 50%, to { opacity: 0; r: 16px; stroke-width: 0; transform: scale(1); } } @keyframes starFill { from, 40% { animation-timing-function: ease-out; transform: scale(0); } 60% { animation-timing-function: ease-in-out; transform: scale(1.2); } 80% { transform: scale(0.9); } to { transform: scale(1); } } @keyframes starStroke { from { transform: scale(1); } 20%, to { transform: scale(0); } } @keyframes starLine { from, 40% { animation-timing-function: ease-out; stroke-dasharray: 1 23; stroke-dashoffset: 1; } 60%, to { stroke-dasharray: 12 13; stroke-dashoffset: -13; } }
JS
Copy
window.addEventListener("DOMContentLoaded",() => { const starRating = new StarRating("form"); }); class StarRating { constructor(qs) { this.ratings = [ {id: 1, name: "Terrible"}, {id: 2, name: "Bad"}, {id: 3, name: "OK"}, {id: 4, name: "Good"}, {id: 5, name: "Excellent"} ]; this.rating = null; this.el = document.querySelector(qs); this.init(); } init() { this.el?.addEventListener("change",this.updateRating.bind(this)); // stop Firefox from preserving form data between refreshes try { this.el?.reset(); } catch (err) { console.error("Element isn’t a form."); } } updateRating(e) { // clear animation delays Array.from(this.el.querySelectorAll(`[for*="rating"]`)).forEach(el => { el.className = "rating__label"; }); const ratingObject = this.ratings.find(r => r.id === +e.target.value); const prevRatingID = this.rating?.id || 0; let delay = 0; this.rating = ratingObject; this.ratings.forEach(rating => { const { id } = rating; // add the delays const ratingLabel = this.el.querySelector(`[for="rating-${id}"]`); if (id > prevRatingID + 1 && id <= this.rating.id) { ++delay; ratingLabel.classList.add(`rating__label--delay${delay}`); } // hide ratings to not read, show the one to read const ratingTextEl = this.el.querySelector(`[data-rating="${id}"]`); if (this.rating.id !== id) ratingTextEl.setAttribute("hidden",true); else ratingTextEl.removeAttribute("hidden"); }); } }