Развлечения с CSS-счётчиками

Перевод статьи Уилла Бойда «Fun Times with CSS Counters» с сайта codersblock.com.

CSS-счетчики — одна из тех интересных возможностей CSS, про которые хочется сказать «ух ты, не знал, что CSS так умеет». Проще говоря, они позволяют вам считать элементы по порядку в CSS – без использования JavaScript.

Базовый счётчик

Для начала здесь представлен простой пример с пагинацией:

Цифры, которые вы видите, не жестко вписаны в HTML. Они сгенерированы в CSS следующим образом:

body {
counter-reset: pages; // инициализация счётчика
}
 
a {
counter-increment: pages; // приращение счётчика
}
 
a::before {
content: counter(pages); // отображение счётчика
}

Свойства счётчика применяются по мере того, как соответствующий элемент встречается в документе. Элемент body встречается первым, инициализируя счётчик, названный «pages». Затем в дереве документа идут элементы a, каждый из которых приращивает значение счётчика «pages» и отображает его.

Множественные счётчики

Вы можете использовать множественные счётчики, просто задавая разные имена. В этом примере показаны два параллельных счётчика, sections и boxes:

Соответствующий CSS:

body {
counter-reset: sections boxes;
}
 
section {
counter-increment: sections;
}
 
section::before {
content: 'Section ' counter(sections);
}
 
.box {
counter-increment: boxes;
}
 
.box::before {
content: counter(boxes, upper-roman);
}

Здесь вы можете видеть синтаксис для инициализации сразу нескольких счётчиков (строка 2). И чтобы быть совсем уж модным, счётчик boxes отображается как upper-roman (строка 18). Полный список вариантов отображения является точно таким же, как и для list-style-type, задокументированный здесь.

Подсчет выбранных вариантов

Теперь давайте перейдём к развлечениям. Свойства счётчика могут размещаться в таких псевдоселекторах, как :checked. Это позволяет счётчикам реагировать на выбранные пользователем при помощи чекбоксов варианты. В этом примере ведётся подсчёт того, сколько вариантов выбрал пользователь.

Представленный здесь CSS не так уж далеко ушел от наших предыдущих примеров. Различия только в том, что мы увеличили счётчик у псевдоселектора (input:checked) и отобразили его только один раз в специальном элементе .total:

body {
counter-reset: characters;
}
 
input:checked {
counter-increment: characters;
}
 
.total::after {
content: counter(characters);
}

Управление приращиванием

Приращение счетчика не обязано быть равным 1. Оно может быть каким угодно целым числом. Оно может быть даже отрицательным. Опираясь на наш предыдущий пример, на этот раз установим конкретные значения приращений для каждого выбранного варианта.

Синтаксис достаточно прост:

body {
counter-reset: sum;
}
 
#a:checked { counter-increment: sum 64; }
#b:checked { counter-increment: sum 16; }
#c:checked { counter-increment: sum -32; }
#d:checked { counter-increment: sum 128; }
#e:checked { counter-increment: sum 4; }
#f:checked { counter-increment: sum -8; }
 
.sum::before {
content: '= ' counter(sum);
}

Кстати, если уж зашёл разговор, мы также можем управлять начальным значением счётчика:

body {
counter-reset: kittens 41; // начиная с 41 котенка
}

Не попадитесь!

Элемент с display: none не будет приращивать счётчик. Если вы захотите скрыть элемент, но всё еще учитывать его в счетчике, то вы должны скрывать его другим способом. Вот один из вариантов:

input {
position: absolute;
left: -9999px;
}

Поддержка браузерами CSS-счётчиков превосходная. Зеленый свет по всем направлениям.

Несмотря на то, что CSS-счётчики такие замечательные, не забывайте о наших старых друзьях <ol> и <li>. Они всё ещё отлично подходят для базового списка нумерованных пунктов. Именно в более хитрых ситуациях можно извлечь пользу из CSS-счётчиков, тем более что они работают на любых элементах, давая вам больше свободы в синтаксисе и в семантике.

Обновление: Мне бы следовало упоминуть о доступности. CSS-счётчики зависят от сгенерированного контента в псевдоэлементах. Некоторые скринридеры подхватят этот контент, а некоторые нет. Из-за этого, лучше не полагаться на псевдоэлементы в важном контенте. Примеры, которые продемонстрированы в этой статье, были подготовлены для изучения интересных способов использования CSS-счётчиков, но я бы не стал применять их в реальных проектах, в таком виде, в котором они есть.

P.S. Это тоже может быть интересно:

6 Комментарии

  1. Denis

    Спасибо за статью. Хорошо и исчерпывающе написано. У меня вопрос по этому поводу: стоит ли этот способ использовать для нумерации таблиц и рисунков в статьях? Или есть другой способ?

    Спасибо.

    1. Максим Усачев (Автор записи)

      А почему бы и нет? Если это решает задачу (тех. задание) и не испортит вёрстку в будущем, если, например, прибавятся ещё блоки, то я бы смело использовал:)

      1. Denis

        Нумерацию хочу делать в Joomla! в статье для подписей как в Word, например, Рисунок 1, Рисунок 2. Не думаю, что там дополнительные блоки повредят верстку. Или Вы о каки-то особых блоках говорите?

        1. Максим Усачев (Автор записи)

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

    2. SelenIT

      На мой взгляд, с любым генериуемым контентом — и счетчиками в том числе — нужно учитывать, что он всё-таки не совсем контент, а скорее часть оформления (напр. не из всех браузеров он копируется в буфер). Так что если номера таблиц и картинок привязаны к контенту (напр., в тексте статьи есть фразы вроде «см. рис. 2.1» и «как следует из таблицы 14.4…»), то они и должны быть в контенте, текстом, а не в CSS. Но если контент от нумерации не зависит, и она нужна чисто для красоты и наглядности (напр. подсчет фото в галерее или товаров в каталоге) — то почему бы и нет?

  2. Denis

    Максим, SelenIT, спасибо вам за помощь. Картинка стала прояснятся по применению счётчиков.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

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