Наследование и каскадность

В этой главе:

  • Наследование

  • Вычисление специфичности (приоритета) селекторов

  • Каскадность

Наследование

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

Например, все элементы расположенные внутри элемента <body> являются его дочерними элементами и потомками. Если в стиле для <body> задать с помощью свойства color красный цвет текста, то цвет текста всех его дочерних элементов и потомков тоже станет красным.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Название документа</title>
    <style>
      body { color: red; }
    </style>
  </head>
  <body>
 
    <h1>Цвет текста заголовка красный</h1>
    <p>Цвет текста абзаца тоже красный.</p>
 
  </body>
</html>

Наследуемые свойства можно переопределить, применив индивидуальное правило для нужного элемента.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Название документа</title>
    <style>
      body { color: red; }
      h1 { color: blue; } /* переопределили цвет текста внутри элементов h1 */
    </style>
  </head>
  <body>
    <h1>Цвет текста заголовка синий</h1>
    <p>Цвет текста абзаца красный.</p>
  </body>
</html>

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

Вычисление специфичности (приоритета) селекторов

Существует множество способов применить стиль оформления к нужному элементу. Но что происходит, если один элемент выбирают два или более взаимоисключающих селектора? Эта дилемма решается с помощью двух принципов CSS: специфичности селекторов и каскада.

Специфичность селекторов (selector's specificity) определяет их приоритетность в таблице стилей. Чем специфичнее селектор, тем выше его приоритет. Для вычисления специфичности селектора используются три группы чисел (a, b, c), расчёт производится следующим образом:

  • Считается число идентификаторов в селекторе (=a)

  • Считается число селекторов классов, атрибутов и псевдо-классов в селекторе (=b)

  • Считается число селекторов типа и псевдо-элементов в селекторе (=c)

  • Селектор внутри псевдо-класса отрицания (:not) считается как любой другой селектор, но сам псевдо-класс отрицания не участвует в вычислении селектора

  • Универсальный селектор (*) и комбинаторы не участвуют в вычислении веса селектора

В примере селекторы расположены в порядке увеличения их специфичности:

1
2
3
4
5
6
7
8
9
*               /* a=0 b=0 c=0 -> специфичность =   0 */
li              /* a=0 b=0 c=1 -> специфичность =   1 */
ul li           /* a=0 b=0 c=2 -> специфичность =   2 */
ul ol+li        /* a=0 b=0 c=3 -> специфичность =   3 */
h1 + *[rel=up]  /* a=0 b=1 c=1 -> специфичность =  11 */
ul ol li.red    /* a=0 b=1 c=3 -> специфичность =  13 */
li.red.level    /* a=0 b=2 c=1 -> специфичность =  21 */
#x34y           /* a=1 b=0 c=0 -> специфичность = 100 */
#s12:not(p)     /* a=1 b=0 c=1 -> специфичность = 101 */

Самый высокий приоритет имеет число из группы (a), число группы (b) имеет средний приоритет, число из группы (c) имеет наименьший приоритет. Числа из разных групп не суммируются в одно общее, т.е. возьмём из примера последнюю строку со специфичностью селектора (101) - это не означает число "сто один", это значит, что был использован один селектор из группы "a" (идентификатор) и один селектор из группы "c" (селектор типа).

Стиль для элемента, определённый внутри атрибута style, имеет больший приоритет, чем любой селектор, определённый в таблице стилей. Однако, если для конкретного свойства в таблице стилей указать специальное объявление !important, то оно будет иметь больший приоритет, чем значение аналогичного свойства, указанного в атрибуте style.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Название документа</title>
    <style>
      #one { color: red; }
      #two { color: blue !important; }
    </style>
  </head>
  <body>
 
    <p id="one" style="color: yellow;">Первый абзац</p>
    <p id="two" style="color: yellow;">Второй абзац.</p>
 
  </body>
</html>

Каскадность

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Название документа</title>
    <style>
      p { color: yellow; }
      p { color: red; }
      p { color: green; } /* для элемента будет установлен зелёный цвет текста */
    </style>
  </head>
  <body>
    <p>Цвет текста абзаца зелёный.</p>
  </body>
</html>

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

1
2
3
4
5
6
h1 {
  color: gray;
  font-family: sans-serif;
}
 
h1 { border-bottom: 1px solid black; }

Код, расположенный в примере выше, равносилен коду в примере ниже, в котором все три свойства указаны в одном правиле.

1
2
3
4
5
h1 {
  color: gray;
  font-family: sans-serif;
  border-bottom: 1px solid black;
}

Обычно дополнительные правила для элемента указываются в тех случаях, когда был задан один стиль сразу для нескольких элементов, но помимо этого необходимо добавить что-то ещё для определённого элемента, например:

1

2

3

4

5

6

h1, h2, h3 /* одинаковый стиль для трёх элементов */
  color: gray;
  font-family: sans-serif;
}
/* дополнительное правило для заголовков второго уровня */
h2 { border-bottom: 1px solid black; }