В прошлой серии нашей передачи шла речь о том, как наилучшим образом “получить доступ” к конкретному 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 - тот самый внутренний стиль браузера по умолчанию):

Список стилевых правил в DOM inspector

Чем ниже в этом списке правило, тем больше его вес (о чем пойдет речь далее).

###Что выбрать

Согласно правилам, каждое стилевое правило, заданное в 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. Они вас ограничивают – это раз, оставляют в вашем коде то, в чем вы потом сами не разберетесь – два.

Официальное описание каскадирования в русском переводе находится здесь.

###Другие части этой интересной истории