TOP code CSS xếp hạng sao (Star Rating) đẹp cho website

rating css 700 size 300x0 znd

Xếp hạng sao (Star Rating) trong các bài viết được tính là thang xếp hạng tiêu chuẩn cho nội dung từng bài viết trên website. Tính năng xếp hạng này bạn có thể thấy trên rất nhiều website – và chính trên QuanTriMang cũng có.

Xếp hạng sao thông thường sử dụng số lượng ngôi sao là 5 để đánh giá các mức độ, có thể tương ứng: Không được (1 sao), Tạm được (2 sao), Bình thường (3 sao), Hay (4 sao) và Rất hay (5 sao). Có một số website sử dụng tiêu chuẩn 10 sao để đánh giá nhưng không phổ biến lắm.

Trong bài viết này, tôi sẽ chia sẻ một số bộ code css về star rating để bạn có thể thử nghiệm hệ thống vote sao trên website của mình.

1. Code xếp hạng sao kèm emotion

Code xếp hạng sao kèm emotion

Link xem thử: Demo                                 Code:   HTML/CSS

HTML

<div class="container">
  <div class="feedback">
    <div class="rating">
      <input type="radio" name="rating" id="rating-5">
      <label for="rating-5"></label>
      <input type="radio" name="rating" id="rating-4">
      <label for="rating-4"></label>
      <input type="radio" name="rating" id="rating-3">
      <label for="rating-3"></label>
      <input type="radio" name="rating" id="rating-2">
      <label for="rating-2"></label>
      <input type="radio" name="rating" id="rating-1">
      <label for="rating-1"></label>
      <div class="emoji-wrapper">
        <div class="emoji">
          <svg class="rating-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <circle cx="256" cy="256" r="256" fill="#ffd93b"/>
          <path d="M512 256c0 141.44-114.64 256-256 256-80.48 0-152.32-37.12-199.28-95.28 43.92 35.52 99.84 56.72 160.72 56.72 141.36 0 256-114.56 256-256 0-60.88-21.2-116.8-56.72-160.72C474.8 103.68 512 175.52 512 256z" fill="#f4c534"/>
          <ellipse transform="scale(-1) rotate(31.21 715.433 -595.455)" cx="166.318" cy="199.829" rx="56.146" ry="56.13" fill="#fff"/>
          <ellipse transform="rotate(-148.804 180.87 175.82)" cx="180.871" cy="175.822" rx="28.048" ry="28.08" fill="#3e4347"/>
          <ellipse transform="rotate(-113.778 194.434 165.995)" cx="194.433" cy="165.993" rx="8.016" ry="5.296" fill="#5a5f63"/>
          <ellipse transform="scale(-1) rotate(31.21 715.397 -1237.664)" cx="345.695" cy="199.819" rx="56.146" ry="56.13" fill="#fff"/>
          <ellipse transform="rotate(-148.804 360.25 175.837)" cx="360.252" cy="175.84" rx="28.048" ry="28.08" fill="#3e4347"/>
          <ellipse transform="scale(-1) rotate(66.227 254.508 -573.138)" cx="373.794" cy="165.987" rx="8.016" ry="5.296" fill="#5a5f63"/>
          <path d="M370.56 344.4c0 7.696-6.224 13.92-13.92 13.92H155.36c-7.616 0-13.92-6.224-13.92-13.92s6.304-13.92 13.92-13.92h201.296c7.696.016 13.904 6.224 13.904 13.92z" fill="#3e4347"/>
        </svg>
          <svg class="rating-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <circle cx="256" cy="256" r="256" fill="#ffd93b"/>
          <path d="M512 256A256 256 0 0 1 56.7 416.7a256 256 0 0 0 360-360c58.1 47 95.3 118.8 95.3 199.3z" fill="#f4c534"/>
          <path d="M328.4 428a92.8 92.8 0 0 0-145-.1 6.8 6.8 0 0 1-12-5.8 86.6 86.6 0 0 1 84.5-69 86.6 86.6 0 0 1 84.7 69.8c1.3 6.9-7.7 10.6-12.2 5.1z" fill="#3e4347"/>
          <path d="M269.2 222.3c5.3 62.8 52 113.9 104.8 113.9 52.3 0 90.8-51.1 85.6-113.9-2-25-10.8-47.9-23.7-66.7-4.1-6.1-12.2-8-18.5-4.2a111.8 111.8 0 0 1-60.1 16.2c-22.8 0-42.1-5.6-57.8-14.8-6.8-4-15.4-1.5-18.9 5.4-9 18.2-13.2 40.3-11.4 64.1z" fill="#f4c534"/>
          <path d="M357 189.5c25.8 0 47-7.1 63.7-18.7 10 14.6 17 32.1 18.7 51.6 4 49.6-26.1 89.7-67.5 89.7-41.6 0-78.4-40.1-82.5-89.7A95 95 0 0 1 298 174c16 9.7 35.6 15.5 59 15.5z" fill="#fff"/>
          <path d="M396.2 246.1a38.5 38.5 0 0 1-38.7 38.6 38.5 38.5 0 0 1-38.6-38.6 38.6 38.6 0 1 1 77.3 0z" fill="#3e4347"/>
          <path d="M380.4 241.1c-3.2 3.2-9.9 1.7-14.9-3.2-4.8-4.8-6.2-11.5-3-14.7 3.3-3.4 10-2 14.9 2.9 4.9 5 6.4 11.7 3 15z" fill="#fff"/>
          <path d="M242.8 222.3c-5.3 62.8-52 113.9-104.8 113.9-52.3 0-90.8-51.1-85.6-113.9 2-25 10.8-47.9 23.7-66.7 4.1-6.1 12.2-8 18.5-4.2 16.2 10.1 36.2 16.2 60.1 16.2 22.8 0 42.1-5.6 57.8-14.8 6.8-4 15.4-1.5 18.9 5.4 9 18.2 13.2 40.3 11.4 64.1z" fill="#f4c534"/>
          <path d="M155 189.5c-25.8 0-47-7.1-63.7-18.7-10 14.6-17 32.1-18.7 51.6-4 49.6 26.1 89.7 67.5 89.7 41.6 0 78.4-40.1 82.5-89.7A95 95 0 0 0 214 174c-16 9.7-35.6 15.5-59 15.5z" fill="#fff"/>
          <path d="M115.8 246.1a38.5 38.5 0 0 0 38.7 38.6 38.5 38.5 0 0 0 38.6-38.6 38.6 38.6 0 1 0-77.3 0z" fill="#3e4347"/>
          <path d="M131.6 241.1c3.2 3.2 9.9 1.7 14.9-3.2 4.8-4.8 6.2-11.5 3-14.7-3.3-3.4-10-2-14.9 2.9-4.9 5-6.4 11.7-3 15z" fill="#fff"/>
        </svg>
          <svg class="rating-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <circle cx="256" cy="256" r="256" fill="#ffd93b"/>
          <path d="M512 256A256 256 0 0 1 56.7 416.7a256 256 0 0 0 360-360c58.1 47 95.3 118.8 95.3 199.3z" fill="#f4c534"/>
          <path d="M336.6 403.2c-6.5 8-16 10-25.5 5.2a117.6 117.6 0 0 0-110.2 0c-9.4 4.9-19 3.3-25.6-4.6-6.5-7.7-4.7-21.1 8.4-28 45.1-24 99.5-24 144.6 0 13 7 14.8 19.7 8.3 27.4z" fill="#3e4347"/>
          <path d="M276.6 244.3a79.3 79.3 0 1 1 158.8 0 79.5 79.5 0 1 1-158.8 0z" fill="#fff"/>
          <circle cx="340" cy="260.4" r="36.2" fill="#3e4347"/>
          <g fill="#fff">
            <ellipse transform="rotate(-135 326.4 246.6)" cx="326.4" cy="246.6" rx="6.5" ry="10"/>
            <path d="M231.9 244.3a79.3 79.3 0 1 0-158.8 0 79.5 79.5 0 1 0 158.8 0z"/>
          </g>
          <circle cx="168.5" cy="260.4" r="36.2" fill="#3e4347"/>
          <ellipse transform="rotate(-135 182.1 246.7)" cx="182.1" cy="246.7" rx="10" ry="6.5" fill="#fff"/>
        </svg>
          <svg class="rating-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
    <circle cx="256" cy="256" r="256" fill="#ffd93b"/>
    <path d="M407.7 352.8a163.9 163.9 0 0 1-303.5 0c-2.3-5.5 1.5-12 7.5-13.2a780.8 780.8 0 0 1 288.4 0c6 1.2 9.9 7.7 7.6 13.2z" fill="#3e4347"/>
    <path d="M512 256A256 256 0 0 1 56.7 416.7a256 256 0 0 0 360-360c58.1 47 95.3 118.8 95.3 199.3z" fill="#f4c534"/>
    <g fill="#fff">
      <path d="M115.3 339c18.2 29.6 75.1 32.8 143.1 32.8 67.1 0 124.2-3.2 143.2-31.6l-1.5-.6a780.6 780.6 0 0 0-284.8-.6z"/>
      <ellipse cx="356.4" cy="205.3" rx="81.1" ry="81"/>
    </g>
    <ellipse cx="356.4" cy="205.3" rx="44.2" ry="44.2" fill="#3e4347"/>
    <g fill="#fff">
      <ellipse transform="scale(-1) rotate(45 454 -906)" cx="375.3" cy="188.1" rx="12" ry="8.1"/>
      <ellipse cx="155.6" cy="205.3" rx="81.1" ry="81"/>
    </g>
    <ellipse cx="155.6" cy="205.3" rx="44.2" ry="44.2" fill="#3e4347"/>
    <ellipse transform="scale(-1) rotate(45 454 -421.3)" cx="174.5" cy="188" rx="12" ry="8.1" fill="#fff"/>
  </svg>
          <svg class="rating-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <circle cx="256" cy="256" r="256" fill="#ffd93b"/>
          <path d="M512 256A256 256 0 0 1 56.7 416.7a256 256 0 0 0 360-360c58.1 47 95.3 118.8 95.3 199.3z" fill="#f4c534"/>
          <path d="M232.3 201.3c0 49.2-74.3 94.2-74.3 94.2s-74.4-45-74.4-94.2a38 38 0 0 1 74.4-11.1 38 38 0 0 1 74.3 11.1z" fill="#e24b4b"/>
          <path d="M96.1 173.3a37.7 37.7 0 0 0-12.4 28c0 49.2 74.3 94.2 74.3 94.2C80.2 229.8 95.6 175.2 96 173.3z" fill="#d03f3f"/>
          <path d="M215.2 200c-3.6 3-9.8 1-13.8-4.1-4.2-5.2-4.6-11.5-1.2-14.1 3.6-2.8 9.7-.7 13.9 4.4 4 5.2 4.6 11.4 1.1 13.8z" fill="#fff"/>
          <path d="M428.4 201.3c0 49.2-74.4 94.2-74.4 94.2s-74.3-45-74.3-94.2a38 38 0 0 1 74.4-11.1 38 38 0 0 1 74.3 11.1z" fill="#e24b4b"/>
          <path d="M292.2 173.3a37.7 37.7 0 0 0-12.4 28c0 49.2 74.3 94.2 74.3 94.2-77.8-65.7-62.4-120.3-61.9-122.2z" fill="#d03f3f"/>
          <path d="M411.3 200c-3.6 3-9.8 1-13.8-4.1-4.2-5.2-4.6-11.5-1.2-14.1 3.6-2.8 9.7-.7 13.9 4.4 4 5.2 4.6 11.4 1.1 13.8z" fill="#fff"/>
          <path d="M381.7 374.1c-30.2 35.9-75.3 64.4-125.7 64.4s-95.4-28.5-125.8-64.2a17.6 17.6 0 0 1 16.5-28.7 627.7 627.7 0 0 0 218.7-.1c16.2-2.7 27 16.1 16.3 28.6z" fill="#3e4347"/>
          <path d="M256 438.5c25.7 0 50-7.5 71.7-19.5-9-33.7-40.7-43.3-62.6-31.7-29.7 15.8-62.8-4.7-75.6 34.3 20.3 10.4 42.8 17 66.5 17z" fill="#e24b4b"/>
        </svg>
          <svg class="rating-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <g fill="#ffd93b">
            <circle cx="256" cy="256" r="256"/>
            <path d="M512 256A256 256 0 0 1 56.8 416.7a256 256 0 0 0 360-360c58 47 95.2 118.8 95.2 199.3z"/>
          </g>
          <path d="M512 99.4v165.1c0 11-8.9 19.9-19.7 19.9h-187c-13 0-23.5-10.5-23.5-23.5v-21.3c0-12.9-8.9-24.8-21.6-26.7-16.2-2.5-30 10-30 25.5V261c0 13-10.5 23.5-23.5 23.5h-187A19.7 19.7 0 0 1 0 264.7V99.4c0-10.9 8.8-19.7 19.7-19.7h472.6c10.8 0 19.7 8.7 19.7 19.7z" fill="#e9eff4"/>
          <path d="M204.6 138v88.2a23 23 0 0 1-23 23H58.2a23 23 0 0 1-23-23v-88.3a23 23 0 0 1 23-23h123.4a23 23 0 0 1 23 23z" fill="#45cbea"/>
          <path d="M476.9 138v88.2a23 23 0 0 1-23 23H330.3a23 23 0 0 1-23-23v-88.3a23 23 0 0 1 23-23h123.4a23 23 0 0 1 23 23z" fill="#e84d88"/>
          <g fill="#38c0dc">
            <path d="M95.2 114.9l-60 60v15.2l75.2-75.2zM123.3 114.9L35.1 203v23.2c0 1.8.3 3.7.7 5.4l116.8-116.7h-29.3z"/>
          </g>
          <g fill="#d23f77">
            <path d="M373.3 114.9l-66 66V196l81.3-81.2zM401.5 114.9l-94.1 94v17.3c0 3.5.8 6.8 2.2 9.8l121.1-121.1h-29.2z"/>
          </g>
          <path d="M329.5 395.2c0 44.7-33 81-73.4 81-40.7 0-73.5-36.3-73.5-81s32.8-81 73.5-81c40.5 0 73.4 36.3 73.4 81z" fill="#3e4347"/>
          <path d="M256 476.2a70 70 0 0 0 53.3-25.5 34.6 34.6 0 0 0-58-25 34.4 34.4 0 0 0-47.8 26 69.9 69.9 0 0 0 52.6 24.5z" fill="#e24b4b"/>
          <path d="M290.3 434.8c-1 3.4-5.8 5.2-11 3.9s-8.4-5.1-7.4-8.7c.8-3.3 5.7-5 10.7-3.8 5.1 1.4 8.5 5.3 7.7 8.6z" fill="#fff" opacity=".2"/>
        </svg>
        </div>
      </div>
    </div>
  </div>
</div>

Code CSS

* { box-sizing: border-box; }

.container {
  display: flex;
  flex-wrap: wrap;
  height: 100vh;
  align-items: center;
  justify-content: center;
  padding: 0 20px;
}

.rating {
  display: flex;
  width: 100%;
  justify-content: center;
  overflow: hidden;
  flex-direction: row-reverse;
  height: 150px;
  position: relative;
}

.rating-0 {
  filter: grayscale(100%);
}

.rating > input {
  display: none;
}

.rating > label {
  cursor: pointer;
  width: 40px;
  height: 40px;
  margin-top: auto;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='126.729' height='126.73'%3e%3cpath fill='%23e3e3e3' d='M121.215 44.212l-34.899-3.3c-2.2-.2-4.101-1.6-5-3.7l-12.5-30.3c-2-5-9.101-5-11.101 0l-12.4 30.3c-.8 2.1-2.8 3.5-5 3.7l-34.9 3.3c-5.2.5-7.3 7-3.4 10.5l26.3 23.1c1.7 1.5 2.4 3.7 1.9 5.9l-7.9 32.399c-1.2 5.101 4.3 9.3 8.9 6.601l29.1-17.101c1.9-1.1 4.2-1.1 6.1 0l29.101 17.101c4.6 2.699 10.1-1.4 8.899-6.601l-7.8-32.399c-.5-2.2.2-4.4 1.9-5.9l26.3-23.1c3.8-3.5 1.6-10-3.6-10.5z'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 76%;
  transition: .3s;
}

.rating > input:checked ~ label,
.rating > input:checked ~ label ~ label {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='126.729' height='126.73'%3e%3cpath fill='%23fcd93a' d='M121.215 44.212l-34.899-3.3c-2.2-.2-4.101-1.6-5-3.7l-12.5-30.3c-2-5-9.101-5-11.101 0l-12.4 30.3c-.8 2.1-2.8 3.5-5 3.7l-34.9 3.3c-5.2.5-7.3 7-3.4 10.5l26.3 23.1c1.7 1.5 2.4 3.7 1.9 5.9l-7.9 32.399c-1.2 5.101 4.3 9.3 8.9 6.601l29.1-17.101c1.9-1.1 4.2-1.1 6.1 0l29.101 17.101c4.6 2.699 10.1-1.4 8.899-6.601l-7.8-32.399c-.5-2.2.2-4.4 1.9-5.9l26.3-23.1c3.8-3.5 1.6-10-3.6-10.5z'/%3e%3c/svg%3e");
}


.rating > input:not(:checked) ~ label:hover,
.rating > input:not(:checked) ~ label:hover ~ label {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='126.729' height='126.73'%3e%3cpath fill='%23d8b11e' d='M121.215 44.212l-34.899-3.3c-2.2-.2-4.101-1.6-5-3.7l-12.5-30.3c-2-5-9.101-5-11.101 0l-12.4 30.3c-.8 2.1-2.8 3.5-5 3.7l-34.9 3.3c-5.2.5-7.3 7-3.4 10.5l26.3 23.1c1.7 1.5 2.4 3.7 1.9 5.9l-7.9 32.399c-1.2 5.101 4.3 9.3 8.9 6.601l29.1-17.101c1.9-1.1 4.2-1.1 6.1 0l29.101 17.101c4.6 2.699 10.1-1.4 8.899-6.601l-7.8-32.399c-.5-2.2.2-4.4 1.9-5.9l26.3-23.1c3.8-3.5 1.6-10-3.6-10.5z'/%3e%3c/svg%3e");
}

.emoji-wrapper {
  width: 100%;
  text-align: center;
  height: 100px;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
}

.emoji-wrapper:before,
.emoji-wrapper:after{
  content: "";
  height: 15px;
  width: 100%;
  position: absolute;
  left: 0;
  z-index: 1;
}

.emoji-wrapper:before {
  top: 0;
  background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(255,255,255,1) 35%,rgba(255,255,255,0) 100%);
}

.emoji-wrapper:after{
  bottom: 0;
  background: linear-gradient(to top, rgba(255,255,255,1) 0%,rgba(255,255,255,1) 35%,rgba(255,255,255,0) 100%);
}

.emoji {
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: .3s;
}

.emoji > svg {
  margin: 15px 0; 
  width: 70px;
  height: 70px;
  flex-shrink: 0;
}

#rating-1:checked ~ .emoji-wrapper > .emoji { transform: translateY(-100px); }
#rating-2:checked ~ .emoji-wrapper > .emoji { transform: translateY(-200px); }
#rating-3:checked ~ .emoji-wrapper > .emoji { transform: translateY(-300px); }
#rating-4:checked ~ .emoji-wrapper > .emoji { transform: translateY(-400px); }
#rating-5:checked ~ .emoji-wrapper > .emoji { transform: translateY(-500px); }

.feedback {
  max-width: 360px;
  background-color: #fff;
  width: 100%;
  padding: 30px;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: center;
  box-shadow: 0 4px 30px rgba(0,0,0,.05);
}

2. Code CSS xếp hạng sao có hiệu ứng

Code CSS xếp hạng sao có hiệu ứng

Link xem thử: Demo               Code: HTML/CSS

HTML

<!DOCTYPE html>
<html>
<head>
<!-- Font Awesome Icon Library -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.checked {
  color: orange;
}
</style>
</head>
<body>

<h2>Star Rating</h2>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star"></span>
<span class="fa fa-star"></span>

</body>
</html>

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  background: #353b48;
}
.star-wrapper {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
  direction: rtl;
}
.star-wrapper a {
  font-size: 4em;
  color: #fff;
  text-decoration: none;
  transition: all 0.5s;
  margin: 4px;
}
.star-wrapper a:hover {
  color: gold;
  transform: scale(1.3);
}
.s1:hover ~ a {
  color: gold;
}
.s2:hover ~ a {
  color: gold;
}
.s3:hover ~ a {
  color: gold;
}
.s4:hover ~ a {
  color: gold;
}
.s5:hover ~ a {
  color: gold;
}
.wraper {
  position: absolute;
  bottom: 30px;
  right: 50px;
}

3. CSS Rating tùy biến số lượng sao

CSS xếp hạng tùy biến số lượng sao

Link xem thử: Demo                       Code: HTML (Pug)/CSS (SCSS)

Với code CSS dưới đây, để tùy biến số lượng sao rate, bạn chỉ cần thay đổi số ở phần let stars, như trong ví dụ HTML dưới đây tôi đã thay 7 (như trong bản Demo) thành 10 ngôi sao.

HTML (Pug)

- let stars = 7
- let i = 0
.rating(style=`--stars: ${stars}`)
	.ratings
		.rating__blank
			while i < stars
				span.star
				- i++
			- i = 0
		.rating__people
			while i < stars
				span.star
				- i++
			- i = stars
		.rating__you
			while i > 0
				input(type="radio" class="star" name="rating" this.value=`${i--}`)/

				span(style="margin: -.14em;")
<input type="radio" class="btn" name="rating" value="0" />

CSS (SCSS)

:root {
	--stars: 'see html editor'; /* How many stars are there */
	
	--votes: 20; /* How many people have voted? */
	--score: 70; /* ...out of (stars * votes) */
}

body {
	font-family: "Helvetica";
	font-size: 62.5%;
}
input {
	font-family: inherit;
}


.rating {
	background-color: #7bf;
	border: 4px solid #0003;
	border-radius: 32px;
	display: inline-block;
	overflow: hidden;
	position: relative;
	vertical-align: middle;
	
	&s {
		margin: 8px 16px;
		position: relative;
	}
	
	& .star {
		/* General Rating Star styles */
		appearance: none;
		box-sizing: border-box;
		font-family: FontAwesome;
		font-size: 3em;
		margin: 0 -.1em;
		position: relative;
		
		&:before, &:after {
			display: inline-block;
			padding: .05em .15em;
			vertical-align: top;
			transition: all .25s;
		}
		&:before {
			/* Filled Star icon */
			content: "\f005";
			position: relative;
		}
		&:after {
			/* Outline Star icon */
			content: "\f006";
			position: absolute;
			top: 0;
			left: 0;
		}
	}
	
	&__blank, &__people, &__you {
		box-sizing: border-box;
		white-space: nowrap;
		transition: all 1s;
	}
	&__people, &__you {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
	}
	
	/* The base. Basically layer 0. */
	&__blank {
		& .star:before {
			color: #ddd;
			-webkit-text-stroke: 1px #000;
		}
		& .star:after {
			color: #0003;
		}
	}
	
	/* The people's votes. Layer 1. */ 
	&__people {
		width: calc(100% * (var(--score) / (var(--votes) * var(--stars))));
		overflow: hidden;
		
		& .star:before {
			color: #39f;
		}
		& .star:after {
			color: #0003;
		}
	}
	
	/* Your vote. Layer 2. */
	&__you {

		direction: rtl;
		
		& .star {
			cursor: pointer;
			&:before, &:after { opacity: 0; }
			

			&:before {
				color: #fc0;
				text-shadow: 0px 0px 1px #000;
			}
			&:hover ~ .star, &:hover {
				&:before { opacity: 1; }
			}
			

			&:after {
				color: #ff0;
				-webkit-text-stroke: .025em #0006;
			}
			&:checked ~ .star, &:checked {
				&:after { opacity: 1; }
			}
		}
	}
}

/* Clear Rating button */
.btn {
	appearance: none;
	background-color: #eee;
	border-radius: 32px;
	box-shadow: inset 0 0 0 1px #0003, inset 0 3px #fff6;
	cursor: pointer;
	display: inline-block;
	margin-top: 8px;
	padding: .4em .8em;
	font-size: 1.25em;
	transition: all .2s;
	outline: none;
	vertical-align: middle;
	
	&:hover, &:focus { background-color: #fff; }
	&:active { background-color: #ddd; }
	
	&:after { content: "Clear Rating"; }
}

/* Rating Info box */
.info {
	border-top: 1px solid #0001;
	margin-top: 8px;
	padding: 1em;
	
	.num:before {
		content: "???";
	}
	#rating_ {
		&current:before {
			counter-reset: num var(--score);
			content: counter(num);
		}
		&max:before {
			counter-reset: num var(--score_max);
			content: counter(num);
		}
		&percent:before {
			counter-reset: num var(--a);
			content: counter(num);
		}
		&votes:before {
			counter-reset: num var(--votes);
			content: counter(num);
		}
	}
}

4. Code Rating sao vàng trên nền xanh

Code Rating sao vàng trên nền xanh

Link xem thử: Demo                            Code: HTML/CSS (SCSS)

 

HTML

<span class="star__container">
  <input type="radio" name="rating" value="1" id="star-1" class="star__radio visuhide">
  <input type="radio" name="rating" value="2" id="star-2" class="star__radio visuhide">
  <input type="radio" name="rating" value="3" id="star-3" class="star__radio visuhide">
  <input type="radio" name="rating" value="4" id="star-4" class="star__radio visuhide">
  <input type="radio" name="rating" value="5" id="star-5" class="star__radio visuhide">

  <label class="star__item" for="star-1"><span class="visuhide">1 star</span></label>
  <label class="star__item" for="star-2"><span class="visuhide">2 stars</span></label>
  <label class="star__item" for="star-3"><span class="visuhide">3 stars</span></label>
  <label class="star__item" for="star-4"><span class="visuhide">4 stars</span></label>
  <label class="star__item" for="star-5"><span class="visuhide">5 stars</span></label>
</span>

CSS (SCSS)

$rating-emoji: '⭐️' !default;
//$rating-emoji: '💛';
*, *::before, *::after { box-sizing: border-box; }

html,
body {
  height: 100%;
  font-size: 32px;
}

body {
  display: flex;
  margin: 0;
  background-color: #e6e6e6;
}

.visuhide {
  position: absolute !important;
  overflow: hidden;
  width: 1px;
  height: 1px;
  clip: rect(1px,1px,1px,1px);
}

%star-active { filter: grayscale(0); }
%star-inactive { filter: grayscale(1); }

.star {
  $p: &;
  $star_count: 5;
  
  @for $i from 1 through $star_count {
    &__container:not(:hover) > &__radio:nth-of-type(#{$i}):checked ~ &__item:nth-of-type(#{$i}) ~ &__item {
      @extend %star-inactive;
    }
    
    &__radio:nth-of-type(#{$i}):checked ~ &__item:nth-of-type(#{$i})::before {
      transform: scale(1.5);
      transition-timing-function: cubic-bezier(.5,1.5,.25,1);
    }
  }
  
  &__container {
    display: flex;
    margin: auto;
    border-radius: .25em;
    background-color: #00a39b;
    box-shadow: 0 .25em 1em rgba(0,0,0,.25);
    transition: box-shadow .3s ease;
    
    &:focus-within {
      box-shadow: 0 0.125em .5em rgba(0,0,0,.5);
    }
  }
  
  &__item {
    display: inline-flex;
    width: 1.25em;
    height: 1.5em;
    @extend %star-inactive;
    
    &::before {
      content: $rating-emoji;
      display: inline-block;
      margin: auto;
      font-size: .75em;
      vertical-align: top;
      backface-visibility: hidden;
      transform-origin: 50% 33.3%;
      transition: transform .3s ease-out;
    }
    
    // Active all stars when the container is hovered…
    #{$p}__container:hover &,
    #{$p}__radio:checked ~ & { 
      @extend %star-active;
    }
    // Then deactivate the ones that are after the hovered star
    &:hover ~ & {
      @extend %star-inactive;
    }
  }
}

5. Code CSS vote sao dạng đơn giản

CSS Star Rating đơn giản

Link xem thử: Demo                 Code: HTML/CSS

HTML

<div class="page">
  <div class="page__demo">
    <div class="page__group">
      <div class="rating">
        <input type="radio" name="rating-star" class="rating__control screen-reader" id="rc1">
        <input type="radio" name="rating-star" class="rating__control screen-reader" id="rc2">
        <input type="radio" name="rating-star" class="rating__control screen-reader" id="rc3">
        <input type="radio" name="rating-star" class="rating__control screen-reader" id="rc4">
        <input type="radio" name="rating-star" class="rating__control screen-reader" id="rc5">
        <label for="rc1" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">1</span>
        </label>
        <label for="rc2" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">2</span>
        </label>
        <label for="rc3" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">3</span>
        </label>
        <label for="rc4" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">4</span>
        </label>
        <label for="rc5" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">5</span>
        </label>	
      </div>
      <span class="page__hint">Chưa được chọn</span>
    </div>
    <div class="page__group">  
      <div class="rating">
        <input type="radio" name="rating-star2" class="rating__control screen-reader" id="rc6">
        <input type="radio" name="rating-star2" class="rating__control screen-reader" id="rc7">
        <input type="radio" name="rating-star2" class="rating__control screen-reader" id="rc8" checked>
        <input type="radio" name="rating-star2" class="rating__control screen-reader" id="rc9">
        <input type="radio" name="rating-star2" class="rating__control screen-reader" id="rc10">
        <label for="rc6" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">1</span>
        </label>
        <label for="rc7" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">2</span>
        </label>
        <label for="rc8" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">3</span>
        </label>
        <label for="rc9" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">4</span>
        </label>
        <label for="rc10" class="rating__item">
          <svg class="rating__star">
            <use xlink:href="#star"></use>
          </svg>
          <span class="screen-reader">5</span>
        </label>	
      </div>    
      <span class="page__hint">Được chọn</span>  
    </div>
  </div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
  <symbol id="star" viewBox="0 0 26 28">
    <path d="M26 10.109c0 .281-.203.547-.406.75l-5.672 5.531 1.344 7.812c.016.109.016.203.016.313 0 .406-.187.781-.641.781a1.27 1.27 0 0 1-.625-.187L13 21.422l-7.016 3.687c-.203.109-.406.187-.625.187-.453 0-.656-.375-.656-.781 0-.109.016-.203.031-.313l1.344-7.812L.39 10.859c-.187-.203-.391-.469-.391-.75 0-.469.484-.656.875-.719l7.844-1.141 3.516-7.109c.141-.297.406-.641.766-.641s.625.344.766.641l3.516 7.109 7.844 1.141c.375.063.875.25.875.719z"/>
  </symbol>
</svg>

CSS

.screen-reader{
  width: var(--screenReaderWidth, 1px) !important;
  height: var(--screenReaderHeight, 1px) !important;
  padding: var(--screenReaderPadding, 0) !important;
  border: var(--screenReaderBorder, none) !important;

  position: var(--screenReaderPosition, absolute) !important;
  clip: var(--screenReaderClip, rect(1px, 1px, 1px, 1px)) !important;
  overflow: var(--screenReaderOverflow, hidden) !important;
}

/*
=====
CORE STYLES
=====
*/

.rating{
  --uiRatingColor: var(--ratingColor, #eee);
  --uiRatingColorActive: var(--ratingColorActive, #ffcc00);

  display: var(--ratingDisplay, flex);
  font-size: var(--ratingSize, 1rem);
  color: var(--uiRatingColor);
}
    
.rating__control:nth-of-type(1):focus ~ .rating__item:nth-of-type(1)::before,
.rating__control:nth-of-type(2):focus ~ .rating__item:nth-of-type(2)::before,
.rating__control:nth-of-type(3):focus ~ .rating__item:nth-of-type(3)::before,
.rating__control:nth-of-type(4):focus ~ .rating__item:nth-of-type(4)::before,
.rating__control:nth-of-type(5):focus ~ .rating__item:nth-of-type(5)::before{
  content: ""; 
  box-shadow: 0 0 0 var(--ratingOutlineWidth, 4px) var(--uiRatingColorActive);

  position: absolute;
  top: -.15em;
  right: 0;
  bottom: -.15em;
  left: 0;
  z-index: -1;
}

.rating__item{
  cursor: pointer;  
  position: relative;
}

.rating__item{
  padding-left: .25em;
  padding-right: .25em;
}

.rating__star{
  display: block;
  width: 1em;
  height: 1em;

  fill: currentColor;
  stroke: var(--ratingStroke, #222);
  stroke-width: var(--ratingStrokeWidth, 1px);
}

.rating:hover,
.rating__control:nth-of-type(1):checked ~ .rating__item:nth-of-type(1),
.rating__control:nth-of-type(2):checked ~ .rating__item:nth-of-type(-n+2),
.rating__control:nth-of-type(3):checked ~ .rating__item:nth-of-type(-n+3),
.rating__control:nth-of-type(4):checked ~ .rating__item:nth-of-type(-n+4),
.rating__control:nth-of-type(5):checked ~ .rating__item:nth-of-type(-n+5){
  color: var(--uiRatingColorActive);
}

.rating__item:hover ~ .rating__item{
  color: var(--uiRatingColor);
}

/*
=====
SETTINGS
=====
*/

.rating{
  --ratingSize: 2rem;
  --ratingColor: #eee;
  --ratingColorActive: #ffcc00;
}

/*
=====
DEMO
=====
*/

body{
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Open Sans, Ubuntu, Fira Sans, Helvetica Neue, sans-serif;
  font-size: 1rem;
  margin: 0;
}

.page{
  min-height: 100vh;
  display: flex;
}

.page__demo{
  margin: auto;  
}

.page__group{
  margin-top: 2rem;
  margin-bottom: 2rem;
  text-align: center;
}

.page__hint{
  display: block;
  font-weight: 700;
  margin-top: 1rem;
}

@media (min-width: 641px){
  .page__demo{
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }

  .page__group{
    margin-left: 3.5rem;
    margin-right: 3.5rem;
  }
}

6. CSS vote sao sử dụng SVG

CSS vote sao sử dụng SVG

Link xem thử: Demo    Code: HTML/CSS (SCSS)

HTML

<div class="wrapper">  
  <div class="rating-holder">
    <div class="c-rating c-rating--small" data-rating-value="2">
      <button>1</button>
      <button>2</button>
      <button>3</button>
      <button>4</button>
      <button>5</button>
    </div>
  </div>
  
  <div class="rating-holder">
    <div class="c-rating c-rating--regular" data-rating-value="3.25">
      <button>1</button>
      <button>2</button>
      <button>3</button>
      <button>4</button>
      <button>5</button>
    </div>
  </div>
  
  <div class="rating-holder">
    <div class="c-rating c-rating--big" data-rating-value="4.5">
      <button>1</button>
      <button>2</button>
      <button>3</button>
      <button>4</button>
      <button>5</button>
    </div>
  </div>
</div>

CSS (SCSS)

////
/// Star Rating
/// @group components
/// @author Damián Muti
////

@import url('https://fonts.googleapis.com/css?family=Roboto+Slab:400');

///
$rating-min-value: 0 !default;
///
$rating-max-value: 5 !default;
///
$rating-steps-value: .25 !default;
///
$rating-color-empty: '%23ddd' !default;
///
$rating-color-full: gold !default;
///
$rating-color-hover: grey !default;
/// This variable is a map containing the "d" attribute of each of the SVG icons
$rating-icons-paths: (
  quarter: 'M196.208 415.2v-224.8l-139.504 20.272 100.944 98.384-23.84 138.928z',
  half: 'M258.672 64l-62.384 126.4-139.504 20.272 100.944 98.384-23.84 138.928 124.768-65.6v-318.4z',
  three-quarters: 'M321.616 190.496l-0.656-0.096-62.384-126.4-62.384 126.4-139.504 20.272 100.944 98.384-23.84 138.928 124.768-65.6 63.024 33.136z',
  full: 'M457.888 210.672l-139.504-20.272-62.384-126.4-62.384 126.4-139.504 20.272 100.944 98.384-23.84 138.928 124.768-65.6 124.768 65.6-23.84-138.928c0 0 100.944-98.384 100.944-98.384z'
);

/// Creates a dynamic list of values that increment each .25 from 0 to 5
/// @return {list} 
@function rating-values() {
  $rating-values: ();

  @for $i from $rating-min-value through ($rating-max-value / $rating-steps-value) {
    $rating-value: abs($i * $rating-steps-value);
    $rating-values: append($rating-values, $rating-value, 'comma');
  }

  @return $rating-values;
}

/// Generates an SVG with a given fill color depending on the type of icon passed as parameter. The SVG string is scaped for cross-browser support.
/// @param {string} $icon - Type of icon. Accepted values: `quarter`, `half`, `three-quarters` or `full`.
/// @param {color} $color - Passes the fill color of the SVG icon that is being generated. Note: Hexa color values must be escaped for cross-browser support.
/// @return {string} background value.
@function get-icon($icon, $color) {
  @if not index(quarter half three-quarters full, $icon) {
    @error "Interaction type must be either `quarter`, `half`, `three-quarters` or `full`.";
  }
  
  @return url('data:image/svg+xml;utf8,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22' + $color + '%22%20d%3D%22' + map-get($rating-icons-paths, $icon) + '%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') center / cover no-repeat;
}

/// This is a CSS-only star rating component that shows the proper rating depending on a data-attribute value. JS logic behind this component should round up values per quarter.
/// @param {number} $star-size [20px] - Provides width and height for each of the stars.
/// @param {string} $rating-element 
    
  
 - Element to use for each of the stars.
/// @param {string} $interaction-type [representative] - Indicates whether this component should be clickable or representative. Accepted values: `clickable` or `representative`.
/// @example scss
///   .class {
///     c-rating(toem(20px), button, clickable);
///   }
/// @example markup
///   <div class="c-rating" data-rating-value="3.25">
///     <span>1</span>
///     <span>2</span>
///     <span>3</span>
///     <span>4</span>
///     <span>5</span>
///   </div>
@mixin c-rating($star-size: 20px, $star-element: button, $interaction-type: representative) {
  @if not index(clickable representative, $interaction-type) {
    @error "Interaction type must be either `clickable` or `representative`.";
  }
  
  #{$star-element} {
    display: inline-block;
    float: left;
    width: $star-size;
    height: $star-size;
    border: 0;
    text-indent: -9999px;
    outline: none;
    background: get-icon(full, $rating-color-empty);

    @if $interaction-type == clickable {
      cursor: pointer;
      transition: background 0.25s ease;
      
      // Override background images on hover state
      &:hover,
      &:hover ~ #{$star-element} {
        background: get-icon(full, $rating-color-empty) !important;
      }
    }
  }
  
  // Override background images on hover state
  @if $interaction-type == clickable {
    &:hover {
      #{$star-element} {
        background: get-icon(full, $rating-color-hover) !important;
      }
    }
  }

  @each $rating-value in rating-values() {
    // Get the next higher integer.
    $rating-value-ceil: ceil($rating-value);

    &[data-rating-value="#{$rating-value}"] {
      #{$star-element}:nth-child(-n+#{$rating-value-ceil}) {
        background: get-icon(full, $rating-color-full);
      }

      #{$star-element}:nth-child(#{$rating-value-ceil}) {
        // Evaluate which fraction of a star this value is and add the proper background
        @if str-slice("#{$rating-value}", 2, 4) == '.25' {
          background: get-icon(quarter, $rating-color-full), get-icon(full, $rating-color-empty)
        }
        @else if str-slice("#{$rating-value}", 2, 4) == '.5' {
          background: get-icon(half, $rating-color-full), get-icon(full, $rating-color-empty)
        }
        @else if str-slice("#{$rating-value}", 2, 4) == '.75' {
          background: get-icon(three-quarters, $rating-color-full), get-icon(full, $rating-color-empty)
        }
      }
    }
  }
}

/*
 * General styles.
 * Not necessary for the component to work
*/

/// Convert to EMs function
/// @param {number} target - The value to be converted
/// @param {number} context [$msuxf-font-size] The base font size
/// @return {em} value
@function toem($target, $context: 16px) {
  @if $target == 0 {
    @return 0
  }

  @return $target / $context+0em;
}

body {
  width: 100vw;
  height: 100vh;
  font-family: 'Roboto Slab', serif;
  text-align: center;
  background: linear-gradient(to bottom, #de6262, #ffb88c);
}

.wrapper {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 700px;
  transform: translate(-50%, -50%);
  
  h1 {
    margin-bottom: 75px;
    font-size: 56px;
    font-weight: 400;
    color: #fff;
  }
}

.rating-holder {
  display: inline-block;
  padding: toem(10px) toem(30px);
  margin: 0 10px;
  background-color: #fff;
  border-radius: toem(25px);
  box-sizing: border-box;
}

.c-rating {
  @include c-rating(toem(20px), button, clickable);
  
  &--small {
    font-size: 50%
  }
  
  &--big {
    font-size: 150%;
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *