Эта статья — перевод оригинальной статьи «More control over :nth-child() selections with the of S syntax»

Также я веду телеграм канал «Frontend по‑флотски», где рассказываю про интересные вещи из мира разработки интерфейсов.

Селекторы псевдоклассов :nth-child() и :nth-last-child()

С помощью селектора псевдокласса :nth-child() можно выбирать элементы в DOM по их индексу. Используя микросинтаксис An+B, вы получаете тонкий контроль над тем, какие элементы вы хотите выбрать.

  • :nth-child(2): Выберет второй дочерний элемент.

  • :nth-child(2n): Выберет все четные дочерние элементы (2-й, 4-й, 6-й, 8-й и так далее).

  • :nth-child(2n+1): Выберет все нечетные дочерние элементы (1-й, 3-й, 5-ый, 7-ой и так далее).

  • :nth-child(5n+1): Выберет 1-го (=(5×0)+1), 6-го (=(5×1)+1), 11-го (=(5×2)+1), ребенка.

Чтобы интерактивно увидеть, как логика An+B влияет на выделения, используйте тестер :nth-child.

Но можно сделать более творческий выбор, если опустить параметр A. Например:

  • :nth-child(n+3): Выберет каждый дочерний элемент, начиная с третьего (3-й, 4-й, 5-й и так далее).

  • :nth-child(-n+5): Выберет каждый дочерний элемент до 5-го (1-го, 2-го, 3-го, 4-го, 5-го).

Объедините несколько таких селекторов :nth-child(), и вы сможете выбирать диапазоны элементов:

  • :nth-child(n+3):nth-child(-n+5): Выберет каждый дочерний элемент от 3-го до 5-го (3-й, 4-й, 5-й).

Используя :nth-last-child(), вы можете делать подобные селекторы, но вместо того, чтобы начинать считать с начала, вы начинаете считать с конца.

Если вы хотите перейти на новый уровень, вы можете использовать :nth-child() для применения стилей к группе элементов, когда они достигают определенного размера ("Quantity Queries") или стилизовать родительский элемент на основе количества его дочерних элементов.

Предварительная фильтрация с помощью синтаксиса of S

Новое в CSS Selectors Level 4 - возможность опционально передавать список селекторов в :nth-child() и :nth-last-child().

:nth-child(An+B [of S]?)
:nth-last-child(An+B [of S]?)

Когда указано of S, логика An+B применяется только к тем элементам, которые соответствуют заданному списку селекторов S. Это означает, что вы можете предварительно отфильтровать дочерние элементы, прежде чем An+B сделает свое дело.

Примеры

Например, :nth-child(2 of .highlight) выбирает второй подходящий элемент, имеющий класс .highlight. Другими словами: из всех дочерних элементов с классом .highlight выберите второй.

Это отличается от .highlight:nth-child(2), который выбирает элемент, имеющий класс .highlight, а также являющийся вторым дочерним элементом.

В демонстрационном примере ниже вы можете увидеть эту разницу:

  • Элемент, соответствующий :nth-child(2 of .highlight), имеет розовый контур.

  • Элемент, соответствующий .highlight:nth-child(2), имеет зеленый контур.

CodePen

Обратите внимание, что S - это список селекторов, что означает, что он принимает несколько селекторов, разделенных запятой. Например, :nth-child(4 of .highlight, .sale) выбирает четвертый элемент, который является либо .highlight, либо .sale из множества дочерних элементов.

В демонстрационном примере ниже элемент, соответствующий :nth-child(4 of .highlight, .sale), имеет оранжевый контур.

CodePen

Зебра, пересмотренный вариант

Классическим примером использования :nth-child() является создание таблицы с полосками зебры. Это визуальный прием, при котором в каждой строке таблицы чередуются цвета. Обычно это делается следующим образом:

tr:nth-child(even) {
  background-color: lightgrey;
}

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

CodePen

Чтобы исправить это, мы можем использовать :nth-child(An+B [of S]?), исключив скрытые строки из логики An+B:

tr:nth-child(even of :not([hidden])) {
  background-color: lightgrey;
}

CodePen

Довольно круто, правда?

Комментарии (1)


  1. EvgenichTalagaev
    10.04.2023 14:09
    +2

    Спасибо за перевод, интересная возможность, но поддержка пока хромает.