WEBLEB
Inicio
Editora de código
Iniciar sesión
Pro
Español
English
Français
Español
Plantilla de calificación de estrellas animadas
3,953
code_rating
Abrir en el editor
Publica tu código
15
Recomendado
26 January 2025
Un código de Redllowge
18 December 2025
Arena del rey del coche
18 December 2025
Código fuente HTML del juego Divide By 1
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"); }); } }