Pull to refresh

CSS counters

Reading time 7 min
Views 33K

Одной из редко используемых возможностей CSS2.1 являются счетчики. Описаны они в разделе спецификации, посвященной генерации контента. Что же это такое?

Приведу пример из спецификации, эмулирующий обычный нумерованый список с помощью счетчика и свойства content:
OL { counter-reset: item }
LI { display: block }
LI:before { content: counter(item) ". "; counter-increment: item }

Первым правилом мы назначаем элементам OL счетчик с именем «item», затем для всех LI меняем значение свойства display на block, вместо значения по умолчанию (list-item), чем отключаем стандартные маркеры-цифры. Наконец, в последнем правиле, мы инкрементируем счетчик для каждого элемента списка, а само его значение показываем перед элементом c помощью функции counter() и свойства content. Всё просто.


С помощью механизма счетчиков можно делать нумерованые списки, с нумерацией 1, 1.1, 1.2. Причем сами маркеры можно оформлять достаточно гибко например в результате вот такого кода:
<style>
OL { counter-reset: item }
LI { display: block }
LI:before { content: "{" counters(item, ".") "} "; counter-increment: item; font-weight:bold }
</style>

<ol>
    <li>item 1, level 1</li>
    <li>item 2, level 1</li>
    <li>item 3, level 1</li>
    <li>item 4, level 1
        <ol>
            <li>item 1, level 2</li>
            <li>item 2, level 2</li>
            <li>item 3, level 2</li>
        </ol>
    </li>
    <li>item 5, level 1</li>
</ol>


* This source code was highlighted with Source Code Highlighter.

мы получим вот такой список:



Функция counters() принимает два параметра, имя счетчика, значение которого нужно вывести и строку-разделитель между значениями вложенных счетчиков, в данном случае это точка. Также вторым параметром можно указывать любое из возможных значений атррибута list-style-type, т.е. none, disc, circle и square. В последних трех случаях список станет выглядеть так же как обычный ненумерованный список с маркерами соответствующего типа.

Но и это еще не всё


С помощью счетчиков можно реализовать то, что совсем недавно делалось исключительно с помощью скриптов — считать элементы, и выводить результат подсчета на странице. Например результатом такого кода:
<style>
    div {counter-reset: num-p} /* объявляем счетчик num-p */
    div p {counter-increment: num-p;margin:0} /* для каждого p внутри div инкрементируем его */
    div:after {    /* выводим результат */
        display:block;font-weight:bold;
        content: "Всего абзацев: " counter(num-p)    ".";
    }
</style>
<div>
    <p>Абзац 1</p>
    <p>Абзац 2</p>
    <p>Абзац 3</p>
    <p>Абзац 4</p>
</div>


* This source code was highlighted with Source Code Highlighter.

станет вот такая страница:



Здесь мы воспользовались псевдоэлементом :after элемента div, для вывода конечного значения привязанного к нему счетчика.

Ну и наконец приведу код, результат которого вы видели на изображении в самом начале топика, если вы подключите этот стиль в качестве пользовательского стиля вашего браузера, то возле каждого топика у вас появится «немного статистики» о нем:

    /* Инициализируем счетчики */
    div.hentry {
        counter-reset:
            num-post-sections 1
                /* Количество заголовков/секций в топике. Обратите внимание, что счетчику можно передать начальное значение. */
                /* В данном случае это единица, потому что один заголовок уже есть вне блока .content */
            num-code-listings  /* Листинги кода code и pre */
            num-bq             /* цитаты */
            num-br             /* break-lines */
            num-links          /* ссылки */
            num-links-internal /* внутренние ссылки */
            num-links-rel-tag  /* ссылки тэгов rel='tag' */
            num-img             /* изображения */
        ;
    }
    /* Инкрементируем счетчики. */
    div.hentry .content h4,
    div.hentry .content h5,
    div.hentry .content h6 { counter-increment: num-post-sections; }
    div.hentry .content code,
    div.hentry .content pre { counter-increment: num-code-listings; }
    div.hentry .content img { counter-increment: num-img; }
    div.hentry .content blockquote { counter-increment: num-bq; }
    div.hentry .content br { counter-increment: num-br; }
    
    div.hentry .content a[href] {     /* все ссыкли */
            counter-increment: num-links;
    }
    div.hentry .content a[href^="http://habrahabr.ru/"],
    div.hentry .content a[href^="/"] { /* внутренние ссыкли */
            counter-increment:
                num-links
                num-links-internal;
    }
    div.hentry a[rel="tag"] { /* теги */
            counter-increment:
                num-links
                num-links-rel-tag;
    }
    /* Показываем результат счетчиков */
    div.hentry:after {
        clear:both;
        display: block;
        background:#9cc;
        border:1px solid #79B1D4;
        padding:10px;
        margin:0 35px;
        white-space:pre;
        content:
            "This topic contains: \a"
            "Sections - " counter(num-post-sections) ",\a"
            "Code listings - " counter(num-code-listings) ",\a"
            "Links - " counter(num-links) ", " counter(num-links-internal) " internal and "
            counter(num-links-rel-tag)" tags, \a"
            "Images - " counter(num-img) ",\a"
            "Quotes - " counter(num-bq) ",\a"
            "Break lines - " counter(num-br) "\a"
        ;
    }


* This source code was highlighted with Source Code Highlighter.


Ограничения


1. К сожалению, всеми нами горячо и страстно любимый браузер Intenet Explorer — не поддерживает CSS-счетчики вплоть до версии 7, как и свойство content. Но в 8-й, говорят поддержка будет.
2. Вывод суммарных счетчиков возможен только в псевдоэлементе :after, что ограничивает возможности дизайна.
3. Контент, сгенеренный с помощью css не может быть выбран/выделен пользователем.

Исходя из ограничений, описываемые возможности пока врядли найдут широкое применение, но думаю светлое будущее не за горами. Весь код был написан только для того, чтобы показать вам эти возможности :)

Upd. В написании топика и кода сильно помогла статья Meitar Moscovitz, там есть еще неплохие примеры.
Tags:
Hubs:
+76
Comments 27
Comments Comments 27

Articles