Фрэйн . - HTML5 и CSS3. Разработка сайтов для любых браузеров и устройств. 2-е изд.
Теперь, несмотря на то что значения идентификаторов и классов в HTML5 могут начинаться с цифр, спецификация CSS по-прежнему не позволяет использовать селекторы идентификаторов и классов, начинающиеся с цифр (http://www.w3.org/TR/CSS21/syndata.html).
К счастью, этот запрет легко обойти, воспользовавшись селектором атрибутов, например [id="10"].
Структурные псевдоклассы CSS3
В CSS3 предоставляется более эффективный механизм выбора элементов на основе их местоположения в структуре DOM.
Рассмотрим обработку весьма распространенной конструкции, при которой ведется работа над панелью навигации для более широкого окна просмотра и нам требуется, чтобы в левой стороне экрана были все ссылки, кроме последней.
Согласно сложившейся практике нам понадобилось бы решать эту задачу путем добавления к последней ссылке имени класса, что дало бы возможность выбрать именно эту ссылку:
<nav class="nav-Wrapper">
<a href="/home" class="nav-Link">Home</a>
<a href="/About" class="nav-Link">About</a>
<a href="/Films" class="nav-Link">Films</a>
<a href="/Forum" class="nav-Link">Forum</a>
<a href="/Contact-Us" class="nav-Link nav-LinkLast">Contact Us</a>
</nav>
Но такое решение само по себе может стать проблематичным. Например, иногда весьма трудно даже получить такую систему управления содержимым, которая может добавить класс к последнему элементу списка. К счастью, подобные обстоятельства больше не вызывают опасений. Эту задачу, как и многие другие, теперь можно решить с помощью структурных псевдоклассов CSS3.
Селектор :last-child
В CSS 2.1 уже был селектор, применяющийся для выбора первого элемента списка:
div:first-child {
/* Стили */
}
А в CSS3 добавился селектор, который также может соответствовать последнему элементу:
div:last-child {
/* Стили */
}
Посмотрим, как с помощью этого селектора решается наша предыдущая задача:
@media (min-width: 60rem) {
.nav-Wrapper {
display: flex;
}
.nav-Link:last-child {
margin-left: auto;
}
}
Есть также селекторы для тех случаев, когда имеется только один элемент :only-child и только один элемент заданного типа :only-of-type.
Селекторы nth-child
Селекторы nth-child позволяют решать куда более трудные задачи. Давайте с той же разметкой, что и прежде, посмотрим, как селекторы nth-child позволяют выбрать любую ссылку (или ссылки) внутри списка.
Прежде всего посмотрим, как можно выбрать каждый второй элемент списка. Это можно сделать с помощью следующего кода:
.nav-Link:nth-child(odd) {
/* Стили */
}
А так можно выбрать каждый первый элемент:
.nav-Link:nth-child(even) {
/* Стили */
}
Усвоение порядка работы nth-правил
Непосвященные могут проявить излишнюю настороженность по отношению к селекторам на nth-основе. Но, как только вы усвоите логику и синтаксис, вы будете удивлены тому, на что они способны. Взглянем на предоставляемые ими возможности.
CSS3 обеспечивает невероятную гибкость, позволяя нам использовать ряд правил на nth-основе:
• nth-child(n);
• nth-last-child(n);
• nth-of-type(n);
• nth-last-of-type(n).
Мы уже видели, как в выражениях на nth-основе можно использовать значения (odd) или (even), а вот параметр (n) может использоваться следующими двумя способами:
• в виде целого числа, например :nth-child(2), что приведет к выбору второго элемента;
• в виде числового выражения, например :nth-child(3n+1), благодаря чему выбор начнется с первого элемента и продолжится выбором каждого третьего элемента.
Разобраться со свойством на основе целого числа нетрудно, нужно просто ввести номер того элемента, который следует выбрать.
Версия селектора с числовым выражением может немного озадачить неискушенных в ее использовании. Если у вас с математикой проблем нет, то я извиняюсь за следующий раздел, а всем остальным советую как следует изучить его.
Разбираемся с математикой. Рассмотрим десять линейных блоков span на странице (посмотреть их в работе можно, запустив пример из файла каталога example_05-05):
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
Изначально им будет задан следующий стиль:
span {
height: 2rem;
width: 2rem;
background-color: blue;
display: inline-block;
}
Нетрудно представить, что в результате мы получим выстроенные в линию десять квадратов.
А теперь посмотрим, как можно выбрать различные элементы с помощью селекции на nth-основе.
Из соображений практичности при разборе выражения в скобках я начну с правого края. К примеру, если я хочу определить, что будет выбрано с помощью выражения (2n + 3), то начинаю с крайнего справа числа (число 3 указывает на третий элемент слева) и знаю, что наряду с ним, начиная с его позиции, будет выбран каждый второй элемент. Поэтому добавление правила:
span:nth-child(2n+3) {
color: #f90;
border-radius: 50%;
}
даст на экране браузера следующий результат.
Как видите, наш nth-селектор нацелен на третий элемент списка, а также на каждый последующий второй элемент после него (если бы в списке было 100 элементов, то продолжался бы выбор каждого второго из них).
А как выбрать каждый последующий элемент, начиная со второго? Хотя можно воспользоваться кодом :nth-child(1n+2), первая цифра вообще-то не нужна, поскольку, если не утверждается ничто иное, переменная n равна единице. Поэтому можно просто написать :nth-child(n+2). По аналогии с этим, если нам нужно выбрать каждый третий элемент, вместо записи :nth-child(3n+3) можно просто указать :nth-child(3n), поскольку каждый третий элемент все равно будет начинаться с третьего элемента и нет необходимости указывать именно на него. В выражении могут применяться также отрицательные числа. Например, при использовании выражения :nth-child(3n-2) выбор начинается с -2, а затем выбирается каждый третий элемент.
Можно также изменить направление. По умолчанию, как только найдена первая часть заданного выбора, последующие части ищутся вниз по элементам в DOM-дереве (и поэтому выбор в нашем примере идет слева направо). Но направление можно изменить на обратное, поставив минус, например:
span:nth-child(-2n+3) {
background-color: #f90;
border-radius: 50%;
}
В этом примере также ищется третий элемент, но затем поиск идет в обратном направлении с целью выбора каждого второго элемента (вверх по DOM-дереву, поэтому в нашем примере — справа налево).
Надеюсь, теперь-то вы усвоили логику выражений на nth-основе?
Разница между nth-child и nth-last-child заключается в том, что вариант nth-last-child работает в противоход распространению дерева документа. Например, :nth-last-child(-n+3) начинает выбор с 3 с конца, а затем выбирает все элементы после него. Результат применения данного правила будет иметь на экране браузера следующий вид.
И в заключение рассмотрим селекторы :nth-of-type и :nth-last-of-type. В предыдущих примерах вычисление шло в отношении всех дочерних элементов независимо от их типа (следует твердо усвоить, что селектор nth-child нацеливается на все дочерние элементы одного и того же DOM-уровня независимо от их классов), а вот селекторы :nth-of-type и :nth-last-of-type позволяют указывать тип подлежащих выбору элементов. Рассмотрим следующую разметку (файл с которой можно найти в каталоге example_05-06):
<span class="span-class"></span>
<span class="span-class"></span>
<span class="span-class"></span>
<span class="span-class"></span>
<span class="span-class"></span>
<div class="span-class"></div>
<div class="span-class"></div>
<div class="span-class"></div>
<div class="span-class"></div>
<div class="span-class"></div>
Если воспользоваться следующим селектором:
.span-class:nth-of-type(-2n+3) {
background-color: #f90;
border-radius: 50%;
}
то независимо от наличия у всех элементов одного и того же класса span-class нацеливание произойдет только на span-элементы (поскольку они относятся к выбираемому типу). В результате будут выбраны следующие элементы.
Вскоре мы увидим, как эта же задача решается с помощью селекторов из спецификации CSS4.
Счетчики в CSS3 работают не так, как в JavaScript и jQuery!
Если вы привыкли пользоваться JavaScript и jQuery, то должны быть в курсе, что подсчет там ведется с нуля и выше (используется индексация, начинающаяся с нуля). Например, при выборе элемента в JavaScript или jQuery целочисленное значение 1 будет фактически указывать на второй по счету элемент. Но в CSS3 счет начинается с 1, поэтому значение 1 соответствует первому элементу.
Выбор на nth-основе в адаптивных веб-конструкциях
Просто для того, чтобы завершить этот небольшой раздел, хочу проиллюстрировать реальную проблему адаптивного веб-дизайна и способ применения выбора на nth-основе для ее решения.
Помните горизонтальную прокручиваемую панель, файлы для создания которой можно найти в каталоге example_05-02? Посмотрим, как это может выглядеть в той ситуации, при которой осуществить горизонтальную прокрутку невозможно. Используя ту же разметку, поместим верхнюю десятку самых кассовых фильмов 2014 года в решетку grid-системы. Для некоторых окон просмотра решетка будет шириной всего в два элемента, по мере увеличения окна просмотра будут показаны три элемента, при еще более крупных размерах — четыре элемента. Но при этом возникает проблема. Независимо от размера окна просмотра нам бы не хотелось, чтобы у самой нижней строки элементов имелась нижняя граница. Файл с соответствующим кодом можно найти в каталоге example_05-09.