Главная страница   /   4.2. Каскады и наследование стилей (Руководство по HTML5

Руководство по HTML5

Руководство по HTML5

Адам Фриман

4.2. Каскады и наследование стилей

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

Браузерные стили

Браузерные стили (более известные как стили пользовательского агента) являются стилями по умолчанию, которые браузер применяет к элементу, если не были указаны другие стили. Эти стили немного различаются у разных браузеров, но они, как правило, в целом аналогичны. В качестве примера рассмотрим, как браузер отображает элемент а, гиперссылку, когда нет других стилей, определенных в HTML документе. В листинге 4-10 показан простой HTML документ, который не содержит никаких стилей.

Листинг 4-10: HTML документ, который не содержит стилей
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
</head>
<body>
	<a href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

Этот листинг является всего лишь вариацией предыдущего примера, только без всякого стиля. Вы можете увидеть, как браузер отображает элементы, на рисунке 4-7.

Рисунок 4-7: Стиль по умолчанию для элементов гиперссылки

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

Листинг 4-11: Создание стиля, сходного тому, который использует браузер по умолчанию для элемента a
a {
	color: blue;
	text-decoration: underline;
}

У браузеров нет стилей по умолчанию для каждого HTML элемента, но многие элементы отображаются с помощью таких стилей. В каждой главе этой книги, которая описывает HTML элементы, я расскажу о стилях по умолчанию, обычно применяемых браузерами. Вы можете посмотреть описание элемента a в главе 8.

Пользовательские стили

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

У каждого браузера есть свой собственный механизм для пользовательских стилей. Google Chrome, например, создает файл в папке профиля пользователя с именем Default\User StyleSheets\Custom.css. Любые стили, добавленные в этот файл, применяются к любому сайту, который посещает пользователь, при условии соблюдения правил каскадирования, которые я опишу в следующем разделе. В качестве простого примера в листинге 4-12 показан стиль, который я добавил в мой файл custom.css.

Листинг 4-12: Добавление стиля в пользовательскую таблицу стилей
a {
	color: white;
	background:grey;
	text-decoration: none;
	padding: 2px;
}

Этот стиль применяется к элементу a и переопределяет браузерный стиль по умолчанию. На рисунке 4-8 показан результат использования моего пользовательского стиля, когда я перезагружаю HTML документ листинга 4-9.

Рисунок 4-8: Определение пользовательских стилей

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

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

  1. Внутренние стили (стили, которые определяются для элемента с помощью глобального атрибута style)
  2. Встроенные стили (стили, которые определены элементом style)
  3. Внешние стили (стили, которые импортируются при помощи элемента link)
  4. Пользовательские стили (стили, которые были определены пользователем)
  5. Браузерные стили (стили по умолчанию, которые применяются браузером)

Представьте себе, что пользователю нужно отобразить элемент a. Одной из вещей, которую должен знать браузер, является цвет отображения текста. Чтобы решить этот вопрос, нужно найти значение CSS свойства color. Во-первых, браузер будет проверять, имеет ли обрабатываемый элемент внутренний стиль, который определяет значение цвета, например:

<a style="color: red" href="http://apress.com">Visit the Apress website</a>

Если внутреннего стиля нет, браузер будет искать элемент style, содержащий стиль, который применяется к обрабатываемому элементу, например:

<style type="text/css"> 
	a { 
		color: red; 
	} 
</style>

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

Первые три источника свойства (внутренние стили, встроенные стили и таблицы стилей) в совокупности именуются авторскими стилями. Стили, определенные в пользовательских таблицах стилей, известны как пользовательские стили; и стили, определенные в браузере, известны как браузерные стили.

Изменение порядка при помощи стилей important

Вы можете изменить обычный порядок каскада, отметив ваши значения свойств как important, что показано в листинге 4-13.

Листинг 4-13: Обозначение свойств стиля как important
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<style type="text/css">
		a {
			color: black !important;
		}
	</style>
</head>
<body>
	<a style="color: red" href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

Вы отмечаете отдельные значения как важные, добавляя в объявление !important. Браузер отдает предпочтение важным стилям (стилям с !important), независимо от того, где они определены. Вы можете увидеть результат использования стиля с !important на рисунке 4-9, где встроенное значение свойства color переопределяет внутреннее значение. (Возможно, это немного трудно понять по печатной странице).

Рисунок 4-9: Значения !important свойства переопределяют внутренние значения свойства

Совет

Единственным, что будет иметь приоритет над важным значением (!important), которое вы определяете, является важное значение, определенное в пользовательских таблицах стилей. Для обычных значений авторские стили используются прежде чем пользовательские стили, но это порядок меняется, когда речь идет о значениях !important.

Вычисление специфичности и порядка использования стилей с равным приоритетом

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

  1. Число значений id в селекторе стиля
  2. Число атрибутов и псевдо-классов в селекторе
  3. Число имен элементов и псевдо-элементов в селекторе

Я объясню, как создать селекторы, которые содержат все эти различные характеристики в главах 17 и 18. Браузер подсчитывает значения каждой оценки и применяет значение свойства наиболее специфичного стиля. Очень простой пример специфичности представлен в листинге 4-14.

Листинг 4-14: Специфичность стилей
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<style type="text/css">
		a {
			color: black;
		}

		a.myclass {
			color: white;
			background: grey;
		}
	</style>
</head>
<body>
	<a href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a class="myclass" href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

При оценке специфичности вы создаете число в виде a-b-c, где каждая буква является итоговой суммой одной из трех подсчитываемых характеристик. Это не трехзначное число: более специфичным является тот стиль, чье значение a является наибольшим. Только если a значения равны, браузер сравнивает значения b: стиль с большим значением b является более специфичным в данном случае. Только если оба значения a и b равны, браузер рассматривает значение с. Это обозначает, что специфичность 1-0-0 является более приоритетной, чем 0-5-5.

В нашем случае селектор a.myclass включает в себя атрибут класса, а это значит, что специфичность стиля равна 0-1-0 (0 значений id + 1 другой атрибут + 0 имен элементов). Другой стиль имеет специфичность равную 0-0-0 (то есть, он не содержит id, других атрибутов или имен элементов). Браузер находит значение свойства color при обработке a элемента, который был назначен классу myclass. Для всех остальных a элементов будет использоваться значение другого стиля. Вы можете увидеть, как браузер выбирает и применяет значения для данного примера, на рисунке 4-10.

Рисунок 4-10: Применение значений нужных стилей, основываясь на их специфичности

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

Листинг 4-15: Стили с одинаковой специфичностью
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<style type="text/css">
		a.myclass1 {
			color: black;
		}

		a.myclass2 {
			color: white;
			background: grey;
		}
	</style>
</head>
<body>
	<a href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a class="myclass1 myclass2" href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

Оба стиля, определенные в элементе style, имеют одинаковые оценки специфичности. Когда браузер будет представлять второй элемент а на странице, он выберет значение white для обозначения свойства color, потому что это значение определено в последнем стиле. Вы можете увидеть результат на рисунке 4-11.

Рисунок 4-11: Выбор значения свойства на основании порядка, в котором определены стили

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

Листинг 4-16: Изменение порядка определения стилей
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<style type="text/css">
		a.myclass2 {
			color: white;
			background: grey;
		}

		a.myclass1 {
			color: black;
		}
	</style>
</head>
<body>
	<a href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a class="myclass1 myclass2" href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

Как и ожидалось, значением, которое браузер выберет для свойства color, теперь будет black, что и показано на рисунке 4-12.

Рисунок 4-12: Результат изменения порядка определения стилей

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

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

Если браузер не может найти значение свойства в одном из доступных стилей, он будет использовать наследование, то есть он будет использовать значение свойства, определенного родительским элементом. В листинге 4-17 представлен пример.

Листинг 4-17: Наследование CSS свойства
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<style type="text/css">
		p {
			color: white;
			background: grey;
			border: medium solid black;
		}
	</style>
</head>
<body>
	<a href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a class="myclass1 myclass2" href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

В этом примере мы заинтересованы в свойствах, которые браузера применяет к элементу span, чьим родительским элементом является элемент p. Вы можете увидеть, как браузер обрабатывает этот документ, на рисунке 4-13.

Рисунок 4-13: Применение унаследованного значения CSS свойства

Нигде в этом документе я не определял в стиле значение для свойства color, которое применяется к элементу span, но браузер использует значение white для отображения текстового содержания. Это значение было унаследовано от родительского элемента p.

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

Листинг 4-18: Использование специального значения inherit
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<style type="text/css">
		p {
			color: white;
			background: grey;
			border: medium solid black;
		}

		span {
			border: inherit;
		}
	</style>
</head>
<body>
	<a href="http://apress.com">Visit the Apress website</a>
	<p>I like <span>apples</span> and oranges.</p>
	<a class="myclass1 myclass2" href="http://w3c.org">Visit the W3C website</a>
</body>
</html>

В этом примере я создал стиль, который будет применен к элементу span и унаследует значение свойства border родительского элемента. Вы можете увидеть результат на рисунке 4-14. Сейчас вокруг элемента span есть рамка, и она содержится в элементе p.

Рисунок 4-14: Использование наследуемого свойства