CSS-правила и селекторы
Теперь приступим к CSS, и начнём, пожалуй, с расшифровки аббревиатуры CSS. Это Cascading Style Sheets, дословно «каскадная таблица стилей», но:
— Почему же она называется каскадной? — этот вопрос я часто задаю на собеседованиях претендентам. Ответом же будет аналогия, ибо она незыблема как перпендикулярная лягушка: представьте себе каскад водопада, вот вы стоите на одной из ступенек каскада с чернильницей в руках, и выливаете её содержимое в воду — вся вода ниже по каскаду будет окрашиваться в цвет чернил. Так и в CSS: если вы задаёте стиль на определённом уровне, он распространяется вниз по "каскаду" к элементам веб-страницы, окрашивая их в "цвет" вашего стиля.
— Зачем мне всё это? — работая с jQuery, вы должны «на отлично» читать правила CSS, а также уметь составлять CSS-селекторы для поиска необходимых элементов на странице. Практически все задачи, которые вы будете решать с помощью jQuery, начинаются с поиска необходимого элемента на странице, так что знание CSS-селекторов обязательно.
Но давайте обо всём по порядку, возьмём следующий простенький пример вполне семантического HTML:
Это пример простого и правильного HTML с небольшим добавлением CSS. Давайте разберём селекторы в приведённом CSS-коде (я умышленно не выносил CSS в отдельный файл, ибо так наглядней):
body
— данные правила будут применены к тегу<body>
и всем его потомкам, запомните: настройки шрифтов распространяются вниз по иерархии элементовh1,h2,h3
— мы выбираем теги<h1>
,<h2>
и<h3>
, и устанавливаем цвет шрифта для данных тегов и их потомков#content
— выбираем элемент сid="content"
, настройки отступов не распространяются на потомков, они будут изменяться только для данного элемента.box
— выбираем элементы сclass="box"
, и изменяем внешний вид границ элементов с заданным классом
Теперь подробнее и с усложнёнными примерами:
h1
ищем элементы по имени тега
#container
ищем элемент по идентификатору id=container
(идентификатор уникален, значит, на странице он должен быть только один)
div#container
ищем <div>
c идентификатором container
, но предыдущий селектор работает быстрее, а этот важнее
.news
выбираем элементы по имени класса class="news"
div.news
все элементы <div>
c классом news
#wrap .post
ищем все элементы с классом class="post"
внутри элемента с id="wrap"
.cls1.cls2
выбираем элементы с двумя классами class="cls1 cls2"
h1, h2, .posts
перечисление селекторов, выберем всё перечисленное
.post > h2
выбираем элементы <h2>
, которые являются непосредственными потомками элемента с классом «post»
a + span
будут выбраны все элементы <span>
следующие сразу за элементом <a>
a[href^=https]
будут выбраны все элементы <a>
у которых атрибут href
начинается с https
(предположительно, все внешние ссылки)
Это отнюдь не весь список, описание же всех CSS-селекторов можно найти на соответствующей страничке W3C: https://www.w3.org/TR/selectors-3/
Возвращаясь к нашей аналогии с водопадом, представьте, что на следующей ступеньке кто-то выльет чернила другого цвета, мы же в результате получим смешение цветов. Но это в жизни, а в CSS это изменение "перекрасит воду" на всех последующих ступенях, ведь в CSS важен порядок, порядок и приоритеты. Давайте перейдём к сути:
первая ступенька нашего каскада имеет самый низкий приоритет, это стили браузера по умолчанию
как бы не заявляли разработчики, но в разных браузерах эти стили могут отличаться, поэтому всё ещё существует такое явление как CSS Reset, такой себе уравнитель
на второй ступеньке стили, заданные пользователем в недрах настроек браузера; на практике встречаются редко
самые важные для нас — стили автора странички, но и тут всё идёт по порядку
самый низкий приоритет у стилей, что подключены как файл
<link rel="stylesheet" type="text/css" href="...">
или встроены внутрь HTML с помощью тега<style>
:и естественно, при равенстве приоритетов «тапки» у того, кто объявлен последним
потом те, что захардкодили плохие люди (не вы, вы так делать не будете) в
style=""
:и тут появляется метка
!important
, и всё нам ломает, т.к. правило с такой меткой становится важнее даже inline-стилей, и всё идёт вверх-дном:чтобы перебить такой стиль, остаётся только вариант прописывать inline-стили с меткой
!important
:
приключения с
!important
не закончились, если есть пользовательские стили с данной меткой, то теперь их выходи даже браузеры грешат с
!important
, и такие стили имеют практически максимальный приоритет
Есть ещё приоритеты у правил которые используются для CSS анимации и CSS переходов, но это уже совсем другая история
Если голова ещё не болит, то я также упомяну, что при расчёте, чьи же правила главней, анализируется специфичность селекторов, и тут считается следующим образом:
расчёт происходит по трём весовым позициям —
[0:0:0]
за каждый идентификатор элемента (
#id
) —[1:0:0]
за каждый класс (
.class
), либо псевдо-класс (:pseudo
) —[0:1:0]
за каждый тег (
<a>
,<div>
, и т.д.) —[0:0:1]
при этом
[1:0:0]
>[0:x:y]
>[0:0:x]
при равенстве счета — снова «тапки» у того, кто объявлен последним
Пример селекторов, выстроенных по возрастанию приоритета (соответствующий код HTML будет ниже):
тег имеет наименьший приоритет
[0:0:1]
p { color: orange }
добавляем к тегу класс intro
[0:1:1]
p.intro { color: green }
добавляем ещё тег
[0:1:2]
article p.intro { color: blue }
... нам нужно больше классов
[0:2:2]
article.news p.intro { color: red }
идентификатор id="pinned"
даже сам по себе важней всех тегов и классов вместе взятых
[1:0:0]
#pinned { color: darkblue }
добавляем тег <p>
, и специфичность увеличивается
[1:0:1]
p#pinned { color: darkcyan }
добавляем ещё один идентификатор id="top"
[2:0:1]
#top p#pinned { color: darkgreen }
используем style
и переопределяем любые правила из внешних файлов и стилей
¯\_(ツ)_/¯
<p style="color:#333">...</p>
Есть ещё правила расчёта специфичности которые относятся к использованию определенных псевдоселекторов типа :not()
и :where()
, сам по себе такой селектор не добавляет веса к специфичности, но правило которое находится в скобках имеет вес:
Да, расчёт специфичности может действительно стать нетривиальной задачей, поэтому вот вам пару калькуляторов на выбор:
Запомните, что первоначально при использовании правил CSS ключевым является уровень специфичности селектора. И только случае, когда специфичности совпадают, будет важен порядок подключения стилей:
Ну и повторюсь, метка !important
- страшная вещь, использовать следует лишь в крайнем случае, такое правило имеет наивысший приоритет, хотя и не имеет ничего общего со специфичностью.
Домашнее задание
Вот кусочек CSS для тренировки, напишите соответствующий ему HTML (это вопрос с собеседования ;):
И ещё один:
Last updated