Креативный стиль списка

Взгляните на некоторые полезные и креативные способы оформления списка.

Что приходит на ум, когда вы думаете о списке? Самый очевидный пример — список покупок — самый простой из списков, набор элементов в произвольном порядке. Но в Интернете мы используем списки по-разному. Коллекция предстоящих концертов в каком-либо месте? Скорее всего, список. Многоэтапный процесс бронирования? Вполне возможно, список. Галерея изображений? Даже это можно считать списком изображений с подписями.

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

Когда использовать список

Элемент списка HTML следует использовать, когда элементы необходимо семантически сгруппировать. Вспомогательные технологии (например, программы чтения с экрана) уведомят пользователя о наличии списка и количестве элементов. Если вы подумаете, скажем, о сетке товаров на торговом сайте, знание этой информации будет очень полезно. Поэтому использование элемента списка может быть хорошим выбором.

Типы списков

Когда дело доходит до разметки, нам доступны на выбор три различных элемента списка:

  • Неупорядоченный список
  • Упорядоченный список
  • Список описаний

Какой из них выбрать, зависит от варианта использования.

Неупорядоченный список (ул)

Элемент неупорядоченного списка ( <ul> ) наиболее полезен, когда элементы в списке не соответствуют какому-либо определенному порядку. По умолчанию это отображается в виде маркированного списка. Примером может служить список покупок, где порядок не имеет значения.

Список покупок таких товаров, как хлеб, молоко, яблоки.

Более распространенный пример в Интернете — меню навигации. При создании меню рекомендуется заключать ul в элемент nav и идентифицировать меню с помощью метки, чтобы помочь вспомогательным технологиям. Нам также следует определить текущую страницу в меню, что мы можем сделать с помощью атрибута aria-current :

<nav aria-label="Main">  
  <ul>  
    <li>  
      <a href="/page-1" aria-current="page">Menu item 1</a>  
    </li>  
    <li>  
      <a href="/page-2">Menu item 2</a>  
    </li>  
    <li>  
      <a href="/page-2">Menu item 2</a>  
    </li>  
      …  
    </ul>  
</nav>  

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

Заказанный список (ол)

Элемент упорядоченного списка ( <ol> ) — лучший выбор, когда порядок элементов важен, например, в многоэтапном процессе. По умолчанию элементы списка пронумерованы. Примером может быть набор инструкций, шаги которых необходимо выполнять по порядку.

Список с подробным описанием шагов, необходимых для приготовления чая с молоком.

Элементы <ol> и <ul> могут содержать только элементы <li> в качестве своих прямых дочерних элементов.

Список описаний (дл)

Список описаний содержит термины (элементы <dt> ) и описания ( <dd> ). Каждый термин может сопровождаться более чем одним описанием. Возможные варианты использования могут включать глоссарий терминов или, возможно, меню ресторана. Списки описаний по умолчанию не отображаются с какими-либо маркерами, хотя браузеры имеют тенденцию делать отступ для элемента <dd> .

В HTML разрешено группировать термины с сопровождающими их описаниями с помощью <div> . Как мы увидим позже, это может быть полезно для стилизации.

<!-- This is valid --> 
<dl>  
    <dt>Term 1</dt>  
    <dd>This is the first description of the first term in the list</dd>  
    <dd>This is the second description of the first term in the list</dd>  
    <dt>Term 2</dt>  
    <dd>This is the description of the second term in the list</dd>  
</dl>

<!-- This is also valid --> 
<dl>  
    <div>  
        <dt>Term 1</dt>  
        <dd>This is the first description of the first term in the list</dd>  
        <dd>This is the second description of the first term in the list</dd>  
    </div>  
    <div>  
        <dt>Term 2</dt>  
        <dd>This is the description of the second term in the list</dd>  
    </div>  
</dl>  

Простое оформление списка

Одно из самых простых применений списка — внутри блока основного текста. Довольно часто эти простые списки не требуют сложного оформления, но мы можем захотеть в некоторой степени настроить маркеры упорядоченного или неупорядоченного списка, например, с помощью цвета бренда или используя собственное изображение для наших маркеров. Мы можем многое сделать с помощью list-style и псевдоэлемента ::marker !

::маркер

Помимо придания нашим маркерам списка базового стиля, мы можем создавать циклические маркеры. Здесь мы используем три разных URL-адреса изображений для значения content псевдо-элемента ::marker , что добавляет ощущение рукописности нашего примера со списком покупок (в отличие от использования одного изображения для всех):

::marker {  
    content: url("/marker-1.svg") ' ';  
}

li:nth-child(3n)::marker {  
    content: url("/marker-2.svg") ' ';  
}

li:nth-child(3n - 1)::marker {  
    content: url("/marker-3.svg") ' ';  
}  

Пользовательские счетчики

Для некоторых упорядоченных списков мы можем использовать значение счетчика, но добавить к нему другое значение. Мы можем использовать счетчик list-item в качестве значения свойства content нашего маркера и добавлять любой другой контент:

::marker {  
    content: counter(list-item) '🐈 ';  
}  

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

li {  
    counter-increment: list-item 3;  
}  

С помощью счетчиков мы могли бы еще много чего углубиться. В статье « Списки CSS, маркеры и счетчики» некоторые возможности рассматриваются более подробно.

Ограничения стиля ::marker

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

Стилизация списков, которые не похожи на списки

Иногда нам может потребоваться стилизовать наши списки совершенно иначе, чем стиль по умолчанию. Это часто происходит, например, с навигационным меню , где мы обычно хотим удалить все маркеры и можем отобразить наш список горизонтально, используя флексбокс. Обычной практикой является установка свойства list-style в none . Это будет означать, что псевдоэлемент маркера больше не будет доступен в DOM.

Пользовательские маркеры с ::before

Стилизация псевдоэлемента ::before была распространенным способом создания пользовательских маркеров списка до появления ::marker . Но даже сейчас это может дать нам больше гибкости, когда нам это нужно, для визуально сложного оформления списка.

Как и ::marker , мы можем добавлять собственные стили маркеров, используя атрибут content . В отличие от использования ::marker , нам нужно выполнить позиционирование вручную, поскольку мы не получаем автоматических преимуществ, предлагаемых list-style-position . Но мы можем относительно легко позиционировать его с помощью flexbox, и это открывает больше возможностей для выравнивания. Например, мы могли бы изменить положение маркера:

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

li::before {  
  counter-increment: list-item;  
  content: counter(list-item);  
}  

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

Список атрибутов

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

Перевернутые списки

Если у нас есть список 10 лучших альбомов прошлого года, мы, возможно, захотим посчитать от 10 до 1. Для этого мы могли бы использовать собственные счетчики и увеличивать их в отрицательное значение. Или мы могли бы просто использовать reversed атрибут в HTML. Я бы сказал, что обычно имеет семантический смысл использовать reversed атрибут, а не отрицательно увеличивать счетчик в CSS, если только счетчики не являются чисто презентационными. Если CSS не удалось загрузить, вы все равно увидите правильный обратный отсчет чисел в HTML. Кроме того, нам нужно подумать о том, как программа чтения с экрана будет интерпретировать список.

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

В демо-версии вы можете увидеть, что при использовании атрибута reversed наши маркеры уже имеют правильное значение без каких-либо дополнительных усилий с нашей стороны! Но если мы создаем собственные маркеры списка с использованием псевдоэлемента ::before , нам необходимо настроить наши счетчики. Нам просто нужно указать нашему счетчику элементов списка отрицательно увеличиваться:

li::before {  
  counter-increment: list-item -1;  
  content: counter(list-item);  
}  

В Firefox этого будет достаточно, но в Chrome и Safari маркеры будут вести отсчет от нуля до -10. Мы можем это исправить, добавив в список атрибут start .

Разделить списки

Атрибут start позволяет нам указать числовое значение, с которого должен начинаться список. Это может быть полезно в тех случаях, когда вы хотите разделить список на группы.

Давайте продолжим наш пример с 10 лучшими альбомами. Возможно, мы на самом деле хотим отсчитать 20 лучших альбомов, но группами по 10. Между двумя группами есть другой контент страницы.

Каркасный список в столбцах с элементом, охватывающим столбцы посередине.

Нам нужно будет создать в HTML-коде два отдельных списка, но как мы можем гарантировать, что счетчики будут правильными? В нашей текущей разметке оба списка будут вести обратный отсчет от 10 до 1, а это не то, что нам нужно. Однако в нашем HTML мы можем указать значение атрибута start . Если мы добавим start значение 20 в наш первый список, маркеры снова обновятся автоматически!

<ol reversed start="20">  
  <li>...</li>  
  <li>...</li>  
  <li>...</li>  
</ol>  

Макет списка из нескольких столбцов

Макет с несколькими столбцами иногда хорошо подходит для наших списков, как вы могли видеть из предыдущих демонстраций. Установив ширину столбца, мы можем гарантировать, что наш список будет автоматически реагировать, размещаясь на двух или более столбцах только при наличии достаточного места. Мы также можем установить зазор между столбцами и для большего эффекта добавить стилизованное правило столбца (используя сокращение, похожее на свойство border ):

ol {  
    columns: 25rem;  
    column-gap: 7rem;  
    column-rule: 4px dotted turquoise;  
}  

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

Демонстрация того, как контент распределяется между двумя столбцами.

Мы можем предотвратить эти принудительные перерывы, используя break-inside: avoid пунктов нашего списка:

li {  
    break-inside: avoid;  
}  

Пользовательские свойства

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

Но мы можем установить индекс элемента в атрибуте style в нашем HTML, что может сделать вычисления более осуществимыми, особенно если мы используем язык шаблонов. В этом примере показано, как мы можем установить это с помощью Nunjucks :

<ol style="--length: items|length">  
  
</ol>  

Splitting.js — это библиотека, выполняющая аналогичную функцию на стороне клиента.

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

li::before {  
    --stop: calc(100% / var(--length) * var(--i));  
    --color1: deeppink;  
    --color2: pink;  

    content: '';  
    background: linear-gradient(to right, var(--color1) var(--stop), var(--color2) 0);  
}  

Мы также могли бы регулировать оттенок по мере продвижения списка, используя функцию цвета hsl() . Мы можем рассчитать значение hue , используя наше пользовательское свойство.

Оформление списка описаний

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

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

С другой стороны, если мы хотим четко сгруппировать термины по их описаниям в карточном стиле, очень полезна оболочка <div> .

Ресурсы