Frontend Development 10 min read

How to Build a Pure CSS Star Rating with input type="range"

This article walks through creating a fully CSS‑based star rating component using the HTML input type="range", exploring its shadow‑DOM structure, applying CSS masks, handling cross‑browser quirks, and providing complete code snippets for a flexible, lightweight solution.

Yuewen Frontend Team
Yuewen Frontend Team
Yuewen Frontend Team
How to Build a Pure CSS Star Rating with input type="range"

Why use CSS to implement a star rating?

Star rating is a common UI need. The author originally used JavaScript, but a colleague suggested that type="range" could achieve it, sparking further exploration.

How to use type="range" for star rating

Is input type="range" just a simple element?

It is a component that contains a shadow DOM . By enabling "Show user agent shadow DOM" in Chrome's settings, you can see the hidden shadow-root and its internal DOM nodes.

Inspecting the element reveals that the range input actually contains other elements that are normally hidden.

Customizing the style of input type="range"

Using the browser's inspector you can locate the internal DOM and modify its styles.

Two pseudo‑elements are key:

::-webkit-slider-runnable-track : styles the track (the area the thumb slides on).

::-webkit-slider-thumb : styles the thumb itself (effective in WebKit/Blink browsers).

To turn the track into stars, a CSS mask is applied. The mask uses an SVG star pattern that repeats across the track.

<code>input[type="range"] {
    -webkit-appearance: none; /* remove default styling */
    width: 100px;
    margin: 0;
    outline: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
    background: coral; /* star color */
    height: 20px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg width='12' height='11' viewBox='0 0 12 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 0l1.693 3.67 4.013.476L8.74 6.89l.788 3.964L6 8.88l-3.527 1.974.788-3.964L.294 4.146l4.013-.476L6 0z' fill='%23F67600'/%3E%3C/svg%3E");
    -webkit-mask-size: 20px;
    -webkit-mask-repeat: repeat-x;
}
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 0;
    height: 100%;
    box-shadow: 999px 0 0 999px #E8EAED; /* hide thumb */
}
</code>

This pure‑CSS solution produces a star rating where the star colors change with the background.

Compatibility considerations

The approach works in browsers that support input type="range" and CSS masks (WebKit/Blink). In Firefox the mask is not supported, so a fallback using ::-moz-range-track and ::-moz-range-progress is added.

<code>input[type=range] {
    -webkit-mask: url("data:image/svg+xml,%3Csvg width='12' height='11' viewBox='0 0 12 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 0l1.693 3.67 4.013.476L8.74 6.89l.788 3.964L6 8.88l-3.527 1.974.788-3.964L.294 4.146l4.013-.476L6 0z' fill='%23F67600'/%3E%3C/svg%3E");
    -webkit-mask-size: 20px;
    -webkit-mask-repeat: repeat-x;
    height: 20px;
}
input[type=range]::-moz-range-track {
    background: #E8EAED;
    height: inherit;
}
input[type=range]::-moz-range-progress {
    background: coral;
    height: inherit;
}
input[type=range]::-moz-range-thumb {
    width: 0;
    opacity: 0;
}
</code>

Testing shows the component fails in Firefox without the Mozilla‑specific rules.

Conclusion

The pure CSS star rating using input type="range" is lightweight, flexible, and can be extended for different star counts or rating ranges. The author plans to integrate it into the open‑source LuLu UI library.

References

张老师 – https://www.zhangxinxu.com/wordpress/

js 实现评分组件 – https://sunseekers.github.io/2020/12/12/star/

同事文彬 – https://github.com/XboxYan

在线 demo type=range 实现评星功能 – https://codepen.io/qingchuang/pen/jOMmQab

::-webkit-slider-runnable-track – https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-slider-runnable-track

::-webkit-slider-thumb – https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-slider-thumb

CSS遮罩 CSS3 mask/masks 详细介绍 – https://www.zhangxinxu.com/wordpress/2017/11/css-css3-mask-masks/

兼容火狐浏览器,谷歌下失效 – https://codepen.io/qingchuang/pen/VwKVJYL

LuLu UI – https://github.com/yued-fe/lulu

Frontendweb developmentCSSmaskcross-browserinput rangestar rating
Yuewen Frontend Team
Written by

Yuewen Frontend Team

Click follow to learn the latest frontend insights in the cultural content industry. We welcome you to join us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.