CSS на практике: Часть III - каскад
В прошлой серии нашей передачи шла речь о том, как наилучшим образом “получить доступ” к конкретному HTML-элементу с помощью CSS. Теперь настало время наилучшим образом этот элемент оформить.
Cascading Style Sheets - не просто название. Никогда не задавались вопросом, почему именно они cascading? Если не задавались (или до сих пор считаете, что CSS-громоздкий инструмент) - пройдите, есть разговор. Устраиваем маленькое шоу, участвуют CSS, каскады и JavaScript.
###Правила, селекторы, свойства Кратко - стилевое правило, заданное в стилевом блоке или в файле со стилями состоит из следующих частей:
/* Стилевое правило */
селектор {
свойство-1: значение-свойства-1;
свойство-2: значение-свойства-2;
}
Стилевое правило, заданное непосредственно для элемента в документе HTML, выглядит так:
<div style='свойство-1: значение-свойства-1; свойство-2: значение-свойства-2'>
</div>
###Специфичность селектора Если вы случайно прочитали заметку о селекторах вы наверное знаете, что правил, влияющих на определенный элемент, может быть сколько угодно.
Например, на параграф в таком коде:
<div id='top'>
<p>Это - абзац</p>
</div>
будут влиять следующие правила со следующими селекторами (я нарочно перегибаю с количеством):
/* Все абзацы внутри любого элемента с идентификатором top */
#top p {
}
/* Все абзацы внутри элементов div */
div p {
}
/* Все абзацы внутри элементов div с иднетификатором top */
div#top p {
}
/* Все абзацы внутри элемента body (то есть - все абзацы в документе) */
body p {
}
/* Все абзацы внутри элемента body внутри элемента HTML (то есть - все абзацы в документе) */
html body p {
}
/* Все элементы внутри всех элементов div */
div * {
}
/* Все элементы внутри любого элемента с идентификатором top */
#top * {
}
/* Все абзацы внутри любого элемента с идентификатором top,
находящегося на втором уровне вложенности во всем документе
(что равносильно селектору #top p) */
* #top p {
}
и так далее. Каждый из этих селекторов может содержать конфликтующие друг с другом правила оформления этого абзаца, и все правила из этих селекторов будут скомбинированы (скаскадированы) друг с другом. Что же будет, если мы в этих правилах создадим определения, конфликтующие друг с другом? Подзоровайтесь с каскадом - самым “хитрым” и в то же время мощным понятием CSS.
###Сводное правило
После того, как ваш документ полностью загружен браузером, браузер для каждого из элементов на вашей странице создаст так называемый (в терминах Mozilla) просчитанный стиль элемента (computed style). Это - все существующие в стандарте CSS свойства оформления элемента, заданные явным образом. Если в ваших стилевых таблицах какие-либо свойства не заданы, браузер использует свойства из своей встроенной стилевой таблицы. В результате для каждого элемента будет составлен “плоский” стиль оформления, содержащий одно значение для каждого свойства. Какое свойство выбрать в этот “плоский” стиль - браузер будет выбирать в соответствии с каскадом специфичности правил оформления. Точнее говоря - из всех существующих для элемента правил будет в итоге выбрано одно и только одно значение каждого конкретного свойства.
Вот пример, какое сводное правило составляет для абзаца на julik live Mozilla (открывается в новом окне):
А вот из каких правил берутся значения свойств (html.css - тот самый внутренний стиль браузера по умолчанию):
Чем ниже в этом списке правило, тем больше его вес (о чем пойдет речь далее).
###Что выбрать
Согласно правилам, каждое стилевое правило, заданное в CSS, имеет specificity (специфичность), которую я для простоты назову просто “весом”. В зависимости от того, насколько вы явно указываете критерии выбора элементов из документа, будет меняться и вес стилевого правила. Чем подробнее вы будете в выборе элемента - тем больше будет вес селектора, и соответственно стилевого правила, которое он определяет.
В случае, если два правила имеют одинаковый вес действует последнее из правил, которое получил браузер. То есть:
div#top {
background: red;
}
div#top {
background: green;
}
зальет фон нашего блока top зеленым цветом. В данном случае правила идентичны по весу, соответственно использованы будут свойства из последнего. Вес же правила зависи от следующих факторов:
- Где правило определено (правила, заданные в теге style имеют больший вес чем правила в стилевом файле)
- Насколько точно правило описывает вложенности (body p специфичнее чем просто p)
- Насколько точно правило указывает элементы (body * менее специфично чем body p)
- Насколько точно правило указывает класс и id элемента ( p#first и p.first специфичнее чем p)
Самому “посчитать” вес каждого конкретного правила довольно сложно - но, как становится ясно, пользуясь весом можно разносить определения одного и того же элемента по нескольким стилевым правилам, зная, как они будут взаимодействовать друг с другом. Например, зная что у нас есть заглавная страница с классом index на элементе body, мы можем сказать, что:
h1#banner {
color: black;
font-size: 14px;
}
body.index h1#banner {
font-size: 24px;
}
В результате элемент h1 с идентификатором banner получит следующее комбинированное правило на заглавное странице:
color: black;
font-size: 24px;
Разовьем идею несколько дальше. Предположим, что у нас есть оформление сайта, которое посетитель видит, попав на него ночью, и оформление сайта, которое он видит попав на него днем. Более того, у сайта есть заглавная и внутренние страницы. Для начала определим общие стили:
/* Сначала определим форматирование для всех страниц */
/* Тело документа - отступы по краям, мягкий фон */
body {
padding-left: 10em;
padding-right: 3em;
background: #ededed;
color: #797979;
font-size: small;
}
/* Абзацы - отступ побольше, интерлиньяж покрупней, шрифт поменьше, цвет-серый */
p {
margin-top: 1.5em;
line-height: 160%;
}
/* Заголовки - шрифт Georgia, цвет - темно-серый, разрядка жидкая (одна десятая круглой шпации) */
h1, h2, h3, h4 {
font-family: Georgia, Times, serif;
color: black;
letter-spacing: .1em;
}
Получим примерно примерно следующее.
Теперь добавим только те специфические особенности, которые характерны для главной страницы. Условимся, что body на главной странице будет иметь идентификатор index.
body#index {
padding-left: 0;
padding-right: 5em;
}
/* Основной заголовок побольше, с чертой.
Цвет рамок у элементов по умолчанию тот же что и цвет текста */
body#index h1 {
margin-top: 4em;
font-size: xx-large;
border-bottom-width: 1px;
border-bottom-style: solid;
padding-bottom: .8em;
}
/* Отступ слева у абзацев вместо отступа всей страницы */
body#index p {
margin-left: 10em;
}
Получим примерно такой результат.
Теперь добавим _только специфические особенности__ для ночного и дневного оформления всех страниц. На главной страницы они тоже будут действовать.
Для дня:
/* Светлый фон */
body.day {
background: #f7f3bf;
}
/* Мягкий зеленый текст */
body.day p {
color: #63756a;
}
/* Апельсиновые заголовки */
body.day h1,
body.day h2,
body.day h3,
body.day h4 {
color: #fa9a36;
}
И для ночи
body.night {
background: #a5a7c8;
}
/* По ночам читать хочется медленнее, чем обычно
- текст побольше, интерлиньяж тоже */
body.night p {
color: #60618c;
}
body.night h1,
body.night h2,
body.night h3,
body.night h4 {
color: #2b3e7c;
}
Теперь добавим кнопки, чтобы все вышеупомянутое можно было рассмотреть не отходя от кассы.
Кстати, желающие иметь “день и ночь” на сайте могут содрать соответствующий JavaScript здесь же. А что вы думали - ECMAScript - официальная спецификация.
###Не только селекторы
На вес стилевого правила также влияет то, где именно оно определено для элемента. Как известно, стили можно определять тремя способами:
- В отдельном файле (самый малый приоритет)
- В элементе style в теле HTML-документа (средний приоритет)
- В атрибуте style самого элемента (наивысший приоритет)
Соответственно, если вам надо “точно перебить” какой-то стиль, определяйте его в самом документе HTML или прямо в элементе.
###Разделяй и властвуй А теперь задание на дом. Отправляйтесь на сайт Дугласа Боумена и внимательно рассмотрите, как стилевые таблицы модуляризуются до абсолюта (что позволяет оформлять ими мало того что пяток-другой разделов, которые выглядят совершенно по-разному, так еще и менять оформление всего сайта раз в сезон, редактируя один-два файла).
###Маленькая заметка на полях Никогда, ни за что и ни при каких условиях не пытайтесь делать все это в “тупых” редакторах кода типа Dreamweaver. Они вас ограничивают – это раз, оставляют в вашем коде то, в чем вы потом сами не разберетесь – два.
Официальное описание каскадирования в русском переводе находится здесь.
###Другие части этой интересной истории