Наследование, каскадирование и приоритетность стилей CSS
http://belarusweb.net
Основы создания сайтов

Наследование, каскадирование и приоритетность стилей CSS

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

Все свойства CSS делятся на те, которые наследуются элементами-потомками от своих элементов-предков, и те, которые не наследуются. Так, например, если для параграфа задать границу (сформировать рамку), то все вложенные в него элементы (элементы-потомки) не унаследуют это свойство CSS, поскольку в данном случае наследование не имеет положительного эффекта. Согласитесь, не совсем разумно было бы переопределять для каждого элемента-потомка унаследованные от абзаца-родителя границы. Но, если мы зададим для абзаца, например, синий цвет шрифта, то он будет унаследован всеми элементами потомками до тех пор, пока мы не переопределим его в случае необходимости для конкретного элемента, а это эффективнее, чем определять шрифт отдельно для каждого элемента-потомка. Узнать, какие стилевые свойства наследуются, а какие нет, можно в нашем справочнике CSS здесь.

Каскадирование стилей CSS

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

Давайте для начала рассмотрим простейший случай, показанный в примере №1.

HTML Результат BwCodes
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">	
	<title>Наследование стилей</title>
	
	<style>
	
		p{
		color: red;		  				 
		background-color: black;    	
		}
		
		/* Для абзацев с атрибутом class="yellow_back" 
		добавляем ширину и переопределяем фон */	
		p.yellow_back{
		background-color: yellow;
		width: 200px;  	 						 
		}
		
	</style>
	
</head>
<body>

	<p>
		Текст простого абзаца.
	</p>
	
	<p class="yellow_back">
		Текст абзаца с классом.
	</p>
	
	<p class="yellow_back" style="color: blue; width: 400px;">
		Переопределяем и цвет шрифта, и ширину абзаца.
	</p>
	
</body>
</html>

Пример №1. Простейший случай каскадности стилей CSS

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

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

Специфичность селекторов CSS

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

Расчет специфичности селектора производится при помощи трех чисел (a, b, c). Происходит это следующим образом:

  • числу a присваивается количество идентификаторов в селекторе;
  • числу b присваивается суммарное количество классов, атрибутов и псевдоклассов в селекторе;
  • числу c присваивается суммарное количество элементов и псевдоэлементов.

После подсчета чисел у всех сравниваемых селекторов, селектором с большей специфичностью будет считаться тот, у которого больше число a, в независимости от величины чисел b и c. Если же у сравниваемых селекторов число a окажется одинаковым, будет сравниваться их число b, а в случае необходимости и число c (см. пример №2).

/* Запишем пример кода html */

/*  

<p class="my_class"> 
	<em id="m_id" title="Город">Текст...</em> 
</p> 
	
*/

/* Здесь а=1, т.к. в селекторе есть 1 идентификатор; */	
/* b=0, т.к. есть 0 классов, 0 атрибутов и 0 псевдоклассов; */	
/* с=0, т.к. есть 0 элементов и 0 псевдоэлементов; */
/* т.о. специфичность равна (1,0,0). */
#m_id{
color: blue;			 
}

/* Здесь а=0, т.к. в селекторе отсутствуют идентификаторы; */	
/* b=3, т.к. есть 1 класс, 1 атрибут и 1 псевдокласс; */	
/* с=2, т.к. присутствуют два элемента: 'p' и 'em'; */
/* т.о. специфичность равна (0,3,2). */

p.my_class em[title="Город"]:hover{
color: red;			 
}

/* Значит цвет текста в примере кода будет синим, т.к. 
во втором правиле число а=0, а в первом правиле а=1. */

/* А вот если бы специфичности селекторов были равны, 
то приоритет имел бы стиль нижнего правила. */

Пример №2. Сравнение специфичности селекторов

Виды и приоритет стилей CSS

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

  • Стиль браузера обладает наиболее низким приоритетом и применяется по умолчанию к элементам html-кода, к которым не применяется другое форматирование, говоря проще – к 'голому' html-коду.
  • Стиль пользователя устанавливается в настройках браузера пользователем и по сути представляет собой измененный пользователем стиль браузера по умолчанию. Так что, если пользователь изменил стиль браузера, то по умолчанию станет применяться стиль пользователя.
  • Стиль автора устанавливается автором страницы (программистом) и обладает еще большим приоритетом. Именно он нас и будет больше всего интересовать.

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

  • Стили, унаследованные элементами-потомками от своих родителей, обладают самым низким приоритетом.
  • Стили, заданные во внешних таблицах обладают большим приоритетом. При этом правила, которые идут в коде внешней таблицы стилей ниже (т.е. встречаются позже) имеют больший приоритет перед правилами, которые встречаются в коде этой таблицы выше (т.е. раньше). Кроме того, из нескольких внешних таблиц стилей большим приоритетом обладают таблицы, подключенные к документу при помощи элемента 'link' ниже в коде этого документа. Соответственно, если таблица подключена в коде документа выше, то приоритет ее стилей будет ниже.
  • Стили внутренних таблиц (расположены внутри контейнеров 'style') имеют приоритет перед стилями внешних таблиц, но только если они расположены в коде ниже, чем элемент 'link', при помощи которого была подключена внешняя таблица стилей. Опять же, правила, которые идут в коде внутренней таблицы стилей ниже имеют больший приоритет перед правилами, которые встречаются в коде этой таблицы выше. Кроме того, если в документе используется несколько внутренних таблиц стилей, т.е. имеется несколько элементов 'style', то большим приоритетом обладают стили тех таблиц, которые расположены в коде документа ниже.
  • Еще большим приоритетом обладают встроенные стили, которые преобладают над правилами с любой специфичностью селекторов. Действительно, куда уже конкретнее, если стиль расположен в открывающем теге элемента.

Служебный параметр !important

Отдельно следует сказать про служебный параметр !important (от англ. importantважный), который указывается в случае необходимости во внутренних и внешних таблицах стилей после значения css-свойства через пробел, например, p{color: green !important;} (см. пример №3). Свойство стиля, в котором указан данный параметр, обладает наибольшим приоритетом в независимости от расположения таблицы стилей в коде документа или же самого правила внутри таблицы стилей, но только в ситуации, когда специфичности стилей равны (при этом не следует забывать, что специфичность встроенного стиля следует считать наивысшей в любом случае!). Опять же, если свойств с таким параметром несколько, да еще и специфичности соответствующих селекторов одинаковы, то приоритет будет определяться по виду стиля, расположению таблиц стилей или же, если они окажутся в одной и той же таблице стилей, сравнению их расположения в коде этой таблицы.

HTML Результат BwCodes
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">  
	<title>Модификатор !important</title>

	<style>

		/* Специфичность селектора выше */
		div p.green_normal{
		color: #007700;      
		font-weight: normal;   
		}

		/* Специфичность селектора ниже, */
		/* плюс отсутствует !important */
		.bold_wrong{
		font-weight: bold;   
		}	

		/* Специфичность селектора ниже, */
		/* но присутствует !important */	
		.bold_font{
		font-weight: bold !important;   
		}

	</style>

</head>
<body>

	<div>
		<p class="green_normal">
			Получаем обычный текст, зеленого цвета.
		</p>
	</div>

	<div>
		<p class="green_normal bold_wrong">
			Начертание не стало полужирным, т.к. приоритет<br> 
			селектора .bold_font ниже, чем селектора div p.green_normal.
		</p>
	</div>

	<div>
		<p class="green_normal bold_font">
			Цвет текста остался зеленым, но начертание стало полужирным,<br> 
			т.к. в подключенном классе .bold_font присутствует !important.
		</p>
	</div>

	<div>
		<p class="green_normal bold_font">
			Цвет текста остался зеленым, но начертание стало полужирным,<br> 
			т.к. в подключенном классе .bold_font присутствует !important.<br>
			<span style="font-weight: normal">Но мое начертание осталось 
			обычным,<br> т.к. встроенный стиль имеет наивысший приоритет.</span>
		</p>
	</div>

</body>
</html>

Пример №3

Всегда пытайтесь использовать специфичность, а не модификатор !important, т.к. он усложняет отладку, нарушая естественное каскадирование стилей.

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

Использование одинаковых свойств CSS в одном правиле

В заключение данного пункта добавим, что в одном и том же правиле иногда задают два одинаковых свойства, но с разными значениями (см. пример №4). Так обычно поступают, когда одно из значений свойства не поддерживается каким-нибудь браузером, тогда его помещают в блоке объявлений (стиле) вторым, а другое правило, которое поддерживается всеми браузерами, помещают первым. В результате, если страница открывается в браузере, в котором второе правило не имеет силы, оно будет проигнорировано, а браузер применит первое правило. Если же страница открывается в браузере, в котором имеют силу и первое и второе правила, то второе правило будет иметь больший приоритет, т.к. следует в коде позже. Таким образом, в любом случае будет реализована задумка программиста, а не применено значение свойства устанавливаемое браузером по умолчанию или наследуемое от родительского элемента.

HTML Результат BwCodes
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">  
	<title>Одинаковые свойства в одном правиле</title>

	<style>

		p{
		width: 450px;
		color: blue;
		color: superblue;
		}

	</style>

</head>
<body>

	<p>
		Цвет текста будет просто синим, т.к. 
		значение superblue не поддерживается 
		браузером и будет просто проигнорировано.
	</p>
    
</body>
</html>

Пример №4

Быстрый переход к другим страницам