Списки CSS, маркеры и счетчики

Опубликовано: 2022-03-10
Краткое резюме ↬ Списки стилей в CSS — это больше, чем вы думаете. В этой статье Рэйчел начинает с рассмотрения списков в CSS и переходит к некоторым интересным функциям, определенным в спецификации списков CSS, — маркерам и счетчикам.

Списки в CSS имеют определенные свойства, которые дают нам стандартный стиль списка, который мы ожидаем. Неупорядоченный список получает маркер списка типа disc , а упорядоченные списки нумеруются. Мой интерес к более подробному изучению списков возник после того, как я проделал некоторую работу по документированию ::marker для MDN. Этот псевдоэлемент поставляется в Firefox 68 и выпускается сегодня . Имея доступный нам ::marker , мы можем начать делать некоторые интересные вещи со списками, и в этой статье я объясню больше.

Деконструкция списка

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

Как и многие вещи в CSS, к спискам применяются некоторые начальные значения. Эти значения делают их похожими на список. Эти специальные значения начинаются с информации о том, что элемент списка имеет свойство display со значением list-item . Это создает поле уровня блока с дополнительным полем маркера. В поле маркера добавляется маркер списка или номер.

Еще после прыжка! Продолжить чтение ниже ↓

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

«Элемент с display: list-item генерирует основное блок-бокс для содержимого элемента и, в зависимости от значений list-style-type и list-style-image , возможно, также блок-маркер в качестве визуальной индикации того, что элемент элемент списка».

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

  • disc
  • circle
  • square
  • decimal
  • decimal-leading-zero
  • lower-roman
  • upper-roman
  • lower-greek
  • lower-latin
  • upper-latin
  • armenian
  • georgian
  • lower-alpha
  • upper-alpha
  • none
  • inherit

Спецификация дисплея уровня 3 определяет display: list-item вместе с другими возможными значениями свойства display . Он ссылается на CSS 2.1 — как и многие свойства и значения CSS, происходящие из CSS2 — но описывает ключевое слово list-item как «заставляющее элемент генерировать ::marker ».

Спецификация уровня 3 также вводит возможность создания встроенного элемента списка с использованием синтаксиса с двумя значениями display: inline list-item . Это еще не реализовано браузерами.

Создание полей маркеров на элементах, не входящих в список

Как и в случае с другими значениями display , абсолютно допустимо присвоить любому элементу HTML тип отображения элемента list-item (если вы хотите сгенерировать ::marker для элемента). Это не приведет к тому, что элемент семантически станет элементом списка, но вместо этого он будет отображаться только визуально как элемент списка и, следовательно, сможет иметь ::marker . Когда мы обсудим ::marker ниже, вы обнаружите несколько случаев, когда предоставление другим элементам display: list-item может быть полезным.

Спецификация списков CSS уровня 3: ::marker And Counters

Спецификация display расширяет и уточняет определение списков, которое мы находим в CSS2, однако есть также спецификация, которая подробно определяет поведение списка: Спецификация списков CSS, уровень 3. Поскольку основное поведение элементов списка определено в display , это Спецификация детализирует поле маркера, сгенерированное, когда что-то имеет display: list-item вместе со счетчиками, которые используются по умолчанию всякий раз, когда вы создаете упорядоченный список. Через эти функции можно получить доступ к некоторым потенциально полезным функциям.

::marker

::marker позволяет настроить таргетинг на маркер списка — отдельно от содержимого элемента списка. Это было невозможно в предыдущих версиях CSS, поэтому, если вы изменили цвет или размер шрифта ul или li , это также изменило бы цвет и размер шрифта маркеров. Чтобы сделать что-то, казалось бы, простое, например, иметь маркеры списка другого цвета, чем текст, потребуется либо обернуть содержимое элемента списка в диапазон (или использовать изображение для маркера).

 ul { color: #00b7a8; } ul span { color #333; }

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

 ul { color: #333; } ul ::marker { color: #00b7a8; }

Вы также можете использовать другой размер и font-family для нумерации в упорядоченном списке.

 ol ::marker { font-size: 200%; color: #00b7a8; font-family: "Comic Sans MS", cursive, sans-serif; }

Вы можете увидеть все это в поддерживающем браузере, используя мой пример CodePen:

См. Pen [Цветные маркеры с маркером и без него] (https://codepen.io/rachelandrew/penVJQyoR) Рэйчел Эндрю.

См. пули Pen Colored с маркером и без маркера Рэйчел Эндрю.

Вы можете использовать ::marker для элементов, не входящих в список. В приведенном ниже коде я установил заголовок для display: list-item . Это дает ему пулю и, следовательно, поле ::marker для цели.

Я изменил пулю, чтобы использовать смайлик:

 h1 { display: list-item; } h1::marker { content: ""; } 
Заголовок со смайликом кота слева от него
В Firefox вы можете увидеть смайлик, используемый в качестве маркера.

См. Pen [Заголовок и маркер] (https://codepen.io/rachelandrew/pen/wLyyMG) Рэйчел Эндрю.

См. Заголовок пера и маркер Рэйчел Эндрю.

В приведенном выше примере я использовал сгенерированный контент в правилах для маркера. Только небольшое подмножество свойств CSS доступно для использования в ::marker . К ним относятся свойства шрифта и цвет, однако они также включают свойство content для включения сгенерированного содержимого.

Добавление content в качестве разрешенного свойства для ::marker произошло недавно, однако оно включено в реализацию Firefox. Включение означает, что вы можете делать такие вещи, как включение строки текста в ::marker . Это также открывает дополнительные возможности для форматирования маркеров, когда вы комбинируете использование счетчиков с ::marker .

Поддержка браузера и запасные варианты

Для браузеров, не поддерживающих ::marker , запасной вариант — это обычный маркер, который все равно отображался бы. К сожалению, в настоящее время мы не можем использовать Feature Queries для обнаружения поддержки таких селекторов, как этот псевдоэлемент, хотя возникла проблема с добавлением этого в спецификацию. Это означает, что вы не можете разветвить свой код, чтобы делать что-то одно, когда у вас есть поддержка, и что-то еще, если у вас ее нет. В большинстве случаев возврат к обычному маркеру будет разумным решением.

Счетчики

Упорядоченные списки имеют нумерацию списков — это достигается с помощью счетчика CSS. Поэтому спецификация списков CSS также описывает эти счетчики. Мы можем сами получать доступ к счетчикам и создавать их, что в сочетании с ::marker может дать нам некоторую полезную функциональность. Эти счетчики также можно использовать в обычном (не ::marker ) сгенерированном контенте.

Если у меня есть пронумерованный список шагов (и я хотел бы написать «Шаг 1», «Шаг 2» и т. д.), я могу сделать это, используя сгенерированное содержимое в своем маркере и добавив счетчик list-item , это представляет встроенный счетчик:

 ::marker { content: "Step " counter(list-item) ": "; } 
Упорядоченный список с шагом 1, шагом 2 и т. д. перед каждым элементом списка.
В Firefox вы увидите счетчик со словом «Шаг».

См. Pen [Счетчики и маркер] (https://codepen.io/rachelandrew/pen/BgRaoz) Рэйчел Эндрю.

См. Счетчики ручек и маркер Рэйчел Эндрю.

Вложенные счетчики

Если у вас есть вложенные списки, общий способ их нумерации состоит в том, чтобы иметь элемент верхнего уровня целым числом (1), затем дочерние элементы как (1.1, 1.2) и их дочерние элементы (1.1.1, 1.1.2), и так далее. Вы можете добиться этого, используя больше функциональных возможностей счетчиков.

Когда вы вкладываете HTML-списки, вы получаете несколько счетчиков с одним и тем же именем, вложенных друг в друга. Доступ к вложению счетчиков можно получить с помощью функции counters() .

В приведенном ниже коде я использую counters() для форматирования маркеров списка, как описано выше. Первым аргументом counters() является имя используемого счетчика. Я использую встроенный счетчик list-item . Второй аргумент — это строка — это то, что будет конкатенировано между выходными счетчиками (я использую . ). Наконец, я добавляю : вне функции счетчика, но внутри значения content , чтобы вывод моего счетчика отделялся от содержимого двоеточием.

 ::marker { content: counters(list-item,'.') ':'; color: #00b7a8; font-weight: bold; }

Это дает мне вывод, как на изображении. Если вы используете браузер, который поддерживает ::marker и счетчики, вы можете увидеть, как это работает в примере CodePen — попробуйте изменить строку из файла . на что-то еще, чтобы увидеть, как это меняет вывод.

Набор вложенных списков
В Firefox вы увидите нумерацию вложенных списков, разделенных точками.

См. Pen [Вложенные счетчики] (https://codepen.io/rachelandrew/pen/VJbwxL) Рэйчел Эндрю.

См. счетчики Pen Nested Рэйчел Эндрю.

В чем разница между counter() и counters() ?

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

Функция counters() , по сути, записывает всю эту ветвь и дает вам возможность конкатенировать строку между счетчиками в ветви. Итак, если у вас есть элемент списка со счетчиком 2 (который является частью списка, вложенного в элемент списка со счетчиком 4 ), то ветвь содержит:

  • 4
  • 2

Вы можете вывести это как 4.2 в маркере, используя:

 ::marker { content: counters(list-item,'.'); }

Счетчики на других элементах

Счетчики можно использовать для вещей, которые не являются списками — либо для вывода маркера — в этом случае элемент должен иметь display: list-item — либо для вывода обычного сгенерированного контента. Счетчики широко используются в книжном производстве, чтобы обеспечить нумерацию глав и рисунков и многое другое. Нет причин не использовать аналогичный подход в Интернете, особенно для более длинных статей.

Свойства CSS, определенные в спецификации списков CSS, которые имеют дело с этими счетчиками:

  • counter-set
  • counter-reset
  • counter-increment

Чтобы увидеть, как они работают вне списков, мы можем рассмотреть пример использования счетчиков для нумерации заголовков в документе.

Первое, что мне нужно сделать, это создать счетчик заголовков в элементе body — и он готов к использованию. Для этого я использую свойство counter-reset . Свойства counter-reset и counter-set очень похожи. Свойство counter-reset создаст новый счетчик, если счетчик с указанным именем еще не существует, но также создаст вложенные счетчики, как описано выше, если счетчик с таким именем существует. Свойство counter-set создаст новый счетчик только в том случае, если нет счетчика с таким именем. Для этого использование любого свойства будет работать нормально, однако counter-set не имеет такой хорошей поддержки браузера, как counter-reset , поэтому я выбираю практичный путь:

 body { counter-reset: heading-counter; }

Теперь, когда у меня есть счетчик, я могу использовать свойство counter-increment в селекторе для заголовков; это должно увеличивать счетчик каждый раз, когда селектор совпадает.

 h2 { counter-increment: heading-counter; }

Чтобы увидеть значение, мне нужно вывести его в документ. Я могу сделать это, используя сгенерированный контент и добавив его before заголовком, как показано в следующем примере CodePen:

 h2::before { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; } 

См. Pen [Заголовки и счетчики] (https://codepen.io/rachelandrew/pen/gNGjxq) Рэйчел Эндрю.

См. Заголовки и счетчики пера Рэйчел Эндрю.

В качестве альтернативы я мог бы превратить элемент h2 в элемент list-item а затем использовать ::marker , как показано ниже. Как уже было сказано, использование элемента ::marker имеет ограниченную поддержку браузера. В Firefox вы должны увидеть счетчик, используемый в качестве маркера для заголовка, в то время как другие браузеры будут отображать маркер по умолчанию.

 h2 { display: list-item; } h2::marker { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; } 

См. Pen [Заголовки, маркеры и счетчики] (https://codepen.io/rachelandrew/pen/pXWZay) Рэйчел Эндрю.

См. Заголовки пера, маркеры и счетчики Рэйчел Эндрю.

Счетчики на элементах формы

Существует также небольшая интерактивность, которую вы можете достичь с помощью счетчиков CSS — то, что вы можете подумать, что вам нужен JavaScript.

У меня есть форма, в которой есть несколько обязательных полей. Необходимый статус можно выбрать в CSS с помощью псевдокласса :required , а тот факт, что поле не заполнено, можно определить с помощью псевдокласса :invalid . Это означает, что мы можем проверять поля, которые являются обязательными и недействительными, и увеличивать счетчик. Затем выведите это как сгенерированный контент.

См. Pen [Подсчет обязательных полей формы] (https://codepen.io/rachelandrew/pen/vqpJdM) Рэйчел Эндрю.

См. обязательные поля формы Pen Counting от Рэйчел Эндрю.

Насколько это полезно на самом деле, спорно, учитывая, что мы ничего не можем сделать с этим значением, кроме как вставить его в сгенерированный контент. Есть также опасения, что сгенерированный контент будет недоступен для определенных программ чтения с экрана, поэтому любое использование, выходящее за рамки декоративного, должно обеспечить другие способы доступа к этой информации. Прочтите «Поддержка специальных возможностей для содержимого, созданного с помощью CSS» и более свежую информацию «Совместимость средства чтения с экрана свойств содержимого CSS», чтобы получить дополнительные сведения о доступности и сгенерированном содержимом.

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

Узнать больше

Эта статья оказалась довольно далекой от списков стилей, несмотря на то, что все, что я описал, находится в спецификации списков CSS. Вы можете найти больше информации о вещах, описанных по ссылкам ниже. Если вы нашли интересное применение счетчикам CSS или можете придумать, для чего можно использовать ::marker , добавьте примечание в комментариях.

  • ::marker
  • counter-set
  • counter-reset
  • counter-increment
  • «Использование счетчиков CSS», веб-документы MDN
  • «Подсчет с помощью счетчиков CSS и сетки CSS», CSS-Tricks