Пять звёздочек без JavaScript

Vladimir
Опубликовано в: CSS, HTML

Кросс-браузерный вариант реализации механизма рейтинга без использования JavaScript

Прочитал сегодня статью "Пять звёздочек" на Pepelsbey.net. Автор описывает очень интересный подход для реализации механизма рейтингов; основное преимущество описываемого подхода — минимум JavaScript за счет грамотного использования CSS.

Решение Вадима основано на использовании CSS rollovers, плавающих элементах и z-index и выглядит очень красиво. Особенно меня впечатлило то, что его решение будет работать с выключенной загрузкой изображений и отключенным CSS. Весьма приятно, ибо о usability отечественные разработчики задумываются далеко не всегда.

Среди недостатков отмечу следующие:

  1. При использовании IE6 с выключенным JavaScript вся красота перестаёт работать (оффтопик: не могу понять, по каким причинам народ до сих пор сидит на IE6?)
  2. Некоторое неудобство при изменении шкалы: например, если изменить код так, чтобы можно было учитывать полбалла, то помимо ширин придется менять и z-index каждого элемента a. Хотя, в принципе, это мелочь.

Полгода назад я какое-то работал над проектом myfolio.com, там тоже применялось пятизвёздочное голосование (правда, принцип несколько другой). Считая, что тот подход тоже имеет право жить :-) , привожу его здесь.

Разметка очень проста:

[-]
View Code HTML
    <!--[if lte IE 6]><a class="ievote" href="#"><table cellpadding="0" cellspacing="0"><tbody><tr><td><![endif]-->
    <ul class="vote">
        <li class="ten"><a href="#rated=10" title="5 stars">5.0</a></li>
        <li class="nine"><a href="#rated=9" title="4.5 stars">4.5</a></li>
        <li class="eight"><a href="#rated=8" title="4 stars">4.0</a></li>
        <li class="seven"><a href="#rated=7" title="3.5 stars">3.5</a></li>
        <li class="six"><a href="#rated=6" title="3 star">3.0</a></li>
        <li class="five"><a href="#rated=5" title="2.5 stars">2.5</a></li>
        <li class="four"><a href="#rated=4" title="2 stars">2.0</a></li>
        <li class="three rated"><a href="#rated=3" title="1.5 stars">1.5</a></li>
        <li class="two"><a href="#rated=2" title="1 star">1.0</a></li>
        <li class="one"><a href="#rated=1" title="0.5 stars">0.5</a></li>
    </ul>
    <!--[if lte IE 6]></a></td></tr></tbody></table><![endif]-->

Про условные комментарии вокруг элемента ul можно прочитать в статье "Кросс-браузерное одноуровневое вертикальное меню без JavaScript".

Из особенностей — нумерация идёт в обратном порядке (это связано отказом от float и z-index, ибо код в myfolio был гораздо сложнее и с z-index возникали некоторые проблемы в IE6).

Теперь самое интересное: стили:

[-]
View Code CSS
.vote, .vote li.rated, .vote li a:hover {
    background: url(stars.gif) no-repeat 0 0;
}

/* Небольшая особенность: если задавать цвет, то картинка не должна быть прозрачной.
Задание цвета используется для тех, кто выключил загрузку изображений в настройках браузера.
В этом случае пользователь увидит нечто наподобие progress bar (но это всё же лучше, чем ничего).
*/

.vote li.rated, .vote li a:hover {
    background-color: red;
}

.vote {
    background-position: 0 -14px;
}

.vote:hover li, .ievote:hover li {
    background: none;
}

.vote {
    width: 80px;
    overflow: hidden;
    position: relative;
}

.vote, .vote li, .vote li a {
    height: 14px;
    display: block;
}

.vote li {
    position: absolute;
}

.vote, .vote li {
    left: 0;
    top: 0;
    list-style: none;
    margin: 0;
    padding: 0;
}

.vote li a {
    overflow: hidden;
    text-indent: -100px;
    outline: 0;
}

/* Задаем ширину каждого балла; каждый последующий балл включает в себя предыдущий*/
.vote li.one   { width: 7px;  }
.vote li.two   { width: 16px; }
.vote li.three { width: 23px; }
.vote li.four  { width: 32px; }
.vote li.five  { width: 39px; }
.vote li.six   { width: 48px; }
.vote li.seven { width: 55px; }
.vote li.eight { width: 64px; }
.vote li.nine  { width: 71px; }
.vote li.ten   { width: 80px; }

/* Для IE6 */
.ievote {
    text-decoration: none !important;
}

Наконец, страница с рабочим примером.

Достоинства метода:

  1. Метод кросс-браузерный, работает даже при отключенной загрузке изображений и выключенном CSS;
  2. Превосходно работает даже при отключённом JavaScript (в том числе, и в IE6);
  3. Благодаря использованию CSS rollover достаточно всего лишь одного HTTP-запроса (в отличие от реализаций, где используются списки с элементами img).

Еще одно красивое решение от site-creator.info.

Добавить в закладки

Связанные записи

30
Май
2008

Комментарии к статье «Пять звёздочек без JavaScript» (3)  »

  1. Vladimir says:

    Любителям семантической вёрстки посвящается…

    Если говорить о семантике, то, все-таки, необходимо использовать input type=”radio”

    Отмечу сразу: я против :-)

    Во-первых, из-за того, что элементы формы поганить нехорошо (с точки зрения usability). То есть если пользователь привык, что радиокнопка выглядит именно так, то именно так она и должна выглядеть. Да и более того, браузеры не дают слишком уж извращать внешний вид элементов формы. То есть, если мы хотим нарисовать background поверх радиокнопки, то нам либо придется прятать радиокнопку (потому что она будет нарисована поверх фона, либо прятать ее под какой-нибудь элемент).

    Во-вторых, из-за того, что появится много лишнего JavaScript: нам по сути нужно будет обработать три ситуации:

    1. Загрузка изображений отключена: мы не должны менять внешний вид формы (из-за usability): изображений нет, а превращать элементы в progress bar в данном случае будет отвратительным решением;
    2. JavaScript отключен: в этом случае пользователь должен видеть кнопку “Проголосовать”
    3. Изображения и JavaScript отключены: самый крайний, но вероятный случай. На мой взгляд, мы в этом случае не должны вообще пытаться изменить стили формы: если картинки отключены, то пользователь увидит не пойми что :-)

    Ладно, теперь от слов переходим к делу.

    Разметка:

    [-]
    View Code HTML
        <form id="vote" action="?" method="get">
            <label class="ten" for="r10"><input type="radio" name="rate" value="10" id="r10"/>5.0</label>
            <label class="nine" for="r9"><input type="radio" name="rate" value="9" id="r9"/>4.5</label>
            <label class="eight" for="r8"><input type="radio" name="rate" value="8" id="r8"/>4.0</label>
            <label class="seven" for="r7"><input type="radio" name="rate" value="7" id="r7"/>3.5</label>
            <label class="six" for="r6"><input type="radio" name="rate" value="6" id="r6"/>3.0</label>
            <label class="five" for="r5"><input type="radio" name="rate" value="5" id="r5"/>2.5</label>
            <label class="four" for="r4"><input type="radio" name="rate" value="4" id="r4"/>2.0</label>
            <label class="three rated" for="r3"><input type="radio" name="rate" value="3" id="r3" checked="checked"/>1.5</label>
            <label class="two" for="r2"><input type="radio" name="rate" value="2" id="r2"/>1.0</label>
            <label class="one" for="r1"><input type="radio" name="rate" value="1" id="r1"/>0.5</label>
            <input type="submit" value="Vote"/>
        </form>

    Стили (примечание: если требуется поддержка IE6, используйте whatever:hover):

    [-]
    View Code CSS
    .vote, .vote label.rated {
        background: url(stars.gif) no-repeat 0 0;
    }

    html>body .vote label:hover, html>body .vote:hover label:hover {
        background: url(stars.gif) no-repeat 0 0;
    }

    * html body .vote label:hover { /* For IE6 w/whatever:hover */
        background: url(stars.gif) no-repeat 0 0 !important;
    }

    .vote {
        background-position: 0 -14px;
        position: relative;
    }

    .vote:hover label.rated {
        background: none !important; /* !important is for IE6 w/whatever:hover */
    }

    .vote label {
        height: 14px;
        position: absolute;
        text-indent: -1000px;
        z-index: 2;
        overflow: hidden;
    }

    .vote, .vote label {
        left: 0;
        top: 0;
        margin: 0;
        padding: 0;
    }

    .vote label.one   { width: 7px;  }
    .vote label.two   { width: 16px; }
    .vote label.three { width: 23px; }
    .vote label.four  { width: 32px; }
    .vote label.five  { width: 39px; }
    .vote label.six   { width: 48px; }
    .vote label.seven { width: 55px; }
    .vote label.eight { width: 64px; }
    .vote label.nine  { width: 71px; }
    .vote label.ten   { width: 80px; }

    .vote input {
        visibility: hidden;
    }

    .vote label input {
        visibility: visible;
        width: 0;
    }

    И, наконец, JavaScript (я использую Prototype; кому что ближе):

    [-]
    View Code Javascript
    var img = new Image();
    img.onload = function()
    {
        $('vote').addClassName('vote').select('input[type="radio"]').invoke('observe', 'click', function(e) { e.element().form.submit(); } );
    }

    img.src = 'stars.gif';

    Результат.

    Внимание: я не тестировал пример во всех браузерах, поэтому кросс-браузерность гарантировать не могу.

    Проверено в IE6/7, FF, Opera, Konqueror.


    Замечания:

    1. Для того, чтобы код работал в IE6, метки (label) должны иметь атрибут for, связывающий их с соответствующей радиокнопкой.
    2. Опять же, из-за IE6 радиокнопки не должны иметь visibility: hidden или display: none. Их нужно либо сдвинуть за label, либо, как в примере, поставить нулевую ширину. Если скрывать label, то обработчик должен вешаться не на input[type="checkbox"], а на label, и код в этом случае немного усложнится.
    3. При медленном соединении/компьютере возможны гонки между whatever:hover и img.onload(). Для правильной работы img.onload() должен сработать первым.
    • Jman says:

      а для второго решения (с радиобутонами) есть пример, чтобы посмотреть его в деле? Лень копипастить :)

      Капча злая, вроде правильно пишу… а говорит неверный код

  2. Jman says:

    Вот блин, извниняюсь… совсем ослеп. ссылку на пример нашёл

Подписаться на RSS-ленту комментариев к статье «Пять звёздочек без JavaScript» Trackback URL: http://blog.sjinks.org.ua/css/173-five-stars-without-javascript/trackback/

Оставить комментарий к записи «Пять звёздочек без JavaScript»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя