Присвоение значений свойствам, каскады и наследование
6 Присвоение значений свойствам, каскады и наследование
Содержание
6.1 Заданные, вычисляемые и фактические значения
После того, как пользовательский агент произвел синтаксический анализ документа и создал дерево документа, он должен присвоить каждому свойству каждого элемента этого дерева некоторое значение, применяемое к целевому устройству.
Присвоение значения произвольному свойству осуществляется в три этапа: сначала значение определяется в соответствии со спецификацией "заданное значение"), затем при необходимости оно приводится к абсолютным величинам ("вычисляемое значение") и в заключение подвергается преобразованиям, необходимым вследствие ограничений локального окружения ("фактическое значение").
6.1.1 Заданные значения
Агенты пользователей в первую очередь присваивают свойству заданное значение, руководствуясь следующей последовательностью действий (перечисленных в порядке убывания приоритета):
- Присваивается значение, являющееся результатом каскада.
- В противном случае, если свойство является наследуемым, то ему присваивается значение родительского элемента, которое чаще всего является вычисляемым.
- В противном случае свойству присваивается начальное значение, которое задается в его определении.
Т.к. корневой элемент дерева документа не имеет родительского элемента, то для него невозможно использовать значения родительского элемента. В этом случае используется начальное значение.
6.1.2 Вычисляемые значения
Заданные значения могут быть как абсолютными (задаются относительно другого значения, например, 'red' или '2mm'), так и относительными (задаются относительно другого значения, например, 'auto', '2em' и '12%'). Чтобы получить вычисляемое значение, для абсолютных значений не требуется никаких преобразований.
Что касается относительных значений, то они должны быть преобразованы в вычисляемые значения следующим образом: процентные соотношения должны быть умножены на значение, относительно которого они заданы (для каждого свойства определено свое такое значение); значения с относительными единицами измерения (em, ex, px) должны быть преобразованы в абсолютные путем умножения на величину, равную размеру шрифта или пикселя; значения 'auto' должны быть вычислены по формулам, заданным для каждого свойства; некоторые ключевые слова ('smaller', 'bolder', 'inherit') должны быть заменены в соответствии с их определениями.
Чаще всего элементы наследуют вычисляемые значения. Однако имеется несколько свойств, заданные значения которых могут быть унаследованы (например, численное значение свойства 'line-height'). Если дочерние элементы не наследуют вычисляемое значение, то этот факт отражается в определении свойства.
6.1.3 Фактические значения
Вычисляемое значение, в принципе, готово к применению, но вполне возможно, что агент пользователя не сможет его использовать в заданном окружении. Например, агент может отображать границы, ширина которых задается только целочисленными значениями, и поэтому будет вынужден округлять вычисленное значение ширины. Фактическим значением является вычисленное значение, к которому были применены все возможные аппроксимации.
6.2 Наследование
Некоторые значения наследуются дочерними элементами в дереве документа. Каждое свойство определяет, является оно наследуемым или нет.
Предположим, что имеется элемент H1, в котором расположен элемент выделения EM:
<H1>Данный заголовок <EM>очень</EM> важен!</H1>
Если для элемента EM не задан цвет, то слово "очень" унаследует цвет родительского элемента. Таким образом, если для H1 определен синий цвет, то и элемент EM будет представлен синим цветом.
Определение свойств стиля, используемого в документе по умолчанию, разработчики могут осуществить в корневом элементе дерева данного документа. Например, в языке HTML эту возможность можно реализовать с помощью элементов HTML или BODY. Обратите внимание, что данная схема будет работать, даже если разработчик пропустил тег BODY в исходном HTML-документе, т.к. синтаксический анализатор HTML сам сгенерирует пропущенный тег.
Например, свойство 'color' является наследуемым, поэтому все потомки элемента BODY унаследуют цвет 'black':
BODY { color: black; }
Значения, заданные в процентах, не наследуются, а вычисляемые значения наследуются.
Пусть задана следующая таблица стиля:
BODY { font-size: 10pt } H1 { font-size: 120% }
и фрагмент документа:
<BODY> <H1>Некоторый <EM>крупный</EM> заголовок</H1> </BODY>
Свойство 'font-size' элемента H1 будет иметь вычисленное значение '12pt' (120% от 10pt, являющегося значением свойства родительского элемента). Так как вычисляемое значение свойства 'font-size' является наследуемым, то элемент EM также будет иметь вычисленное значение '12pt'. Если агент пользователя не может отобразить шрифт размером в 12pt, то фактическим значением свойства 'font-size' для обоих элементов H1 и EM может быть, например, '11pt'.
6.2.1 Значение 'inherit'
Для каждого свойства может быть задано значение 'inherit', которое означает, что для данного элемента это свойство принимает такое же вычисляемое значение, как и свойство родительского элемента. Наследуемое значение, которое обычно используется для предупреждения ошибок, может быть усилено, если задать явно значение 'inherit'.
В приведенных ниже примерах свойства 'color' и 'background' заданы внутри элемента BODY. Все другие элементы наследуют значение 'color', а фон будет прозрачным. Если эти правила являются частью пользовательской таблицы стилей, то во всем документе текст будет отображаться черным цветом на белом фоне.
BODY { color: black !important; background: white !important; } * { color: inherit !important; background: transparent; }
6.3 Правило @import
Правило '@import' позволяет пользователям импортировать правила стилей из других таблиц стилей. Массив правил @import должен предшествовать всем другим правилам в таблице стилей. После ключевого слова '@import' должен следовать URI таблицы стилей, которую необходимо импортировать. Также допускается использование строки. В этом случае подразумевается, что она заключена в url(...).
Следующие строки эквивалентны по значению и представляют два варианта синтаксиса правила '@import' (один с использованием "url()" и один с открытой строкой):
@import "mystyle.css"; @import url("mystyle.css");
Т.к. агенты пользователей могут не загружать ресурсы для неподдерживаемых типов устройств, то разработчики могут задать зависящие от устройств правила @import. В этих условных правилах импортирования после URI задается список типов устройств, разделенных запятыми.
Действие приведенных ниже правил происходит так, как если бы импортируемая таблица стилей при прочих равных условиях присоединялась посредством правила @media с той лишь разницей, что они позволяют пользовательскому агенту не выполнять бесполезную загрузку.
@import url("fineprint.css") print; @import url("bluish.css") projection, tv;
При отсутствии каких-либо типов устройств импорт не зависит ни от каких условий. Если при этом использовать значение 'all' для импортируемых аппаратных средств, то будет достигнут аналогичный эффект.
6.4 Каскад
Таблицы стилей имеют три источника: разработчик, пользователь и агент пользователя.
- Разработчик. Разработчик создает таблицы стилей для исходного документа в соответствии с договоренностями, принятыми в языке документа. Например, в языке HTML таблицы стилей могут быть интегрированы в документ или подключены извне.
- Пользователь. Пользователь может задать информацию о стиле конкретного документа. Например, он может создать файл с таблицей стилей, или агент пользователя может предоставить ему интерфейс, позволяющий сгенерировать пользовательскую таблицу стилей (или работать так, как будто она есть).
- Агент пользователя. Конформные агенты пользователей должны сначала применить таблицу стиля, используемую по умолчанию (или работать так, как будто они это сделали), а затем все остальные таблицы стилей. Таблица стилей, используемая агентом по умолчанию, должна представлять элементы языка документа таким образом, чтобы удовлетворять основным требованиям к их отображению (например, элемент EM языка HTML визуальные агенты отображают курсивом). Информацию о таблице стилей, рекомендуемой для использования по умолчанию в документах на языке HTML 4.0, можно найти в разделе "Пример таблицы стилей для HTML 4.0".
Обратите внимание, что используемые по умолчанию таблицы стилей могут измениться, если пользователь изменит системные установки (например, системные цвета). Однако вследствие ограничений, накладываемых внутренней реализацией агента пользователя, изменение значений в используемой по умолчанию таблице стилей может быть невозможно.
Области действия таблиц стилей, созданных любым из трех этих субъектов, могут пересекаться, и тогда их взаимодействие осуществляется в соответствии с принципами каскада.
Каскад CSS назначает каждому правилу стиля определенный приоритет. При выполнении нескольких правил преимущество имеет правило с большим приоритетом.
По умолчанию правила в таблицах стилей разработчика имеют больший приоритет, чем правила в пользовательских таблицах стилей. Однако для правил "!important" ситуация противоположна. Все правила пользователей и разработчиков имеют более высокий приоритет, чем правила таблиц стилей, используемых по умолчанию в агенте пользователя.
Кроме того, импортируемые таблицы стилей каскадируются, и их приоритет зависит от порядка импортирования. Правила, определенные в заданной таблице стилей, отменяют правила, импортируемые из других таблиц стилей. Импортируемые таблицы стилей сами могут рекурсивно импортировать и отклонять другие таблицы стилей и применять те же самые правила приоритетов.
6.4.1 Порядок каскадирования
Чтобы найти значение для комбинации элемент/свойство, агенты пользователей должны применять следующие правила сортировки:
- Найти все объявления, которые в соответствии с типом конечного устройства применяются к рассматриваемой паре элемент/свойство. Объявление применяется, если рассматриваемому элементу сопоставляется связанный с ним селектор.
- Первичная сортировка объявлений выполняется по приоритету и источнику: что касается обычных объявлений, то таблицы стилей разработчика имеют приоритет над пользовательскими таблицами стилей, которые, в свою очередь, имеют приоритет над таблицей стилей, используемой по умолчанию. Для объявлений "!important" пользовательские таблицы стилей имеют приоритет над таблицами стилей разработчика, которые, в свою очередь, имеют приоритет над таблицей стилей, используемой по умолчанию. Объявления "!important" имеют приоритет над обычными объявлениями. Импортируемая таблица стилей имеет тот же источник (разработчика), что и таблица стилей, в которую она импортирована.
- Вторичная сортировка выполняется по специфичности селектора: более специфичные селекторы имеют приоритет над более общими селекторами. Псевдоэлементы и псевдоклассы считаются обычными элементами и классами, соответственно.
- И наконец, сортировка в соответствии с порядком следования: если два правила имеют одинаковые приоритет, источник и специфичность, то будет использоваться правило, описанное последним. Считается, что правила импортируемых таблиц стилей должны располагаться перед правилами таблицы стилей, в которую осуществляется импорт.
Если не принимать во внимание установку "!important" для отдельных объявлений, то данная стратегия предоставляет таблицам стилей разработчика более высокий приоритет, чем таблицам стилей пользователя. Поэтому важно, чтобы агент предоставлял пользователю возможность отключать определенные таблицы стилей, например, с помощью выпадающего меню.
6.4.2 Правила !important
В CSS предпринята попытка установить баланс между возможностями таблиц стилей разработчика и пользователя. По умолчанию правила в таблице стилей разработчика имеют приоритет над правилами пользовательской таблицы стилей (см. третье правило каскада).
Однако для соблюдения баланса объявление "!important" (объявление сопровождается ключевыми словами "!" и "important") наделяется преимуществом перед обычным объявлением. Таблицы стилей как разработчика, так и пользователя могут содержать объявления "!important", но пользовательские правила "!important" имеют приоритет над правилами "!important" разработчика. Эта особенность CSS улучшает возможность доступа к документам, предоставляя пользователям со специальными требованиями (большие размеры шрифтов, сочетания цветов и т.д.) более гибкий контроль над представлением.
Примечание. Это является семантическим отличием от CSS1. В CSS1 правила "!important" разработчика имеют преимущество над пользовательскими правилами "!important".
Объявление свойства стенографического типа (например, 'background') как "!important" равнозначно объявлению всех содержащихся в нем свойств как "!important".
В следующем примере первое правило пользовательской таблицы стилей содержит объявление "!important", которое имеет приоритет над соответствующим объявлением в таблице стилей разработчика. Второе объявление также имеет больший приоритет, так как оно помечено "!important". Однако третье правило в пользовательской таблице стилей не является правилом "!important", и поэтому более высокий приоритет будет иметь второе правило в таблице стилей разработчика (которое устанавливает стиль в свойстве стенографического типа). Кроме того, третье правило разработчика имеет меньший приоритет, чем второе его правило, так как последнее является "!important". Это говорит о том, что объявления "!important" работают также и в таблицах стилей разработчика.
/* Из пользовательской таблицы стилей */ P { text-indent: 1em ! important } P { font-style: italic ! important } P { font-size: 18pt } /* Из таблицы стилей разработчика */ P { text-indent: 1.5em !important } P { font: 12pt sans-serif !important } P { font-size: 24pt }
6.4.3 Вычисление специфичности селектора
Специфичность селектора вычисляется следующим образом:
- подсчитывается число атрибутов ID в данном селекторе (= a);
- подсчитывается число других атрибутов и псевдоклассов в данном селекторе (= b);
- подсчитывается число имен элементов в данном селекторе (= c);
- псевдоэлементы игнорируются.
После конкатенации трех чисел a-b-c (в системе счисления с большим основанием) получается специфичность.
Несколько примеров:
* {} /* a=0 b=0 c=0 -> специфичность = 0 */ LI {} /* a=0 b=0 c=1 -> специфичность = 1 */ UL LI {} /* a=0 b=0 c=2 -> специфичность = 2 */ UL OL+LI {} /* a=0 b=0 c=3 -> специфичность = 3 */ H1 + *[REL=up]{} /* a=0 b=1 c=1 -> специфичность = 11 */ UL OL LI.red {} /* a=0 b=1 c=3 -> специфичность = 13 */ LI.red.level {} /* a=0 b=2 c=1 -> специфичность = 21 */ #x34y {} /* a=1 b=0 c=0 -> специфичность = 100 */
В HTML значениями атрибута "style" элемента являются правила таблицы стилей. Эти правила не имеют селекторов, но с целью обеспечения правомочности шага 3 алгоритма каскадирования предполагается, что у них имеется селектор ID (специфичность: a=1, b=0, c=0). С целью обеспечения правомочности шага 4, считается, что они располагаются после всех остальных правил.
<HEAD> <STYLE type="text/css"> #x97z { color: blue } </STYLE> </HEAD> <BODY> <P ID=x97z style="color: red"> </BODY>
В приведенном выше примере цвет элемента P должен быть красным. Несмотря на то, что оба объявления имеют одинаковую специфичность, объявление в атрибуте "style" отменит объявление в элементе STYLE в соответствии с четвертым правилом каскадирования.
6.4.4 Приоритеты оформительских рекомендаций, не принадлежащих CSS
Вопрос о соблюдении оформительских рекомендаций, не содержащихся в таблицах стилей (например, элемент FONT или атрибут "align" в HTML), а агенты пользователей оставляют на свое усмотрение. Если агент решает придерживаться их, то они должны быть преобразованы в соответствующие правила CSS, специфичность которых равна нулю. Предполагается, что эти правила находятся в начале таблицы стилей разработчика и могут быть отменены последующими правилами таблицы стилей.
Примечание. На этапе преобразования этот метод упростит совместное существование стилистических атрибутов и таблиц стилей.
Примечание. В CSS1 оформительским рекомендациям, не принадлежащим CSS, была присвоена специфичность, равная 1, а не 0. Принятое здесь изменение было сделано из-за того, что был введен универсальный селектор, специфичность которого равна 0.