Статьи

Малоизвестный способ заменить некоторые скрипты счетчиками CSS

С тех пор, как Эрик Мейер подчеркнул, насколько мощен CSS в его коллекции css / edge , мы искали способы заменить эффекты, которые когда-то были возможны только при использовании JavaScript, на эквиваленты на основе CSS. Замена исполняемых сценариев таблицами стилей часто повышает производительность и приводит к более доступной странице. Одним из самых ранних примеров этого были Эрик Pure CSS Popups , эффект, который он кратко суммировал, когда текст появляется и исчезает без JavaScript, чтобы управлять им .

По мере того, как улучшаются CSS и улучшаются реализации, все больше и больше возможно только с использованием таблиц стилей и без необходимости в дополнительных сценариях на внешней или внутренней стороне сайта, что уменьшает объем исполняемого кода. Одна возможность, которая меня недавно осенила, заключалась в том, что, используя только биты сгенерированных свойств контента CSS2.1, мы можем собирать и предоставлять дополнительную информацию о целых частях страниц.

Как и во многих других блогах, сообщения блога SitePoint содержат небольшой абзац метаданных в конце каждого сообщения. Этот параграф предоставляет читателям дополнительную информацию о публикации, такую ​​как дата публикации, теги и любые категории, под которыми размещается публикация. Давайте посмотрим, как легко мы можем добавить к этому новую информацию, используя только CSS.

Использование (и злоупотребление?) CSS-счетчиками

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

Что действительно интересно в CSS-счетчиках, так это то, что поскольку отображение счетчика не связано с самим механизмом подсчета, мы можем использовать их для отображения общего количества элементов в дополнение к простой нумерации элементов в серии.

Вкратце, вот как спецификация CSS2.1 говорит, что мы можем заменить числовые маркеры типичного упорядоченного списка счетчиком CSS для достижения более или менее эквивалентного визуального результата:

ol { counter-reset: item; } ol li { display: block; } ol li:before { counter-increment: item; content: counter(item)". "; } 

Этот код инициализирует счетчик с именем item для каждого элемента ol . Затем он превращает все элементы li в CSS-блоки block вместо их стандартных list-item чтобы они не отображали маркер (т. Е. Число или маркер из свойства list-style-type ). Наконец, для каждого элемента списка он увеличивает счетчик item , а затем отображает его текущее значение.

Теперь, вот как мы можем использовать тот же механизм для отображения количества элементов списка в конце списка с незначительными и совершенно корректными изменениями:

 ol { counter-reset: item; } ol li { display: block; counter-increment: item; } ol:after { display: block; content: "Number of items in this list: " counter(item) "."; } 

Единственная хитрость — не вызывать функцию counter() более одного раза. В частности, вы называете это только :after того, :after вы закончили увеличивать счетчик для каждого элемента, который вы считаете. Используя это, вы можете видеть, что счетчики CSS похожи на целочисленную переменную ограниченного типа.

Благодаря этим двум обобщенным возможностям — счетчикам CSS и контенту, сгенерированному CSS, — мы можем начать проявлять креативность.

Творчество: подсчет вещей в блоге

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

 /* Initialize counter to 1 (not 0) since titles are outside .entrytext but may include intro paras. */ .post { counter-reset: num-post-sections 1; } .post .entrytext h2 { counter-increment: num-post-sections; } #thisentry:after { content: "This entry has " counter(num-post-sections) " sections."; } 

Приведенный выше код просто увеличивает счетчик, называемый num-post-sections каждый раз, когда элемент h2 встречается в entrytext post , а затем отображает результат в конце, как в предыдущем примере подсчета элементов списка.

Конечно, вы не ограничены просто считать одну вещь. Вот как можно подсчитать количество разделов и количество фрагментов кода в сообщении блога SitePoint, используя один и тот же шаблон:

 .post { counter-reset: num-post-sections 1 /* titles outside .entrytext but may include intro paras */ num-code-listings ; } .post .entrytext h2 { counter-increment: num-post-sections; } /* match both with (pre>code) and without (table.dp-c) JavaScript code highlighting */ .post .entrytext pre > code, table.dp-c { counter-increment: num-code-listings; } #thisentry:after { content: "This entry has " counter(num-post-sections) " sections and " counter(num-code-listings) " code listings." ; } 
Снимок экрана с этим сообщением в блоге SitePoint с примененным отрывком CSS.

Снимок экрана с этим сообщением в блоге SitePoint с примененным отрывком CSS.

В качестве шаблона это становится более полезным, если мы обобщим вышеупомянутые правила CSS для SitePoint, чтобы они работали для любого блога, посты которого структурированы с использованием микроформата hAtom , поэтому вы можете использовать его на многих сайтах или вставить в свой собственный браузер. как таблица стилей пользователя . Единственными необходимыми изменениями являются CSS-селекторы , но вы можете стать очень модными. Для примера я добавил несколько дополнительных счетчиков, чтобы проиллюстрировать больше возможностей того, что вы можете сосчитать.

 /* Initialize counters. */ .hentry { counter-reset: num-post-sections num-code-listings num-code-listings-css /* code listings that are specifically CSS */ num-links num-links-internal /* links to other blog posts on this site */ num-links-rel-tag /* rel-tag microformat */ ; } /* Increment counters. */ .hentry h2, .hentry h3, .hentry h4, .hentry h5, /* consider any headline an additional "section" */ .hentry h6 { counter-increment: num-post-sections; } .hentry pre > code { counter-increment: num-code-listings; } .hentry pre > code.css { counter-increment: num-code-listings /* increment count of total code listings */ num-code-listings-css /* AND the subset that are just CSS samples */ ; } .hentry :link { counter-increment: num-links; } .hentry :link[href^="/blogs/"] { counter-increment: num-links num-links-internal ; } .hentry :link[rel="tag"] { counter-increment: num-links num-links-rel-tag; } /* Display results. */ .hentry:after { display: block; content: "This entry has a total of " counter(num-post-sections) " sections, " counter(num-code-listings) " code listings " "(" counter(num-code-listings-css) " are CSS) " " and " counter(num-links) " links, " "of which " counter(num-links-internal) " point to other blog posts on this site " " and " counter(num-links-rel-tag) " are tags." ; } 

Естественно, вы можете рассчитывать только то, на что вы можете ориентироваться с помощью селектора CSS, поэтому генерация количества слов невозможна. Кроме того, вы можете отображать только итоги в сгенерированном контенте, который приходит :after всей разметки, которую вы хотите посчитать, а не :before нее. Очевидно, что эта деталь реализации может ограничить гибкость вашего дизайна.

Наконец, стоит еще раз подчеркнуть, что CSS-счетчики не реализованы в IE 6 или 7 (вздох…). Кроме того, поскольку мы имеем дело исключительно с контентом, сгенерированным CSS, отображаемый текст не может быть выбран пользователем или доступен через DOM для дальнейшей манипуляции. И, конечно же, во многих случаях вы можете захотеть поместить такие вещи прямо в вашу разметку как «реальный» контент.

Однако, возможно, более важным моментом, чем эти ограничения, является то, что это мощная демонстрация того, как вы можете использовать свою разметку в качестве API, чтобы позволить продвигающимся возможностям CSS делать то, что вы могли когда-то делать только с использованием сценариев на стороне клиента или сервера. , Теперь это захватывающе.