HTML & CSS IS HARD - НА РУССКОМ

СЕЛЕКТОРЫ CSS

УРОК Nº 6.

Самый понятный учебник веб-разработки о выборке HTML-элементов

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

Interneting is hard HTML+CSS
Скриншот 1: CSS-селектор, связывающий CSS-правило с HTML-элементом

Если вы не хотите, чтобы все секции вашего сайта выглядели одинаково, к вашим услугам очень полезная функциональная особенность. С ее помощью мы можем сказать: "Я хочу, чтобы этот абзац был синим, а тот - желтым". До сих пор мы могли сделать все абзацы только синими (или желтыми).

До сих пор мы использовали только один CSS-селектор, так наз. "селектор типа" [type selector]. Он определяет все соответствующие элементы на странице. На этом уроке мы рассмотрим более детальные способы стилизации веб-страниц с помощью селекторов классов, потомков, псевдоклассов и идентификаторов.

подготовка
setup

Для нашего примера к этому уроку нам понадобится только один HTML-файл и таблица стилей CSS. Создайте новую папку css-selectors и новую веб-страницу selectors.html со следующей разметкой:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>CSS Selectors</title>
<link rel='stylesheet' href='styles.css'/>
</head>
<body>
<h1>CSS Selectors</h1>

<p>CSS selectors let you <em>select</em>, individual HTML elements in an HTML
document. This is <strong>super</strong> useful.</p>

<p>Classes are ridiculously important, since they allow you to select
arbitrary boxes in your web pages.</p>

<p>We’ll also be talking about links in this example, so here’s
<a href='https://internetingishard.com'>Interneting Is Hard</a> for us to
style.</p>

<div>Button One</div>

</body>
</html>

Создайте в той же папке таблицу стилей styles.css. Тогда у нас будет все необходимое для изучения селекторов CSS.

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

селекторы классов
Class Selectors

"Селекторы классов" позволяют применять стили CSS к определенному элементу HTML. Они позволяют различать HTML-элементы одного типа, как, например, в предыдущей главе, когда у нас было два элемента <div>, но мы хотели придать стиль только одному из них. Для использования селекторов классов необходимы две вещи:

Interneting is hard HTML+CSS
Скриншот 2: селектор класса CSS, связывающий правило CSS с атрибутом class HTML-элемента

Мы можем использовать селектор класса для того, чтобы стилизовать первый абзац нашего примера страницы иначе, чем остальные. Это может быть, например, синопсис [краткий обзор содержания] газетной статьи. Сначала добавим атрибут class к нужному абзацу:

<p class='synopsis'>CSS selectors let you <em>select</em>, individual HTML
elements in an HTML document. This is <strong>super</strong> useful. </p>

Теперь мы можем выбрать этот элемент <p class='synopsis'> в нашем CSS с помощью следующего правила (добавьте его в файл styles.css):

.synopsis {
color: #7E8184; /* светло-серый */
font-style: italic;
}

Это правило применяется только к элементам с соответствующим атрибутом class. Обратите внимание на точку (.) в префиксе имени класса. Это отличает селекторы классов от селекторов типов, с которыми мы работали до этого урока.

Interneting is hard HTML+CSS
Скриншот 3: выделенный курсивом элемент <p>, стилизованный с помощью селектора класса
СТАНДАРТЫ НАИМЕНОВАНИЯ КЛАССОВ
Class Naming Conventions

Значение атрибута HTML class может быть (почти) любым, если оно соответствует селектору в ваших CSS. Стандартный порядок именования классов - все строчные буквы и дефисы для пробелов, как в именах файлов и папок.

Добавление атрибута class не меняет семантического смысла HTML-документа - он служит исключительно для подключения к таблице стилей CSS. Тем не менее, обычно рекомендуется избегать именования классов по их внешнему виду. Если мы назовем наш класс .italic, то в CSS мы не сможем сделать ничего, кроме как сделать его курсивным, что приведет к запутанной ситуации. Использование смыслового имени, например .synopsis, дает нам больше свободы в CSS для настройки отображения синопсиса.

полезные возможности div
More Useful Divs

Атрибут class не ограничивается элементами <p> - он может быть определен для любого HTML-элемента. Вооружившись новоприобретенными селекторами классов CSS, мы получаем гораздо больше возможностей применения универсальных контейнеров <div> и <span> из предыдущего урока. Мы можем использовать их для стилизации как отдельных элементов, так и любых секций нашей веб-страницы.

Interneting is hard HTML+CSS
Скриншот 4: веб-страница, на которой выделен элемент <div> в виде кнопки, стилизованный с помощью селектора класса

Начнем с отдельных элементов, воссоздав нашу кнопку из предыдущей главы. На этот раз вместо селектора div мы используем класс. Добавьте в файл styles.css следующее:

.button {
color: #FFF;
background-color: #5995DA; /* синий */
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063; /* темно-серый */
border-radius: 5px;

width: 200px;
margin: 20px auto;
}

Разумеется, для этого нам необходим соответствующий атрибут class. Измените <div> в файле selectors.html следующим образом:

<div class='button'>Button One</div>.

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

div-контейнеры
Container Divs

Помните, что <div> не изменяет смысловую структуру веб-страницы. Это делает его отличным инструментом для структуры внешнего вида страницы. Обернув другие HTML-элементы в теги <div>, мы можем разделить наш сайт на крупные сегменты, ориентированные на верстку, не испортив при этом восприятия поисковиками нашего контента.

Interneting is hard HTML+CSS
Скриншот 5: люди видят элемент <div> с отступами (margins), веб-роботы его не видят

В качестве примера создадим макет фиксированной ширины с использованием техники auto-margin, которую мы изучали в предыдущей главе. Сначала упакуем весь наш документ в общий <div> и присвоим ему cвой собственный класс:

<body>
<div class='page'> <!-- добавьте это -->
<h1>CSS Selectors</h1>

<p class='synopsis'>CSS selectors let you <em>select</em>, individual HTML elements in an HTML
document. This is <strong>super</strong> useful.</p>

<p>Classes are ridiculously important, since they allow you to select
arbitrary boxes in your web pages.</p>

<p>We’ll also be talking about links in this example, so here’s
<a href='https://internetingishard.com'>Interneting Is Hard<a> for us to
style.</p>

<div class='button'>Button One</div>
</div> <!-- и это добавьте -->
</body>

Затем в styles.css добавим вот такой код:

.page {
width: 600px;
margin: 0 auto;
}

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

Interneting is hard HTML+CSS
Скриншот 6: обертывание всего документа веб-страницы посредством <div> с классом .page

Именно так задаются макеты в более сложных веб-страницах. Например, если бы на нашей странице была боковая панель, мы бы вложили все элементы боковой панели в другой <div> с классом .sidebar. Мы увидим это в действии на следующем уроке. Пока же важно понять, что без селекторов классов, позволяющих отделять элементы <div>, ничего этого сделать было бы невозможно.

многократное использование стилей классов
Reusing Class Styles

Один и тот же класс можно применять к нескольким элементам в одном HTML-документе. Это означает, что теперь мы можем повторно использовать любые CSS-декларации в любом месте. Чтобы создать еще одну кнопку, достаточно добавить еще один HTML-элемент с тем же классом:

<div class='button'>Button One</div>
<div class='button'>Button Two</div>

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

Interneting is hard HTML+CSS
Скриншот 7: две стрелки, идущие от одного правила CSS к двум разным элементам HTML
Изменение стилей классов
Modifying Class Styles

А что если мы захотим немного изменить нашу вторую кнопку? К счастью, мы можем применить несколько классов к одному и тому же HTML-элементу. Стили каждого класса будут применены к элементу, позволяя нам:
а) повторно использовать стили из .button и
б) переопределить некоторые из стилей в новом классе.

Interneting is hard HTML+CSS
Скриншот 8: две стрелки, идущие от двух CSS-правил к одному HTML-элементу

Добавим к нашей второй кнопке еще один класс call-to-action. Обратите внимание, что оба класса находятся в одном атрибуте class, разделенные пробелом:

<div class='button call-to-action'>Button Two</div>

Теперь у этого элемента есть два отдельных класса, и мы можем использовать любой из них для его стилизации. Это открывает некоторые возможности. Стили, общие для обеих кнопок, могут находиться в классе .button (как это уже сделано), а стили, специфичные для второй кнопки, - в классе .call-to-action (не забудьте добавить его после правила .button):

.call-to-action {
font-style: italic;
background-color: #EEB75A; /* желтый */
}

ОЧЕРЕДНОСТЬ ИМЕЕТ ЗНАЧЕНИЕ
Order Matters

Теперь в нашей второй кнопке происходит несколько важных вещей:

Переопределение [overriding] происходит из-за порядка следования .call-to-action и .button в нашей таблице стилей. Когда в CSS-файле присутствуют два конфликтующих свойства, всегда применяется последнее. Так, если переместить .call-to-action в верхнюю часть styles.css, то последнее слово в значении background-color будет за .button, и фон останется синим.

Отсюда следует, что порядок следования атрибутов class в нашем HTML-элементе не влияет на поведение переопределения. Несколько классов к одному элементу применяются "одинаково" (за неимением лучшего термина), поэтому старшинство определяется исключительно порядком следования правил в styles.css. Другими словами, следующие элементы фактически эквивалентны:

<!-- В результате, страница будет отображаться без изменений -->
<div class='button call-to-action'>Button Two</div>
<div class='call-to-action button'>Button Two</div>

Однако все усложняется, когда в дело вступает специфика CSS, о которой мы поговорим в конце этого урока.

селекторы потомков
Descendant Selectors

Вы, наверное, заметили, что элемент <em> в нашем первом абзаце уже не отличим от окружающего текста, поскольку правило .synopsis сделало все курсивом.

Чтобы изменить этот элемент <em>, мы могли бы добавить другой класс непосредственно к нему, но это не приведет к удобству работы с кодом. Мы хотим рассматривать .synopsis как свой собственный независимый компонент, который мы можем полностью стилизовать с помощью CSS (т.е. без необходимости вносить изменения в наш HTML только для того, чтобы что-то стилизовать).

Interneting is hard HTML+CSS
Скриншот 9: веб-страница с текстом span внутри другого элемента, стилизованным с помощью селектора-потомка

Для этого и нужны "селекторы потомков". Они позволяют выбрать только те элементы, которые находятся внутри другого элемента. Например, мы можем извлечь этот <em> в параграфе .synopsis следующим образом:

.synopsis em {
font-style: normal;
}

Добавление этого правила в файл styles.css приведет к тому, что <em> будет отображаться в виде "обычного" шрифта (т.е. не курсивного), отличаясь тем самым от курсива, которым мы выделяем весь текст <p>. Остальные элементы <em> на странице не будут затронуты.

Interneting is hard HTML+CSS
Скриншот 10: единичная стрелка, идущая от составного CSS-правила [CSS rule] к HTML-элементу внутри другого HTML-элемента

Селекторы-потомки не ограничиваются селекторами классов - таким образом можно объединять любые другие группы селекторов. Например, если мы хотим выбрать только элементы <em> внутри заголовков, мы можем использовать что-то вроде этого:

h1 em {
/* некие другие стили */
}

Повторим, цель этого урока - дать возможность применять стили именно к тому элементу, который вам нужен. Селекторы-потомки - отличный инструмент для достижения этой цели. Если еще осталось свободное место в вашем "ящике инструментов", ознакомьтесь с селектором дочерних элементов на сайте MDN.

НЕ ПЕРЕУСЕРДСТВУЙТЕ
Don’t Overdo It

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

/* постарайтесь избежать такого */
.article h2 .subheading em {
/* особые стили */
}

Это ни в коей мере не пригодно для повторного использования, поскольку соответствует только следующей структуре HTML:

<div class='article'>
<h2>
<span class='.subheading'>This is <em>really</em> special text</span>
</h2>
</div>

Если вы захотите применить эти стили к заголовку <h2>, не обернутому в теги <div class='article'>, то будет, как говорится, полный облом. То же самое произойдет, если вы захотите применить их к заголовку <h3> в любом месте страницы. Такой CSS только приведет к кошмару специфичности.

До сих пор все рассмотренные CSS-селекторы привязывались непосредственно к созданному нами фрагменту HTML-разметки. Однако на отображаемой веб-странице присутствует нечто большее, чем просто наш HTML-контент. Кроме созданного нами контента, там есть "служебная" информация о том, что делает пользователь.

Классический пример - ссылка. Как веб-разработчик, вы создаете элемент <a href>. После того как браузер отобразит его, пользователь может взаимодействовать с этой ссылкой. Он может навести на нее курсор, щелкнуть и перейти по URL-адресу.

Interneting is hard HTML+CSS
Скриншот 11: селектор псевдокласса, связывающий CSS-правило с поведением пользователя [hover - наведение курсора]

"Псевдоклассы" CSS это механизм, позволяющий подключаться к такого рода временной информации о пользователе. Элемент <a href> может находиться в нескольких различных состояниях, и вы можете использовать псевдоклассы для стилизации каждого из этих состояний в отдельности. Считайте, что это селекторы классов, которые не нужно писать самостоятельно, ибо они уже встроены в браузер.

ОСНОВНЫЕ СТИЛИ ССЫЛОК
Basic Link Styles

Псевдоклассы начинаются с двоеточия, за которым следует имя нужного класса. Наиболее распространенными псевдоклассами ссылок являются следующие:

Давайте рассмотрим все это, добавив в таблицу стилей CSS следующие правила (также обратите внимание на использование ключевых цветов вместо привычных hex-кодов [шестнадцатеричных кодов]):

a: link {
color: blue;
text-decoration: none;
}
a: visited {
color: purple;
}
a: hover {
color: aqua;
text-decoration: underline;
}
a: active {
color: red;
}

Если вы никогда не были на главной странице InternetingIsHard.com [веб-страница англоязычного оригинала данного учебника], данная ссылка должна быть синего цвета. А если уже там были, то цвет ссылки будет фиолетовым. При наведении курсора на ссылку ее цвет поменяется на aqua [цвет морской волны], а при нажатии на нее - цвет станет красным.

ССЫЛКА КОТ. ПОСЕЩАЛИ ПРИ НАВЕДЕНИИ НА НЕЕ МЫШИ
Visited Hover State

Приведенный выше фрагмент кода вполне подходит для большинства сайтов, но обратите внимание на поведение a:visited, изменив атрибут href на URL, который вы уже посещали. Наш стиль a:hover применяется как к посещенным, так и к непосещенным ссылкам. Можно еще более усовершенствовать наши ссылки, просто добавляя псевдоклассы. В конец вышеприведенного кода добавим еще пару строк:

a: visited:hover {
color: orange;
}

Это создаст особый стиль hover для посещаемых ссылок. При наведении на непосещаемую ссылку ее цвет уже не будет меняется на aqua. А при наведении на посещенную ссылку - ее цвет станет оранжевым. Фантастиш! За исключением того факта, что это ломает наш стиль a:active из-за некоторых сложных CSS-интерфейсов, с которыми вы наверняка никогда не захотите разбираться. И еще, когда вы щелкнете на ссылку, она уже не станет красной.

АКТИВНОЕ СОСТОЯНИЕ ПОСЕЩЕННОЙ ССЫЛКИ
VISITED ACTIVE STATE

Мы можем исправить это с помощью a:visited:active. Добавьте следующее в конец нашей таблицы стилей. Помните, что, как и в случае с классом .call-to-action, порядок, в котором они определены в styles.css, имеет значение:

a: visited:active {
color: red;
}

Последние два секции объясняют как стилизовать посещенные ссылки отдельно от непосещенных. Это хорошая возможность, но, опять же, вы можете ограничиться базовыми стилями ссылок. Может вам их будет достаточно?

псевдоклассы для кнопок
Pseudo-Classes for Buttons

Помимо стилизации текстовых ссылок псевдоклассы можно применять для стилизации любого типа селекторов (не только селекторов типов). Вместо стилизации a:link и других ссылок, в этой секции с помощью псевдоклассов мы будем модифицировать класс .button. Тем самым мы создим кнопки, которые реально работают и куда-то ведут.

ЭЛЕМЕНТЫ ССЫЛОК, ВМЕСТО ЭЛЕМЕНТОВ DIV
Link Elements, Not Div Elements

Прежде всего, нам нужно изменить наши кнопки так, чтобы они были элементами <a href>, а не обычными элементами <div>, что показано ниже:

<div class='button' href='nowhere.html'>Button One</a>
<div class='button call-to-action' href='nowhere.html'>Button Two</a>

Добавив этот код и перезагрузив страницу, увидим, что некоторые стили потерялись, хотя мы используем все те же классы. Причина? Это происходит потому, что <a> по умолчанию это строчный элемент со своим стандартным значением color.

Interneting is hard HTML+CSS
Скриншот 12: изображение кнопок на веб-странице с искаженными стилями CSS

Нам нужно изменить его на блоковый элемент и удалить некоторые стили ссылок по умолчанию.

СТИЛИ КНОПОК
Button Styles

Начнем с :link и :visited. Мы используем тот же шаблон, что и в предыдущей секции, но с одним отличием. Поскольку мы стилизуем кнопки, желательно сохранить одинаковый цвет для непосещенных и уже посещенных. Измените существующие правила .button следующим образом:

.button:link, /* измените это */
.button:visited { /* измените это */
display: block; /* добавьте это */
text-decoration: none; /* добавьте это */

color: #FFF; /* остальное без изменений */
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;

width: 200px;
margin: 20px auto;
}

Обратите внимание на новые псевдоклассы :link и :visited в селекторе. Без них наш цвет не будет переопределять стандартный стиль браузера a:link. Cпецифичность CSS более подробно объясняет, почему это так. Далее давайте займемся состояниями наведения курсора [hover]:

.button:hover,
.button:visited:hover {
color: #FFF;
background-color: #76AEED; /* голубой */
}

При наведении курсора обе кнопки будут становиться светло-голубыми. И наконец, сделаем кнопку немного темнее, когда пользователь щелкает мышью. В этом нам поможет псевдокласс :active:

.button:active,
.button:visited:active {
color: #FFF;
background-color: #5995DA; /* синий */
}

Самое чудесное в этом то, что все только что заданные стили, можно использовать многократно, то есть сколько угодно. Примените класс .button к любому элементу HTML, и вы превратите его в интерактивную кнопку.

ВТОРАЯ КНОПКА
The Other Button

А как насчет второй кнопки? Она должна иметь желтый фон, но мы нарушили это правило с помощью кода из предыдущей секции. Наш селектор .button:link был более "конкретным", чем наше текущее правило .call-to-action, поэтому он получил приоритет. Опять же, мы рассмотрим это подробнее в конце данного урока.

А пока давайте исправим это, применив некоторые псевдоклассы к нашему правилу .call-to-action. Замените существующее правило следующим (убедитесь, что данные изменения расположены после кода стилей .button из предыдущей секции):

.call-to-action:link,
.call-to-action:visited {
font-style: italic;
background-color: #EEB75A; /* Желтый */
}

.call-to-action:hover,
.call-to-action:visited:hover {
background-color: #F5CF8E; /* Светло-желтый */
}

.call-to-action:active,
.call-to-action:visited:active {
background-color: #EEB75A; /* Желтый */
}

Поскольку мы добавили класс .call-to-action только ко второй кнопке, только она станет желтой. Конечно, нам все еще нужен класс .button для обоих элементов <a>, потому что он определяет общие стили, такие как padding, округление углов рамки и жирность шрифта.

псевдоклассы для структуры
Pseudo-Classes For Structure

Состояния ссылок - это лишь один из аспектов псевдоклассов. Существует также множество других псевдоклассов, которые предоставляют дополнительную информацию об окружении элемента. Например, псевдокласс :last-of-type выбирает последний элемент определенного типа в его родительском элементе. Это дает нам альтернативу селекторам классов для выбора конкретных элементов.

Например, мы можем использовать :last-of-type, чтобы добавить немного пустого пространства после последнего абзаца на нашей странице:

p:last-of-type {
margin-bottom: 50px;
}

Это позволяет избежать селекции первых двух элементов <p>, не требуя нового атрибута class для последнего абзаца:

Interneting is hard HTML+CSS
Скриншот 13: нижнее поле последнего абзаца на странице, стилизованное с помощью псевдокласса-селектора :last-of-type

Мы даже можем использовать псевдокласс :first-of-type вместо класса .synopsis. Заменив существующее правило .synopsis следующим фрагментом, вы получите точно такую же страницу.

p:first-of-type {
color: #7E8184;
font-style: italic;
}

У этого метода есть свои плюсы и минусы по сравнению с обычными классами. Например, он работает только в том случае, если наш синопсис - это элемент <p>. Если мы захотим создать многопараграфный синопсис, обернув кучу элементов <p> в <div class='synopsis'>, нам придется соответствующим образом переписать наш CSS. С другой стороны, метод псевдоклассов позволяет нам стилизовать определенные элементы без необходимости изменять HTML. Таким образом, мы получаем очень чистое разделение контента и внешнего вида.

ОГОВОРКИ
Caveats

На самом деле метод псевдоклассов немного сложнее. Но они все равно являются полезным инструментом - при условии, что вы знаете их особенности и недостатки. Селекторы :first-of-type и :last-of-type действуют только внутри родительского элемента. То есть p:first-of-type выбирает первый <p> в каждом элементе-контейнере.

У нас есть один общий <div>, обертывающий наш контент (.page), поэтому для нас это не проблема. Однако посмотрите, что произойдет, если мы добавим это в нижнюю часть нашего элемента .page:

<div class='sidebar'>
<p>If this page had a sidebar...</p>
<p>We’d have some problems with pseudo-classes.</p>
</div>

Мы еще не умеем делать настоящую боковую панель (об этом на следующем уроке), но это подчеркивает сложность псевдоклассов для структуры. Первый элемент <p> здесь также будет соответствовать p:first-of-type, потому что область действия псевдокласса ограничена родительским элементом.

Если бы мы хотели избежать абзацев боковой панели и выбрать только первый <p> в нашем <div class='page'>, нам бы пришлось ограничить его область действия с помощью дочернего селектора, как показано ниже:

.page > p:first-of-type {
color: #7E8184;
font-style: italic;
}

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

id-селекторы
ID Selectors

"Селекторы ID" - это более жесткая альтернатива селекторам классов. Они работают практически так же, за исключением того, что на странице может быть только один элемент с одинаковым ID. Это означает, что вы не можете повторно использовать стили. Вместо атрибута class они требуют атрибут id у HTML-элемента, который вы пытаетесь задействовать. Попробуйте добавить его к нашей второй кнопке:

<a id='button-2' class='button' href= 'nowhere.html'>Button Two</a>

Соответствующий селектор CSS должен начинаться с знака хеш (#), а не с точки. Добавив следующее в файл styles.css, вы измените цвет текста нашей желтой кнопки:

#button-2 {
color: #5D6063; /* темно-серый */
}

Проблема в том, что как только мы захотим поделиться этим стилем с другой кнопкой, нам придется присвоить ей еще один уникальный атрибут id. Очень скоро наш CSS выглядел бы довольно неприглядно:

/* (обслуживать такой код очень напряжно) */
#button-2,
#button-2,
#checkout-button,
#menu-bar-call-to-action
{
color: #5D6063;
}

По этой причине селекторы ID обычно не одобряются. Вместо них используйте селекторы классов.

ФРАГМЕНТЫ URL
URL Fragments

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

Interneting is hard HTML+CSS
Скриншот 14: синтаксис URL - схема, домен, путь, фрагмент.

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

<!-- В случае, когда одна и та же страница -->
<a href='#button-2'>Go to Button Two</a>

<!-- В случае, когда путь ведет на другую страницу -->
<a href='selectors.html#button-2'>Go to Button Two</a>

Если вы добавите первый вариант на нашу страницу selectors.html и щелкнете по нему, вы увидите, как изменится URL в браузере. Чтобы увидеть переход ко второй кнопке, вам придется добавить на страницу еще немного фиктивного контента или сделать высоту окна очень маленькой, так как браузер ограничит прокрутку экрана видимым пространством страницы.

Interneting is hard HTML+CSS
Скриншот 15: две стрелки от фрагментов URL к двум элементам HTML и две стрелки от правил CSS к этим же элементам

Такая накладывающаяся функциональность - еще одна причина избегать селекторов ID. Они создают зависимость между URL-адресами вашего сайта и стилями CSS. Представьте, что вы используете кучу атрибутов id в заголовках в качестве фрагментов URL и селекторов ID. Если бы вы забывали обновлять таблицу стилей каждый раз, когда редактировали URL-адрес секции, вы бы фактически сломали свой сайт.

специфичность
css specificity

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

Interneting is hard HTML+CSS
Скриншот 16: четыре правила CSS с одинаковой спецификой, применяемые по порядку

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

Для начала давайте посмотрим, где это не нарушается. Если вы добавите следующее после существующего правила .call-to-action, оно отменит предыдущий цвет фона. Если вы поместите его в начало файла, он будет отменен позже, поэтому наша кнопка не станет красной. Это ожидаемое поведение.

.call-to-action:link,
.call-to-action:visited {
background-color: #D55C5F; /* Красный */
}

Теперь посмотрите, что произойдет, если мы попытаемся сделать то же самое с селектором ID. Сначала удалите предыдущий фрагмент, а затем попробуйте добавить его перед существующими правилами .call-to-action:

#button-2 {
background-color: #D55C5F; /* Красный */
}

Селекторы ID имеют более высокую специфичность, чем селекторы классов. Поэтому наша вторая кнопка будет красной и все тут. Даже если мы попытаемся установить цвет фона с помощью .call-to-action:link ниже в нашей таблице стилей - это не поможет. Вся концепция "порядок имеет значение" работает только тогда, когда все ваши правила имеют одинаковую специфику.

Interneting is hard HTML+CSS
Скриншот 17: четыре правила CSS. Третье правило имеет более высокую специфичность, поэтому четвертое игнорируется.

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

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

РЕЗЮМЕ

На этом уроке мы получили практический опыт работы с селекторами классов, селекторами потомков, псевдоклассами, стилизацией ссылок и селекторами ID. Цель всего этого заключалась в том, чтобы иметь возможность выбирать конкретный элемент HTML из вашего CSS. Селекторы классов являются наиболее универсальными и имеют наименьшее количество недостатков. В результате они станут частью вашей повседневной жизни веб-разработчика.

Нравится вам это или нет, начиная с этого урока все стало намного сложнее. Теперь мы можем заставить наш CSS взаимодействовать с HTML-документом несколькими разными способами. Более того, чем дальше, тем яснее станет взаимодействие между HTML-структурой и макетом веб-страницы. Из-за этого взаимодействия CSS и HTML бывает трудно понять, с чего начать создание новой веб-страницы.

Разделение контента и внешнего вида помогает направить этот процесс. Прежде чем подать контент, нужно его разметить. Поэтому первым шагом обычно является разметка исходного контента с помощью HTML-тегов. После чего можно добавить атрибуты класса к элементам и стилизовать их один за другим. Если возникает необходимость в дополнительной структуре для создания нужного макета (например, превращения группы элементов в боковую панель), то вы начинаете помещать содержимое в контейнеры <div>.

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

СЛЕДУЮЩИЙ УРОК >