Пользователь
0,0
рейтинг
16 июля 2015 в 20:08

Разработка → Star rating на CSS со шрифтовыми иконками от font-awesome из песочницы

HTML*, CSS*
Стояла задача добавить стар-рейтинг к форме комментариев для шаблона.

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

Решение делал не для конечного проекта, а для шаблона. Поэтому нужно было сделать звездочки максимально гибким для дальнейшей кастомизации. То есть изменения цвета, размера звездочек должно быть максимально легким. Под такую конфигурацию использование спрайта изображений не подходило, поэтому решил использовать шрифтовые иконки. Выбор пал на сервис Font Awesome. Там есть звездочки с названием fa-star-o — звездочка по умолчанию и fa-star — звездочка активная (при наведении и выборе).

Дальше решил подумать, как можно реализовать такую задача минимальными ресурсами, в идеале без использования javascript. В итоге все получилось и, как по мне, такое решение оптимальное для подобной задачи.

Кому лень читать дальше, можете сразу посмотреть результат тут — codepen.

HTML-разметка


Общая идея состоит в том, что мы выводим рейтинг обычными радиокнопками, что бы сохранить передачу данные через форму. Дальше прячем радиокнопки с помощью CSS, а выделять их будем с помощью клика по соседних лейблах, которые ссылаются на радиокнопку атрибутом for. Сами же лейблы мы выводим в виде иконок с сервиса Font Awesome.

В итоге HTML-разметка следующая:

<div class="star-rating">
      <div class="star-rating__wrap">
        <input class="star-rating__input" id="star-rating-5" type="radio" name="rating" value="5">
        <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-5" title="5 out of 5 stars"></label>
        <input class="star-rating__input" id="star-rating-4" type="radio" name="rating" value="4">
        <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-4" title="4 out of 5 stars"></label>
        <input class="star-rating__input" id="star-rating-3" type="radio" name="rating" value="3">
        <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-3" title="3 out of 5 stars"></label>
        <input class="star-rating__input" id="star-rating-2" type="radio" name="rating" value="2">
        <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-2" title="2 out of 5 stars"></label>
        <input class="star-rating__input" id="star-rating-1" type="radio" name="rating" value="1">
        <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-1" title="1 out of 5 stars"></label>
      </div>
</div>

Конечно, не забываем подключить шрифт Font Awesome в начале.

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

Очень важно сохранять порядок следования элементов input и label, при чем не помещать никаких вложенных элементов внутрь.Такая зависимость от html-разметки негативная, но это та жертва которую я посчитал уместной.

Также очень важно выводить радиокнопки в обратном порядке от 5 до 1.

CSS-стили


Первое, что нужно сделать — это спрятать радиокнопки. В результате у нас остаются только звездочки при нажатия на которые выделяется нужный радиобокс.

.star-rating__input{
display: none;
}

Второе — при наведении иконка должна изменятся на активную, при чем измениться должна не только текущая иконка, а и все иконки перед ней!

.star-rating__ico:hover:before,
.star-rating__ico:hover ~ .b-star-rating__ico:before,
{
	content: "\f005";
}

content: "\f005"; — это код активной иконки стар-рейтинга в шрифте Font Awesome. Иконки в этом шрифте вставляются через псевдоэлемент ::before

Третье — при клике на иконку состояние наведения должно сохраниться, то-есть активными должны быть текущая и соседние звездочки.

Добавляем к этому же правилу еще один селектор:

.star-rating__input:checked ~ .star-rating__ico:before


В результате главные стили, которые делают основную работу следующие:

.star-rating__input{
	display: none;
}
.star-rating__ico:hover:before,
.star-rating__ico:hover ~ .star-rating__ico:before,
.star-rating__input:checked ~ .star-rating__ico:before
{
	content: "\f005";
}

Дальше нужно перевернуть звездочки в другую сторону, так как сестринский селектор выбирает соседей по направлению текста. По умолчанию слева-направо, а нам нужно наоборот.

Для решения этой задачи есть два способа: изменить направления текста для элемента star-rating указав direction: rtl или сделать элемент плавающим по правой стороне. Мне больше по душе второй вариант. Кроме этого сделав элементы внутри .star-rating плавающими мы уберем отступы между звездочками из-за которых пропадает наведение

В общем, дальше уже все обычно. Еще раз ссылка на результат codepen.

В результате у нас полноценный стар-рейтинг со шрифтовыми иконками, написанный только на HTML+СSS в котором легко изменять размеры и цвет звездочек.
Андрей Шабат @Kepler-22b
карма
7,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (23)

  • +2
    Неплохо конечно же, но вы просто слегка изменили решение от Криса Койера на который ссылается сам автор Font Awesome на этой странице.

    А вот что касается отдельного подключения целой таблицы стилей со шрифтом Font Awesome, то это реально громоздко. можно было просто обойтись одной или двумя иконками звездочек.

    Что-то вроде этого:
    .css
    .star-rating__ico:hover:before,
    .star-rating__ico:hover ~ .b-star-rating__ico:before, {
      content: "";
      background-image: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%20id%3D%22imgView%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%22256px%22%20height%3D%22255px%22%20viewBox%3D%220%200%20126.729%20126.73%22%20style%3D%22display%3A%20block%3B%22%20xml%3Aspace%3D%22preserve%22%20class%3D%22detail%20convertSvgInline%20replaced-svg%22%20data-id%3D%2256786%22%20data-kw%3D%22favourites7%22%20fill%3D%22%23FF9800%22%3E%3Cg%3E%3Cpath%20d%3D%22M121.215%2C44.212l-34.899-3.3c-2.2-0.2-4.101-1.6-5-3.7l-12.5-30.3c-2-5-9.101-5-11.101%2C0l-12.4%2C30.3%20%20%20c-0.8%2C2.1-2.8%2C3.5-5%2C3.7l-34.9%2C3.3c-5.2%2C0.5-7.3%2C7-3.4%2C10.5l26.3%2C23.1c1.7%2C1.5%2C2.4%2C3.7%2C1.9%2C5.9l-7.9%2C32.399%20%20%20c-1.2%2C5.101%2C4.3%2C9.3%2C8.9%2C6.601l29.1-17.101c1.9-1.1%2C4.2-1.1%2C6.1%2C0l29.101%2C17.101c4.6%2C2.699%2C10.1-1.4%2C8.899-6.601l-7.8-32.399%20%20%20c-0.5-2.2%2C0.2-4.4%2C1.9-5.9l26.3-23.1C128.615%2C51.212%2C126.415%2C44.712%2C121.215%2C44.212z%22%20style%3D%22%22%20fill%3D%22%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E);
      width: 20px;
      height: 20px;
      display: block;
      background-size: cover;
    }
    

    • +2
      Проще использовать свой шрифт, сделанный на сервисах типа fontello.com

      А вообще, автор поста не открыл Америки. Решение известное и довольно прикольное.
    • –1
      Спасибо за ссылки, решение на Font Awesom не видел. В отрыве от контекста для такой задачи грузить весь Font Awesom, конечно, накладно. Но как я замечаю эта библиотека шрифтов очень часто итак подключена на многих проектах. В Криса Койера не нравиться использование direction rtl, мне кажется с float лучше. Кроме того я максимально изолировал блок рейтинга, что-бы просто скопипастить код и вставить в любое место на сайте.
      • 0
        Вообще, само решение Койера уже давно морально устарело, и реализация через direction rtl является для многих спорным вариантом.
      • 0
        Нет никакого «всего Font Awesome».
        Вы выбираете из него нужные глифы и скачиваете их. Я обычно ставлю 3–10 глоифов на проект, больше не пригождается.
  • +1
    А зачем label-ы? И hover-ы можно обыграть интереснее: codepen.
    • +1
      Псевдо-элементы на элементах с заменяемым содержимым противоречат спецификации и то, что это поддерживает Webkit / Blink вовсе не означает, что так всегда и будет.

      code.google.com/p/chromium/issues/detail?id=480891
      bugzilla.mozilla.org/show_bug.cgi?id=1157575
      • +1
        Да, согласен. Странно, как такое решение работает. Псевдоэлементы before и after нельзя добавлять к одиночным тегам, так как в них нельзя ничего вложить. Хром как-то осилил, Firefox и IE10 в ауте.
        • +1
          Если интересно, то вот тест возможности использования псевдо-элементов в различных элементах: red-team-design.com/wp-content/uploads/2012/06/generated-content-on-replaced-elements-test.html.
          • 0
            Спасибо! Посмотрел исходник в хроме, офигел. В DOM браузер открыл input, вставил туда псевдоэлемент и закрыл — prntscr.com/7tis4r Это жесть какая-то. Не знаю, что именно меня тревожит, но это уже слишком.
          • +1
            Спасибо, очень интересно.
            Не знал, что Blink настолько сошёл с ума.
            <input type="button"> — нет псевдоэлемента.
            <input type="checkbox"> — есть псевдоэлемент.
            

            «Где логика? Где разум?» © известный анекдот.
        • 0
          К одиночным можно, нельзя к заменяемым (replaced). Факт 11 отсюда: www.sitepoint.com/12-little-known-css-facts-the-sequel
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              Интересно, было бы благодарен за ссылку на источник (не сильно ориентируясь в спеке, не нашёл там про область применимость ПЭ). Ну и было бы совсем круто указать на ошибку автору статьи, на которую я сослался.
              • НЛО прилетело и опубликовало эту надпись здесь
      • –1
        Видимо создателям спецификации ничего не говорят такие вещи, как AJAX, DHTML, contenteditable в конце концов. В современном вебе у любого элемента может замениться содержимое, у некоторых это происходит чаше, чем у иного input-а. По этой логике следует отказаться от псевдоэлементов вообще.
        • 0
          Тут дело даже не в спецификации, а в логике. Суть псевдоэлементов в том, что они добавляют виртуальный элемент первым или последним ребенком. В одиночного элемента нету понятий закрывающий и открывающий тег и контент внутри, как, в принципе, там может оказаться другой элемент?
  • 0
    Ну не правильно это как-то считать с конца)
    Лучше как положено с 1 до 5 codepen.io/anon/pen/mJjEMj
    Конечно звездочки немного прыгают, но это скорее всего из-за самого шрифта. Если их подогнать под целые значения и сделать свой шрифт, то все должно стать супер)
  • +2
    А зачем FontAwesome, когда есть ★ и ☆?
    • 0
      К сожалению, они довольно криво рендерятся разными браузерными движками.

      • 0
        Ну или не подходят по дизайну.
  • 0
    Как-то странно, что если одна из звезд чекнута, то ховер срабатывает только на тех, что после нее, а предыдущие как будто дизейблятся. Не думаю, что это ожидаемое поведение.
    • 0
      В этом случае иммхо лучше иметь состояния с разными цветами на чекнутый и на ховер

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.