julik live

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

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

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

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

Suspects: Веб-стройка CSS на практике

 
comments powered by Disqus

Aspirine not included.