Перейти к навигации · Перейти к содержимому

Рейтинг со звездами на CSS

Теги

Если вам понадобилось сделать механизм простановки оценок чему-либо (чаще всего при помощи «звездочек»), то для этого вовсе не обязательно применять JavaScript. Можно все сделать при помощи CSS и семантической разметки.

Первоисточник

На одном замечательном сайте есть целых две статьи про то, как такие рейтинги делать:

  1. Самое начало
  2. Вариант с выставленным рейтингом

Теперь я попытаюсь объяснить все это по-русски, добавив от себя некоторые улучшения (на мой взгляд).

Разметка

Почему вообще применяется список? Это очень удобно с точки зрения доступности (accessibility) — если агент не поддерживает CSS, то наш рейтинг предстанет простым списком ссылок без звездочек, но с возможностью голосования.

В исходном примере автор применяет простой ненумерованный список для создания рейтинга. Мне это показалось не совсем верным с точки зрения семантики: так как элементами списка являются цифры, то и список лучше применять нумерованный, вписав вместо цифр более понятные человеку термины типа «хорошо», «плохо» и т. д.

Кроме того, чтобы показать уже выбранное значение, применялся еще один элемент (неактивный), говорящий о том, какой рейтинг проставлен: <li class="current-rating">Currently 3.5/5 Stars.</li>. Мне кажется, что для подобных случаев уместнее использовать элемент DL — список определений.

W3C говорит нам:

Definition lists, created using the DL element, generally consist of a series of term/definition pairs (although definition lists may have other applications).

Это означает, что списки определений могут использоваться для пар термин/определение, а также иметь другие применения. То есть мы вполне можем использовать этот элемент, при этом «термином» будет текущий рейтинг, а его определением — список со звездами:

<dl class="star-rating">
  <dt>Рейтинг: 4 из 5 звезд</dt>
  <dd>
    <ol>
      <li><a href="#" class="star1">Ужасно</a></li>
      <li><a href="#" class="star2">Плохо</a></li>
      <li><a href="#" class="star3">Нормально</a></li>
      <li><a href="#" class="star4">Хорошо</a></li>
      <li><a href="#" class="star5">Отлично</a></li>
    </ol>
  </dd>
</dl>

Результат — ничего лишнего и необходимая функциональность.

Сами звезды

Изображение на все три состояния одно, что избавляет нас от необходимости догрузки отдельных картинок.

Звезды Теперь пришло время сделать сам рисунок звезд — открываете свой любимый Fireworks/Photoshop и рисуете примерно следующее:

Размер картинки в моем случае 20×60 пикселей, т. е. каждая звездочка имеет размер 20×20. Смысл в том, что необходимо изобразить картинку с тремя состояниями рейтинга (сверху-вниз):

  1. Пустое (рейтинг не проставлен)
  2. Звезда при выборе
  3. Состояние уже проставленного рейтинга

Оформление стилями

Стили буду объяснять по шагам:

Для начала уберем ненужные отступы у нашего списка, а также зададим его ширину и высоту (высота = 20, а ширина — 20×5 = 100). Важно указать правило position:relative, которое потом будет нужно для позиционирования элементов. Кроме того, на подложку мы положили нашу картинку со звездами (по умолчанию — пустая звезда, как если бы мы указали background-position:top):

dl.star-rating ol {
  margin: 0;
  padding: 0;
  list-style: none;
  width: 100px;
  height: 20px;
  position: relative;
  background: url(stars.png);
}

Теперь мы выстраиваем наши элементы списка в линию (float:left) и также убираем отступы:

dl.star-rating li {
  float: left;
  margin: 0;
  padding: 0;
}

Пришло время для ссылок: мы делаем их блочными элементами (чтобы задать ширину и высоту звездочек), прячем текст text-indent:-9999px, а также указываем абсолютное позиционирование и z-index (потом станет ясно зачем):

dl.star-rating li a {
  display: block;
  width: 20px;
  height: 20px;
  text-indent: -9999px;
  position: absolute;
  text-decoration: none;
  z-index: 10;
}

Теперь начинается самое важное — мы указываем правила для реакции на курсор. При его наведении, наша ссылка заполняется рисунком звездочки (второе состояние из-за указания center), а также отодвигается влево (к самому краю всего рейтинга). Делается это для того, чтобы активная ссылка (т. е. в состоянии hover) заполняла собой больше чем положенные ей по умолчанию 20 пикселей — сейчас увидим.

dl.star-rating li a:hover {
  background: url(stars.png) left center;
  left: 0;
  z-index: 2;
}

Теперь, чтобы все заработало, нам надо добавить следующие правила для каждого элемента списка (их у нас 5):

dl.star-rating a.star1 {
  left: 0;
}
  dl.star-rating a.star1:hover {
  width: 20px;
}
dl.star-rating a.star2 {
  left: 20px;
}
dl.star-rating a.star2:hover {
  width: 40px;
}
...

Из-за указания z-index, наши звездочки позволяют «понижать» рейтинг, опускаясь ниже неактивных ссылок.

Остальные можно понять по аналогии: каждая следующая получает позиционирование, смещенное на 20 пикселей, а при наведении мышки — ширину, равную «значение»?20. Таким образом, каждая ссылка находится на «своем» месте в неактивном состоянии, а при hover’e — «отскакивает» влево, расширяясь при этом на заданную ширину.

Результат можно увидеть здесь: Шаг 2.

Проставленный рейтинг

Чтобы показать уже проставленный рейтинг нам необходимо добавить некоторую разметку к списку (к четвертому пункту):

<dl class="star-rating">
  ...
      <li class="current" style="width:80px"><a href="#" class="star4">Хорошо</a></li>
  ...
</dl>

Избежать указания ширины похоже не удастся. Вычислить ее придется на серверной стороне, умножив количество баллов на ширину звезды — на 20 пикселей.

При этом совершенно не обязательно указывать круглое число. Вы можете проставить, скажем, 3.5 баллов — лишь укажите width:70px.

Кроме того, добавим немного стилей:

dl.star-rating li.current {
  background: url(stars.png) left bottom;
  height: 20px;
  z-index: 1;
}

Что даст нам «запомненное» состояние рейтинга. Результат.

Небольшой бонус

Чтобы сделать пользование рейтингом еще удобнее, мы можем отображать соответствующие надписи при смене рейтинга. Для этого нам понадобится добавить всего одно правило:

dl.star-rating ol>li a:hover {
  text-indent: 110px;
}

upd. последний код не работает в IE 5/6, поэтому мы его просто от него скрываем. Решить эту проблему можно при помощи обертки в дополнительные теги (а может и еще как-то), а мне этого не хочется... Поэтому пользователи IE просто не увидят поясняющих надписей (hint: вынесите их в аттрибут title у ссылок).

Самый финальный результат: Наш рейтинг.

upd2. в комментариях спросили про серверную сторону реализации рейтинга. Один из способов здесь.

Комментарии

Отлично! Как раз надо делать. Использую твое решение :) Спасибо.

Спасибо. Очень интересно… При случае не премину воспользоваться ;)

Спасибо.

Последний пример ( http://eye.loveline.ru/example/stars/ ) сбоит в IE6 – под надписями множатся звездочки на всю длину текста.

dva: точно не работает… последнее писал не проверяя в IE. Сейчас допишу про это

Классно получилось!

А как это реализовать на серверной стороне?

А как это реализовать на серверной стороне?

Самой логичной была бы реализация на AJAX с возможностью просто кликнуть по ссылке при отключенном JS. А в ссылке указать путь на скрипт, например: vote.php?id=1&ra­te=3 с защитой от накруток внутри самого скрипта. Как-то так…

Прекольно, но в ИЕ дёргается…а с учётом того сколько пользователей под ИЕ…

Прекольно, но в ИЕ дёргается…а с учётом того сколько пользователей под ИЕ…

Как понять «дергается»? Проверял в IE 5/6 — не дергается. А оригинальный вариант тоже так себя ведет?

Так, очередной превед от ИЕ…
Посмотрел в эмуляторе 98 и XP, действительно всё отлично работает, ничего не дёргается… а мой рабочий комп – w2k, IE6, при переводе курсора от одной звезды к другой на мгновение все звёзды становятся серыи, а потом зажигаются…дё­ргаются то бишь… частный случай в общем (наверное)…
В любом случае для моей ситуации этот пример не подходит, т.к. по дизайну под звёздами цЫфры:

* * * * * * *
12 34 56 7

В любом случае для моей ситуации этот пример не подходит, т.к. по дизайну под звёздами цЫфры:

Цифры сделать не сложно — только придется ввести оборачивающий span. Или написать их вместо слов…

А вы попробуйте если «не сложно», при этом надо учесть что цифр 10 (от 1 до 10), каждая цифра должна адекватно стоять (ровно по центру под звездой) ну и конечно, всё это должно работать у всех (Opera, FF, IE)
;-)

Попробовал =) Результат.

Правда из-за странного глюка мозиллы, пришлось еще и слова с описаниями оценок обернуть в лишний div — в Опере и IE все работало и без него.

Красота :)

great article greets

Я полючил данную фитчу с php сктипту по типу vote все работает, только вот этот скипт отдельно статистику показывает… и приходиться рейтинг звезд менять в ручную…
Можно ли как-то выципить цифры рейтинга из php и например при помощи java всунуть в рейтинг звезд, что бы автоматом менялись???