TGViewer
WebDev+ | Веб-разработка WebDev+ | Веб-разработка @webdev_plus · 7.9K subscribers
Post #1157 1.11K
Хватит использовать библиотеки для рейтингов. Я сделал компонент звездочного рейтинга только на CSS с поддержкой половинок звезд всего в 60 строк. Без JavaScript. Полностью доступный. С плавным hover.

Я посмотрел существующие pure-CSS решения и почти везде одни и те же проблемы.
Либо нет поддержки половинок, либо завязка на FontAwesome, либо дерганый и нестабильный hover.

В итоге я сделал свое решение, используя только radio input’ы, label’ы и SVG-маски.

Ключевая идея упирается в ограничение CSS:
он умеет выбирать только элементы, идущие после текущего (через ~).

А в рейтинге звезд нужно подсвечивать звезды до той, на которую навели курсор.

Решение простое: переворачиваем DOM и визуально отражаем его через flex-direction: row-reverse.

.star-rating {
display: inline-flex;
flex-direction: row-reverse;
justify-content: flex-end;
}


Порядок в DOM: 5★ → 0.5★
Визуальный порядок: 0.5★ → 5★

Теперь ~ выбирает визуально предыдущие звезды.

Для половинок я разделил каждую звезду на два <label> — левую и правую половину.
Каждый label использует SVG-маску половинки звезды.

nth-of-type(odd) — правая половина
nth-of-type(even) — левая половина

Почему маска, а не background-image?

У background-image нельзя динамически менять цвет заливки SVG.
А mask работает как трафарет — сквозь него просто просвечивает background-color.

В итоге hover — это просто смена цвета.

/* Подсветка при наведении */
label:hover,
label:hover ~ label {
background-color: goldenrod;
}

/* Подсветка выбранного */
input:checked ~ label {
background-color: gold;
}


Простые селекторы. Никаких JS-обработчиков.

Отступы между звездами ломают UX hover’а — появляются «мертвые зоны», где ничего не подсвечивается.
Фикс такой: расширяем ширину label, но оставляем mask-size прежним.
Зазор виден визуально, но зона hover остается непрерывной.

Radio-кнопки визуально скрыты, но остаются в DOM.
Скринридеры видят:

* нормальные radio input’ы
* label’ы с aria-label вроде 3 1/2 stars
* полноценную навигацию с клавиатуры

CSS-only — это не компромисс по доступности.

@WebDev_Plus
More from @webdev_plus
  1. Oct 8, 2026Как работают очереди в контексте HTTP-запросов Разбираются основные стратегии очередей: FI…
  2. Oct 7, 2026Разработчики Next.js: добавьте эти 4 строки в ваш .vscode/settings.json, чтобы сразу прока…
  3. Oct 7, 2026Полезное расширение для Chrome «Responsive Viewer» Помогает веб-разработчикам и дизайнерам…
  4. Oct 6, 2026Laravel / PHP: как предпочитаете отправлять письма — описывать их прямо в месте вызова или…
  5. Oct 6, 2026Этот HTML-косяк непростителен. Не использовать атрибут inputmode в элементах input — серьё…
  6. Oct 5, 2026Работает!? Не трогай 🎯
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →