16. Каскадные таблицы стилей

Каскадные таблицы стилей (Cascading Style Sheets, CSS) – это стандарт визуального представления HTML-документов. Каскадные таблицы стилей предназначены для использования дизайнерами: они позволяют точно определить шрифты, цвета, величину полей, выравнивание, параметры рамок и даже координаты элементов в документе. Но они также представляют интерес и для программистов, пишущих на клиентском языке JavaScript, потому что позволяют воспроизводить анимационные эффекты, такие как плавное появление содержимого документа из-за правого края, например, или сворачивание и разворачивание списков, благодаря чему пользователь получает возможность управлять объемом отображаемой информации. Когда подобные визуальные эффекты только появились, они казались революционными. Совместное применение технологий CSS и JavaScript, обеспечивающее получение разнообразных визуальных эффектов, получило не совсем удачное название «динамический язык HTML» (Dynamic HTML, DHTML), которое уже вышло из употребления.

CSS – достаточно сложный стандарт, который на момент написания этих строк продолжал активно развиваться. Тема CSS настолько объемная, что для полного ее охвата потребовалось бы написать отдельную книгу, и ее детальное обсуждение выходит далеко за рамки этой книги. Однако чтобы освоить принципы работы с каскадными таблицами стилей, совершенно необходимо знать хотя бы основы CSS и наиболее часто используемые стили. Поэтому эта глава начинается с обзора CSS, за которым следует описание ключевых стилей, наиболее часто используемых в сценариях. Вслед за этими двумя вводными разделами глава переходит к описанию принципов работы с CSS. В разделе 16.3 описываются наиболее общие и важные приемы: изменение стилей, применяемых к отдельным элементам документа с помощью HTML-атрибута style. Атрибут style элемента можно использовать для задания стилей, но с его помощью нельзя узнать текущие настройки стилей элементов. В разделе 16.4 рассказывается, как можно получить вычисленные стили любого элемента. В разделе 16.5 вы узнаете, как можно изменить сразу несколько стилей путем изменения атрибута style элемента. Имеется также возможность непосредственно управлять таблицами стилей, хотя это и редко используется на практике. В разделе 16.6 будет показано, как включать и отключать таблицы стилей, изменять правила в существующих таблицах и добавлять новые таблицы.

Рекомендуемое издание: Эрик Мейер «CSS – каскадные таблицы стилей. Подробное руководство», 3-е издание - Пер. с англ. - СПб.: Символ-Плюс, 2008. 16.1. Обзор CSS 445

содержание 16.1. Обзор CSS содержание

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

font-weight: bold

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

margin-left: 10%;  /* левое поле 10% от ширины страницы */
text-indent: .5in; /* отступ 1/2 дюйма */
font-size: 12pt:   /* размер шрифта 12 пунктов */

Как видите, в каскадные таблицы стилей можно помещать комментарии, заключая их в пары символов /* и */. Однако здесь не поддерживаются комментарии, начинающиеся с символов //.

Существует два способа связать набор значений CSS-свойств с HTML-элементами, чье визуальное представление они определяют. Первый заключается в установке атрибута style отдельного HTML-элемента. Такие стили называются встроенными:

<p style="margin: 20px; border: solid red 2px;">
Зтот абзац имеет увеличенные поля и окружен прямоугольной рамкой красного цвета.
</p>

Однако намного эффективнее отделять стили CSS от отдельных HTML-элементов и определять их в таблицах стилей. Таблица стилей связывает наборы свойств стилей с группами HTML-элементов, которые описываются с помощью селекторов. Селектор определяет, или «выбирает», один или более элементов документа, опираясь на атрибут id или class, имя тега или на другие более специализированные критерии. Селекторы были представлены в разделе 15.2.5, где также было показано, как с помощью querySelectorAll() выбрать группу элементов, соответствующих селектору.

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

p {                  /* селектору "p" соответствуют все элементы <p> */
  text-indent: .5in; /* первая строка с отступом 0,5 дюйма */
}
.warning {                  /* Любой элемент с атрибутом class="warning" */
  background-color: yellow: /* будет иметь желтый фон */
  border: solid black 5px;  /* и толстую черную рамку */
}

Таблицу стилей CSS можно добавить в HTML-документ, заключив ее в теги <sty1е> и </sty1е> внутри тега <head>. Подобно элементам <script>, синтаксический анализ содержимого элементов <sty1е> выполняется отдельно и не интерпретируется как разметка HTML:

<html>
<head><title>Текстовый документ</title>
<style>
  body { margin-left: ЗОрх; margin-right: 15px; background-color: #fffffff }
  p { font-size: 24px; }
</style>
</head>
<body><p>Проверка, проверка</р>
</html>

Если таблица стилей используется более чем в одной странице веб-сайта, ее обычно лучше сохранить в отдельном файле, без использования объемлющих HTML- тегов. Затем этот файл CSS можно будет подключить к HTML-странице. В отличие от элемента <script>, элемент <style> не имеет атрибута src. Чтобы подключить таблицу стилей к HTML-странице, следует использовать элемент <link> в теге <head> документа:

<head>
  <title>Текстовый документ</title>
  <link rel="stylesheet" href="mystyles.css" type="text/css">
</head>

Мы вкратце рассмотрели, как работают каскадные таблицы стилей. При этом с таблицами CSS связано несколько важных моментов, которые нужно знать и которые описываются в следующих подразделах.

содержание 16.1.1. Каскад правил

Напомню, что буква «C» в аббревиатуре CSS обозначает «cascade» (каскадная). Этот термин указывает, что правила стилей, применяемые к конкретному элементу документа, могут быть получены из «каскада» различных источников:

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

Для отображения любого элемента документа веб-браузер должен объединить атрибут style элемента со стилями из всех совпавших селекторов таблицах стилей документа. Результатом этого объединения является фактический набор свойств стилей и значений, которые используются для отображения элемента. Этот набор значений называется вычисленным стилем элемента.

содержание 16.1.2. История развития CSS

CSS – это довольно старый стандарт. В декабре 1996 года был принят стандарт CSS1 и определены атрибуты для задания цвета, шрифта, полей, рамок и других базовых стилей. Такие старые браузеры, как Netscape 4 и Internet Explorer 4, в значительной степени поддерживают CSS1. Вторая редакция стандарта, CSS2, была принята в мае 1998 года; она определяет более развитые возможности, наиболее важной из которых является возможность абсолютного позиционирования элементов. Версия CSS2.1 дополняет и уточняет положения стандарта CSS2. Из нее были исключены возможности, которые не были реализованы в браузерах. Текущие браузеры практически полностью реализуют поддержку стандарта CSS2.1, хотя в версиях IE, предшествовавших IE8, имеются существенные пробелы.

Работа над CSS продолжается и в настоящее время. Третья версия CSS разделена на специализированные модули, работа по стандартизации которых ведется по отдельности. Спецификации и рабочие проекты CSS можно найти по адресу http://www.wS.org/Style/CSS/current-work.

содержание 16.1.3. Сокращенная форма определения свойств

Свойства стиля, которые часто используются совместно, допускается объединять вместе, используя сокращенную форму записи. Например, свойства font-family, font-size, font-style и font-weight можно определить в виде единственного свойства font с составным значением:

font: bold italic 24pt helvetica;

Аналогично свойства border, margin и padding являются сокращенными именами для свойств, определяющих параметры рамок, полей и отступов (пространство между рамкой и содержимым элемента) для каждой из сторон элемента. Например, чтобы определить параметры рамки для каждой из сторон в отдельности, вместо свойства border можно использовать свойства border-left, border-right, border-top и border-bottom. Каждое из этих свойств также является сокращенной формой записи. Вместо свойства border-top можно определить свойства border-top-color, border-top-style и border-top-width.

содержание 16.1.4. Нестандартные свойства

Когда производители браузеров реализуют нестандартные свойства CSS, они добавляют префикс к именам свойств. В браузере Firefox используется префикс moz-, в Chrome используется -webkit-, а в IE используется -ms-. Производители браузеров добавляют префиксы, даже когда реализуют свойства, которые в будущем, как предполагается, будут включены в стандарт. В качестве примера можно назвать свойство border-radius, которое определяет закругленные углы. Это свойство впервые было реализовано как экспериментальное в Firefox 3 и Safari 4, и к его имени были добавлены соответствующие префиксы. Когда стандарт устоялся в достаточной степени, в версиях Firefox 4 и Safari 5 префикс был убран, и теперь они поддерживают свойство border-radius без префикса. (Chrome и Opera уже давно поддерживают это свойства без префикса. IE9 также поддерживает его без префикса, но IE8 не поддерживает его, даже с префиксом.)

При работе со свойствами CSS, которые в разных браузерах имеют отличающиеся имена, можно определять для таких свойств классы:

.radius10 {   
  border-radius: 10px; /* для текущих браузеров */
  -moz-border-radius: 10px; /* для Firefox 3.x */
  -webkit-border-radius: 10px; /* для Safari 3.2 и 4 */
}  

Определив такой класс, можно просто добавить значение «radiuslO» в атрибут class любого элемента, чтобы дать элементу рамку с закругленными углами.

содержание 16.1.5. Пример CSS-таблицы

Пример 16.1 представляет собой HTML-файл, определяющий и использующий таблицу стилей. Он иллюстрирует селекторы, базирующиеся на имени тега, атрибутах class и id, а также содержит встроенный стиль, определяемый атрибутом style. На рис. 16.1 показано, как этот пример отображается в браузере.

cheme

Рис. 16.1. Веб-страница, оформленная с помощью CSS

Пример 16.1. Определение и использование каскадных таблиц стилей

Example 16-1. Defining and using Cascading Style Sheets <head>
<style type="text/css">
/* Указывает, что заголовки отображаются курсивом синего цвета. */
h1, h2 { color: blue; font-style: italic }
/*
* Любой элемент с атрибутом class="WARNING" отображается крупными жирными
* символами, имеет большие поля и желтый фон с жирной красной рамкой.
*/
.WARNING {
          font-weight: bold;
          font-size: 150%;
          margin: 0 1in 0 1in; /* сверху справа, снизу слева */
          background-color: yellow;
          border: solid red 8px;
          padding: 10px; /* 10 пикселов со всех 4 сторон */
}
/*
* Текст заголовков h1 и h2 внутри элементов с атрибутом class="WARNING"
* должен быть выровнен по центру, в дополнение к выделению синим курсивом.
*/
.WARNING h1, .WARNING h2 { text-align: center }
/* Отдельный элемент с атрибутом id="special" отображается прописными буквами по центру. */
#special {
          text-align: center;
          text-transform: uppercase;
}
</style>
</head>
<body>
<h1>Cascading Style Sheets Demo</h1>
<div class="WARNING">
<h2>Warning</h2>
This is a warning!
Notice how it grabs your attention with its bold text and bright colors.
Also notice that the heading is centered and in blue italics.
</div>
<p id="special">
This paragraph is centered<br>
and appears in uppercase letters.<br>
<span style="text-transform: none">
Here we explicitly use an inline style to override the uppercase letters.
</span>

Ультрасовременные свойства CSS

Когда я работал над этой главой, CSS находился в процессе революционных изменений: производители браузеров реализовали поддержку новых мощных свойств стиля, таких как border-radius, text-shadow, box-shadow и column-count. Другой качественно новой возможностью CSS стали веб-шрифты: новое CSS-правило @font-face позволяет загружать и использовать нестандартные шрифты (подробнее о шрифтах, которые свободно могут использоваться в веб-страницах, и о простом механизме их загрузки с серверов компании Google можно прочитать на странице http://code.google.com/webfonts).

Еще одной революционной разработкой в области каскадных таблиц стилей стал модуль «CSS Transitions». Этот проект стандарта определяет возможности, позволяющие преобразовать в анимационные эффекты любые динамические изменения стилей CSS в документе (когда поддержка этого стандарта будет реализована достаточно широко, это позволит избавиться от программного кода, воспроизводящего анимационные эффекты, связанные со сменой стилей CSS, как показано в разделе 16.3.1). Положения модуля «CSS Transitions» реализованы во всех текущих браузерах, кроме IE, но в именах свойств стиля присутствуют префиксы производителей. Проект родственного стандарта «CSS Animations», использующий модуль «CSS Transitions» в качестве основы, определяет более сложные анимационные последовательности. В настоящее время «CSS Animations» реализован только в веб-браузерах, основанных на механизме Webkit. Ни один из этих стандартов не описывается в данной главе, но вам, как веб-разработчикам, нужно знать о существовании этих технологий.

Другим проектом, касающимся CSS, и о котором должны знать веб-разработчики, является стандарт «CSS Transforms», позволяющий определять двухмерные преобразования (вращение, масштабирование, перемещение, а также их комбинации, определяемые в матричном виде), применяемые к любым элементам. Все текущие браузеры (включая версии IE9 и выше) поддерживают этот проект с добавлением приставок, соответствующих производителям. Более того, в Safari реализована поддержка расширения, позволяющего выполнять трехмерные преобразования, но пока неясно, последуют ли этому другие браузеры.

содержание 16.2. Наиболее важные CSS-свойства содержание

Для разработчиков клиентских сценариев на языке JavaScript наиболее важными являются CSS-свойства, которые позволяют задавать режим видимости, размер и точную позицию отдельных элементов документа. Другие CSS-свойства дают возможность определять порядок наложения слоев, степень прозрачности, вырезанные области, поля, отступы, рамки и цвета. При работе с CSS-свойства- ми важно понимать, как работают свойства стиля. Они перечислены в табл. 16.1 и более подробно описываются в последующих разделах.

Таблица 16.1. Наиболее важные CSS-свойства

Свойство Описание
position Определяет тип позиционирования, применяемый к элементу
top. left Позиция верхнего и левого краев элемента
bottom, right Позиция нижнего и правого краев элемента
width, height Размер элемента
z-index «Порядок в стеке» относительно любых перерывающих его элементов (третье измерение в позиционировании элемента)
display Режим отображения элемента
visibility Режим видимости элемента
clip «Область отсечения» элемента (отображаются только те части документа, которые находятся внутри этой области)
overflow Определяет, что следует делать, если размер элемента больше, чем предоставленное ему место
margin, border, paddingГраницы и рамки элемента
background Цвет фона или фоновый рисунок для элемента
opacity Степень непрозрачности (или прозрачности) элемента. Это свойство относится к стандарту CSS3 и поддерживается не всеми браузерами. Работающая альтернатива имеется для IE

содержание 16.2.1. Позиционирование элементов с помощью CSS

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

static
Это значение, применяемое по умолчанию. Оно указывает, что элемент позиционируется статически в соответствии с нормальным порядком вывода содержимого документа (для большинства западных языков – слева направо и сверху вниз). Статически позиционированные элементы не могут позиционироваться с помощью свойств top, left и других. Для позиционирования элемента документа с применением приемов CSS сначала нужно установить его свойство position равным одному из трех других значений.
absolute
Это значение позволяет задать абсолютную позицию элемента относительно содержащего его элемента. Такие элементы позиционируются независимо от всех остальных элементов и не являются частью потока статически позиционированных элементов. Абсолютно позиционированный элемент позиционируется либо относительно тела документа, либо, если он вложен в другой абсолютно позиционированный элемент, относительно этого элемента.
fixed
Это значение позволяет зафиксировать положение элемента относительно окна браузера. Элементы с фиксированным позиционированием не прокручиваются с остальной частью документа. Как и абсолютно позиционированные, фиксировано позиционированные элементы не зависят от всех остальных элементов и не являются частью потока вывода документа. Фиксированное позиционирование поддерживается большинством современных браузеров, ис; ключая IE6.
relative
Если свойство position имеет значение relative, элемент располагается в соответствии с нормальным потоком вывода, а затем его положение смещается относительно его обычного положения в потоке. Пространство, выделенное для элемента в нормальном потоке вывода документа, остается выделенным для него, и элементы, расположенные со всех сторон от него, не смыкаются для заполнения этого пространства и не «выталкиваются» с новой позиции элемента.

Присвоив свойству position элемента значение, отличное от static, можно задать положение элемента с помощью произвольной комбинации свойств left, top, right и bottom. Чаще всего для позиционирования используются свойства left и top, задающие расстояние от левого края элемента-контейнера (обычно самого документа) до левого края позиционируемого элемента и расстояние от верхнего края контейнера до верхнего края элемента. Так, чтобы поместить элемент на расстоянии 100 пикселов от левого края и 100 пикселов от верхнего края документа, можно задать CSS-стили в атрибуте style, как показано ниже:

<div style="position: absolute; left: 100px; top: 100px;">

Если для элемента задана абсолютная позиция, значения его свойств top и left интерпретируются как расстояния до ближайшего родительского элемента, свойство position которого имеет любое значение, кроме static. Если абсолютно позиционируемый элемент не имеет позиционируемого предка, его свойства top и left будут определять координаты относительно начала документа – левого верхнего его угла. Если вам потребуется позиционировать элемент относительно контейнера, который является частью обычного потока вывода документа, определите в контейнере свойство position:relative и укажите значение 0px в свойствах top и left контейнера. В этом случае контейнер будет позиционироваться динамически и останется при этом на обычном месте в потоке вывода документа. Любые абсолютно позиционируемые вложенные элементы будут позиционироваться относительно контейнера.

При позиционировании элементов чаще всего задается положение верхнего левого угла элемента с помощью атрибутов left и top, но точно так же можно задать положение нижнего и правого краев элемента относительно нижнего и правого краев элемента-контейнера с помощью атрибутов right и bottom. Например, при помощи следующих стилей можно указать, что правый нижний угол элемента должен находиться в правом нижнем углу документа (предполагается, что он не вложен в другой динамический элемент):

position: absolute; right: 0px; bottom: 0px;

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

position: fixed; right: 10px; top: 10px;

Помимо позиций элементов CSS позволяет указывать их размеры. Чаще всего это делается путем задания значений свойств стиля width и height. Например, следующая разметка HTML создаст абсолютно позиционированный элемент без содержимого. Его свойствам width, height и background-color присвоены такие значения, что он будет отображаться в виде маленького синего квадрата:

<div style="position: absolute; top: 10px; left: 10px;
            width: 10px; height: 10px; background-color: blue">
</div>

Другой способ задать ширину элемента состоит в одновременном задании значений обоих свойств, left и right. Аналогично можно задать высоту элемента, одновременно указав оба свойства, top и bottom. Однако если задать значения для свойств left, right и width, то свойство width переопределит свойство right, а если ограничивается высота элемента, то более высоким приоритетом будет пользоваться свойство height.

Имейте в виду, что задавать размер каждого динамического элемента не обязательно. Некоторые элементы, такие как изображения, имеют собственный размер. Кроме того, для динамических элементов, включающих текст или другое потоковое содержимое, часто бывает достаточно указать желаемую ширину элемента и разрешить автоматическое определение высоты в зависимости от размещения содержимого элемента.

Стандарт CSS требует, чтобы в значениях свойств, определяющих позицию и размер, указывались единицы измерения. В предыдущих примерах значения свойств позиционирования и размера задавались с суффиксом «px», означающим «pixels» (пикселы). Можно также использовать другие единицы измерения: дюймы («in»), сантиметры («cm»), пункты («pt») и «em» (размер высоты строки текущего шрифта).

Помимо единиц измерения, представленных выше, CSS позволяет задавать положение и размер элемента в процентах от размера элемента-контейнера. Например, следующая разметка HTML создаст пустой элемент с черной рамкой, имеющий ширину и высоту в половину элемента-контейнера (или окна браузера) и расположенный в этом элементе по центру:

<div style="position: absolute; left: 25%; top: 25%; width: 50%; height: 50%;
            border: 2px solid black">
</div>

содержание 16.2.1.1. Третье измерение: z-index

Мы видели, что свойства left, top, right и bottom позволяют указывать координаты X и Y элемента в двухмерной плоскости элемента-контейнера. Свойство z-index определяет что-то вроде третьего измерения: оно позволяет определить порядок наложения элементов и указать, какой из двух или более перекрывающихся элементов должен располагаться поверх других. Атрибут z-index представляет собой целое число. По умолчанию его значение равно нулю, но можно задавать положительные и отрицательные значения. Когда два или более элементов перекрываются, они отображаются в порядке от меньших значений z-index к большим, т. е. элемент с большим значением z-index отображается поверх всех остальных. Если перекрывающиеся элементы имеют одинаковые значения z-index, они отображаются в порядке следования в документе, поэтому наверху оказывается последний из перекрывающихся элементов.

Обратите внимание, что порядок наложения определяется свойством z-index только для смежных элементов (т. е. для дочерних элементов одного контейнера). Если перекрываются два несмежных элемента, то на основе индивидуальных значений свойств z-index нельзя указать, какой из них должен находиться сверху. Вместо этого надо задать атрибут z-index для двух смежных контейнеров перекрывающихся элементов.

Способ размещения непозиционируемых элементов (элементов со значением по умолчанию режима позиционирования position:static) исключает возможность перекрытия, поэтому к ним свойство z-index не применяется. Тем не менее они получают значение z-index, по умолчанию равное нулю, т. е. позиционируемые элементы с положительным значением z-index отображаются поверх обычного потока вывода документа, а позиционируемые элементы с отрицательным значением z-index оказываются ниже обычного потока вывода документа.

содержание 16.2.1.2. Пример позиционирования средствами CSS:

Спецификация CSS3 включает свойство text-shadow, позволяющее добиться эффекта отбрасывания тени текстовыми элементами. Данное свойство поддерживается многими текущими браузерами, однако добиться эффекта тени можно и с помощью CSS-свойств позиционирования, для чего достаточно продублировать, сместив, выводимый текст:

<!-- Свойство text-shadow производит тень автоматически -->
<span style="text-shadow: 3px 3px 1px #888">Shadowed</span>
<!-- Ниже показано, как добиться похожего эффекта с помощью механизма позиционирования. -->
<span style="position:relative;">
  С тенью <!-- Это основной текст, отбрасывающий тень. -->
  <span style="position:absolute; top:3px; left:3px; z-index:-1; color: #888">
    С тенью <!-- Это тень -->
  </span>
</span>

Текст, отбрасывающий тень, заключается в относительно позиционируемый элемент <span>. Для него не определяются свойства, задающие позицию, поэтому текст отображается в обычной позиции в потоке. Тень заключается в абсолютно позиционируемый элемент <span>, помещенный в относительно позиционируемый элемент <span> (и поэтому позиционируется относительно него). Свойство z-index обеспечивает отображение тени под текстом.

содержание 16.2.2. Рамки, поля и отступы

Стандарт CSS позволяет задавать поля, рамки и отступы для любого элемента. Рамка элемента – это прямоугольник, обрисованный вокруг (полностью или частично) этого элемента. CSS-свойства позволяют задать стиль, цвет и толщину рамки:

border: solid black 1px; /* рамка рисуется черной сплошной линей, толщиной 1 пиксел */
border: 3px dotted red;  /* рамка рисуется красной пунктирной линией толщиной 3 пиксела */

Толщину, стиль и цвет рамки можно задать с помощью отдельных CSS-свойств, а также отдельно для каждой из сторон элемента. Например, чтобы нарисовать линию под элементом, достаточно просто определить свойство border-bottom. Можно даже задать толщину, стиль и цвет рамки только для одной стороны элемента с помощью таких свойств, как border-top-width и border-left-color.

В CSS3 можно закруглить все углы рамки, определив свойство border-radius, или отдельные углы, задействовав более конкретные свойства. Например:

border-top-right-radius: 50px;

Свойства margin и padding задают ширину пустого пространства вокруг элемента. Отличие (очень важное) заключается в том, что свойство margin задает ширину пустого пространства снаружи от рамки, между рамкой и окружающими элементами, а свойство padding – внутри рамки, между рамкой и содержимым элемента. Поля (margin) позволяют визуально отделить элемент (возможно, окруженный рамкой) от соседних элементов в нормальном потоке вывода документа. Отступы (padding) позволяют визуально отделить содержимое элемента от его рамки. Если элемент не имеет рамки, определять ширину отступов обычно не требуется. Если элемент позиционируется динамически, он выпадает из нормального потока вывода документа, и для него не имеет смысла определять ширину полей.

Поля и отступы элемента задаются с помощью свойств margin и padding:

margin: 5px; padding: 5px;

Можно также определить поля и отступы для каждой из сторон элемента в отдельности:

margin-left: 25px;
padding-bottom: 5px;

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

padding: 1px 2px 3px 4px;
/* Предыдущая строка эквивалентна четырем следующим. */
padding-top: 1px;
padding-right: 2px;
padding-bottom: 3px;
padding-left: 4px;

Порядок работы с атрибутом margin ничем не отличается.

содержание 16.2.3. Блочная модель и детали позиционирования в CSS

Свойства стиля margin, border и padding, описанные выше, не относятся к числу свойств, которыми приходится часто управлять в сценариях. Причина, по которой они были описаны здесь, состоит в том, что поля, рамки и отступы являются частью блочной модели CSS, знать которую необходимо, чтобы до конца разобраться, как действуют CSS-свойства позиционирования.

Рис. 16.2 иллюстрирует блочную модель CSS и наглядно показывает, какой смысл имеют свойства top, left, width и height для элементов с рамками и отступами.

cheme

Рис. 16.2. Блочная модель в CSS: рамки, отступы и свойства позиционирования

На рис. 16.2 показан абсолютно позиционируемый элемент, вложенный в позиционируемый элемент-контейнер. Оба элемента, контейнер и вложенный в него, имеют рамки и отступы, и на рисунке показаны CSS-свойства, определяющие ширину отступов и толщину рамок для каждой стороны элемента-контейнера. Обратите внимание, что здесь не показаны свойства margin: поля не используются при отображении абсолютно позиционируемых элементов.

Рис. 16.2 содержит также другую важную информацию. Во-первых, свойства width и height задают только размеры области содержимого элемента – они не включают дополнительное пространство, занимаемое отступами или рамками (и полями) элементов. Чтобы определить полный размер, занимаемый на экране элементом с рамкой, необходимо прибавить к ширине элемента ширину левого и правого отступов и толщину левой и правой рамок, а к высоте элемента необходимо прибавить ширину верхнего и нижнего отступов и толщину верхней и нижней рамок.

Во-вторых, свойства left и top задают расстояние от внутреннего края рамки контейнера до внешнего края рамки позиционируемого элемента. Эти свойства определяют расстояние не от левого верхнего угла области содержимого контейнера, а от левого верхнего угла области, занимаемой отступами контейнера. Аналогично свойства right и bottom определяют расстояние от правого нижнего угла области, занимаемой отступами.

Для полной ясности рассмотрим несложный пример. Предположим, что у вас есть динамически позиционируемый элемент, вокруг содержимого которого имеются отступы размером 10 пикселов, а вокруг них – рамка толщиной 5 пикселов. Теперь предположим, что вы динамически позиционируете дочерний элемент внутри этого контейнера. Если установить свойство left дочернего элемента равным «0px», обнаружится, что левый край дочернего элемента будет находиться непосредственно у внутреннего края рамки контейнера. При этом значении свойства left дочерний элемент перекроет отступы контейнера, хотя предполагается, что они остаются пустыми (т. к. для этого и предназначены отступы). Чтобы поместить дочерний элемент в левый верхний угол области содержимого контейнера, необходимо присвоить свойствам left и top значение «10px».

содержание 16.2.3.1. Модель border-box и свойство box-sizing

Стандартная блочная модель CSS определяет, что свойства стиля width и height задают размер области содержимого элемента и не учитывают ширину отступов и толщину рамки. Эту модель можно было бы назвать «content-box». Эта модель имеет исключения, наблюдаемые в старых версиях IE и в новых версиях CSS. При отображении страниц в IE версии ниже 6 или в IE6, 7 или 8 в «режиме совместимости» (когда страница не имеет объявления <!DOCTYPE> или это объявление недостаточно строгое), свойства width и height включают ширину отступов и толщину рамок.

Поведение IE ошибочно, но нестандартная блочная модель, реализованная в IE, иногда бывает весьма удобна. Учитывая это, в стандарт CSS3 было добавлено свойство box-sizing. По умолчанию оно имеет значение content-box, которое указывает, что используется стандартная блочная модель, описанная выше. Если вместо него указать значение box-sizing: border-box, браузер будет использовать блочную модель IE и свойства width и height будут включать рамки и отступы. Модель border-box особенно удобно использовать, когда желательно задать общий размер элемента в процентах, а ширину отступов и толщину рамки – в пикселах:

<div style="box-sizing:border-box; width: 50%;
            padding: 10px; border: solid black 2px;">

Свойство box-sizing поддерживается всеми текущими браузерами, но пока не во всех оно реализовано без префикса. В Chrome и Safari свойство имеет имя -webkit-box-sizing. В Firefox используется -moz-box-sizing. В Opera и IE8 (и выше) свойство имеет имя box-sizing без префикса.

Будущей альтернативой модели border-box, предусматриваемой стандартом CSS3, являются вычисляемые значения свойств:

<div style="width: calc(50%-12px); padding: 10px; border: solid black 2px;"&пt;

Возможность вычисления значений CSS-свойств с применением calc() поддерживается в IE9 и в Firefox 4 (как -moz-calc()).

содержание 16.2.4. Отображение и видимость элементов

Управлять видимостью элемента документа позволяют два CSS-свойства: visibility и display. Пользоваться свойством visibility очень просто: если оно имеет значение hidden, то элемент не отображается, если visible, – отображается. Свойство display является более универсальным и служит для задания варианта отображения элемента, определяя, блочный это элемент, встраиваемый, списочный или какой-нибудь другой. Если же свойство display имеет значение none, то элемент вообще не отображается и для него даже не выделяется место на странице.

Различие между свойствами стиля visibility и display имеет отношение к их воздействию на статически или относительно позиционируемые элементы. Для элемента, расположенного в нормальном потоке вывода документа, установка свойства visibility в значение hidden делает элемент невидимым, но резервирует для него место в документе. Такой элемент может повторно скрываться и отображаться без изменения компоновки документа. Однако если свойство display элемента установлено в значение none, то место в документе для него не выделяется; элементы с обеих сторон от него смыкаются, как будто его вообще не существует. Свойство display может пригодиться, например, при создании разворачивающихся и сворачивающихся списков.

Обратите внимание, что нет особого смысла использовать атрибуты visibility и display, чтобы сделать элемент невидимым, если вы не собираетесь динамически устанавливать их в сценарии на языке JavaScript, чтобы в какой-то момент сделать его снова видимым! Как это делается, будет показано далее в этой главе.

содержание 16.2.5. Цвет, прозрачность и полупрозрачность

Цвет текста, содержащегося в элементе документа, можно задать с помощью CSS-свойства color. Цвет фона любого элемента – с помощью свойства background-color. Выше мы видели, что цвет рамки элемента можно задать с помощью свойства border-color или сокращенной формы его написания border.

При обсуждении рамок мы рассматривали пример, в котором цвет рамки задавался указанием названий наиболее распространенных цветов, таких как «red» (красный) и «black» (черный). Стандарт CSS поддерживает множество таких обозначений цветов на английском языке, но имеется более универсальный способ определения цветов, который заключается в использовании шестнадцатеричных цифр, определяющих красную, зеленую и синюю составляющие цвета. Значения каждой из составляющих могут задаваться одной или двумя цифрами. Например:

#000000 /* black, черный */
#fff /* white, белый */
#f00 /* bright red, ярко-красный */
#404080 /* dark unsaturated blue, ненасыщенный темно-синий */
#ccc /* light gray, светло-серый */

Стандарт CSS3 дополнительно определяет возможность определения цвета в формате RGBA (значения красной, зеленой и синей составляющих плюс альфа-значение, определяющее степень прозрачности). Формат RGBA поддерживается всеми современными браузерами, кроме IE; ожидается, однако, что его поддержка будет включена в IE9. CSS3 также определяет поддержку форматов HSL (hue-saturation-value – тон-насыщенность-яркость) и HSLA. И снова эти форматы поддерживаются браузерами Firefox, Safari и Chrome, но не поддерживаются IE.

Таблицы CSS позволяют точно указать позицию, размеры, цвета фона и рамки элемента, что обеспечивает элементарные графические средства рисования прямоугольников и (если до предела уменьшить высоту или ширину) горизонтальных или вертикальных линий. В предыдущее издание книги был включен пример рисования столбчатых диаграмм средствами CSS, но в этом издании он был заменен расширенным описанием элемента <canvas> (подробнее о работе с графикой на стороне клиента рассказывается в главе 21).

В дополнение к атрибуту background-color можно также указать изображение, которое должно использоваться в качестве фоновой картинки элемента. Свойство background-image определяет фоновое изображение, а свойства background-attachment, background-position и background-repeat уточняют некоторые параметры рисования изображения. Сокращенная форма записи – свойство background, позволяющее указывать все эти атрибуты вместе. Свойства, определяющие фоновый рисунок, могут применяться для создания довольно интересных визуальных эффектов, но это уже выходит за рамки темы данной книги.

Очень важно понимать, что если цвет фона или фоновый рисунок элемента не задан, то фон элемента обычно прозрачный. Например, если поверх некоторого текста в обычном потоке вывода документа расположить элемент <div> с абсолютным позиционированием, то по умолчанию текст будет виден через элемент <div>. Если же элемент <div> содержит собственный текст, символы окажутся наложенными друг на друга, образуя трудную для чтения мешанину. Однако не все элементы по умолчанию прозрачны. Например, элементы форм выглядели бы нелепо с прозрачным фоном, и такие элементы, как <button>, имеют цвет фона по умолчанию. Переопределить значение цвета по умолчанию можно с помощью свойства background-color; при необходимости можно явно установить цвет фона прозрачным («transparent»).

Прозрачность, о которой мы до сих пор говорили, может быть либо полной, либо нулевой: элемент имеет либо прозрачный, либо непрозрачный фон. Однако существует возможность получить полупрозрачный элемент (для содержимого как заднего, так и переднего плана). (Пример полупрозрачного элемента приведен на рис. 16.3.) Делается это с помощью свойства opacity, определяемого стандартом CSS3. Значением этого свойства является число в диапазоне от 0 до 1, где 1 означает 100-процентную непрозрачность (значение по умолчанию), а 0 – 100-процентную прозрачность. Свойство opacity поддерживается всеми текущими браузерами, кроме IE. В IE аналогичная функциональность реализуется с помощью специфичного свойства filter. Чтобы сделать элемент непрозрачным на 75%, можно воспользоваться следующими CSS-стилями:

opacity: .75;              /* стандартный стиль прозрачности в CSS3 */
filter: alpha(opacity=75); /* прозрачность в IE; обратите внимание на отсутствие десятичной точки */

содержание 16.2.6. Частичная видимость: свойства overflow и clip

Свойство visibility позволяет полностью скрыть элемент документа. С помощью свойств overflow и clip можно отобразить только часть элемента. Свойство overflow определяет, что происходит, когда содержимое документа превышает размер, указанный для элемента (например, в свойствах стиля width и height). Далее перечислены допустимые значения этого свойства и указано их назначение:

visible
Содержимое может выходить за пределы и по необходимости прорисовываться вне прямоугольника элемента. Это значение по умолчанию.
hidden
Содержимое, вышедшее за пределы элемента, обрезается и скрывается, так что никакая часть содержимого никогда не прорисовывается вне области, определяемой свойствами размера и позиционирования.
scroll
Область элемента имеет постоянные горизонтальную и вертикальную полосы прокрутки. Если содержимое превышает размеры области, полосы прокрутки позволяют увидеть остальное содержимое. Это значение учитывается, только когда документ отображается на экране компьютера; когда документ выводится, например, на бумагу, полосы прокрутки, очевидно, не имеют смысла.
auto
Полосы прокрутки отображаются не постоянно, а только когда содержимое превышает размер элемента.

Если свойство overflow определяет, что должно происходить, когда содержимое элемента превысит область элемента, то с помощью свойства clip можно точно указать, какая часть элемента должна отображаться независимо от того, выходит ли содержимое за пределы элемента. Это свойство особенно полезно для создания эффектов, когда элемент открывается или проявляется постепенно.

Значение свойства clip задает область отсечения элемента. В CSS2 области отсечения прямоугольные, но синтаксис атрибута clip обеспечивает возможность в следующих версиях стандарта задавать области отсечения, отличные от прямоугольных. Синтаксис свойства clip:

rect(top right bottom left)

Значения top, right, bottom и left задают границы прямоугольника отсечения относительно левого верхнего угла области элемента. Чтобы, например, вывести только часть элемента в области 100 х 100 пикселов, можно задать для этого элемента следующий атрибут style:

style="clip: rect(0px 100px 100px 0px);"

Обратите внимание, что между значениями нет запятых, и края области отсечения задаются по часовой стрелке, начиная с верхнего края.

содержание 16.2.7. Пример: перекрытие полупрозрачных окон

Данный раздел завершается примером, который демонстрирует порядок работы с большинством обсуждавшихся CSS-свойств. В примере 16.2 CSS-стили используются для создания визуального эффекта наложения полупрозрачного окна на другое окно, обладающее полосой прокрутки. Результат приводится на рис. 16.3.

cheme

Рис. 16.3. Окна, созданные с помощью CSS

Пример не содержит JavaScript-код и в нем нет никаких обработчиков событий, поэтому возможность взаимодействия с окнами отсутствует (иначе как через полосу прокрутки), но это очень интересная демонстрация эффектов, которые можно получить средствами CSS.

Пример 16.2. Отображение окон с использованием CSS-стилей

Example 16-2. Displaying windows with CSS
<!DOCTYPE html>
<head>
<style type="text/css">
/**
 * Эта таблица CSS-стилей определяет три правила стилей, которые используются
 * в теле документа для создания визуального эффекта "окна". В правилах использованы
 * свойства позиционирования для установки общего размера окна и расположения
 * его компонентов. Изменение размеров окна требует аккуратного
 * изменения атрибутов позиционирования во всех трех правилах.
**/
div.window { /* Определяет размер и рамку окна */
    position: absolute; /* Положение задается в другом месте */
    width: 300px; height: 200px;/* Размер окна без учета рамок */
    border: 3px outset gray; /* Обратите внимание на ЗР-эффект рамки */
}
div.titlebar { /* Задает положение, размер и стиль заголовка */
    position: absolute; /* Это позиционируемый элемент */
    top: 0px; height: 18px; /* Высота заголовка 18рх + отступ и рамка */
    width: 290px; /* 290 + 5рх отступы слева и справа = 300 */
    background-color: #aaa; /* Цвет заголовка */
    border-bottom: groove gray 2px; /* Заголовок имеет рамку только снизу */
    padding: 3px 5px 2px 5px; /* Значения по часовой стрелке: сверху, справа, снизу, слева */
    font: bold 11pt sans-serif; /* Шрифт заголовка */
}
div.content { /* Задает размер, положение и прокрутку содержимого окна */
    position: absolute; /* Это позиционируемый элемент*/
    top: 25px; /* 18рх заголовок+2рх рамка+3рх+2рх отступ */
    height: 165px; /* 200px всего - 25px заголовок - 10px отступ */
    width: 290px; /* 300px ширина - 10px отступ */
    padding: 5px; /* Отступы со всех четырех сторон */
    overflow: auto; /* Разрешить появление полос прокрутки */
    background-color: #fff; /* По умолчанию белый фон */
}
div.translucent { /* Этот класс делает окно частично прозрачным */
    opacity: .75; /* Стандартный стиль прозрачности */
    filter: alpha(opacity=75); /* Прозрачность для IE */
}
</style>
</head>
<body>
<!-- Порядок определения окна: элемент div "окна" с заголовком и элемент div -->
<!-- с содержимым, вложенный между ними. Обратите внимание, как задается -->
<!-- позиционирование с помощью атрибута style, дополняющего -->
<!-- стили из таблицы стилей -->
<div class="window" style="left: 10px; top: 10px; z-index: 10;">
<div class="titlebar">Test Window</div>
<div class="content">
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>0<br><!-- Множество строк для -->
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>0<br><!-- демонстрации прокрутки -->
</div>
</div>
<!-- Это еще одно окно с другими позицией, цветом и шрифтом -->
<div class="window" style="left: 75px; top: 110px; z-index: 20;">
<div class="titlebar">Another Window</div>
<div class="content translucent"
     style="background-color:#ccc; font-weight:bold;">
Это еще одно окно. Значение атрибута <tt>z-index</tt> этого окна заставляет
его расположиться поверх другого. За счет CSS-стилей содержимое этого окна
будет выглядеть полупрозрачным в браузерах, поддерживающих такую возможность.
</div>
</div>

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

содержание 16.3. Управление встроенными стилями содержание

Самый простой способ управления стилями CSS – это манипулирование атрибутом style отдельных элементов документа. Как и для большинства HTML-атрибутов, атрибуту style соответствует одноименное свойство объекта Element, и им можно манипулировать в сценариях на языке JavaScript. Однако свойство style имеет одну отличительную особенность: его значением является не строка, а объект CSSStyleDeclaration. Свойства этого объекта представляют CSS-свойства, определенные в HTML-атрибуте style. Например, чтобы вывести содержимое текстового элемента e крупным, полужирным шрифтом синего цвета, можно выполнить следующие операции для записи желаемых значений в свойства, которые соответствуют свойствам стиля font-size, font-weight и color:

e.style.fontSize = "24pt";
e.style.fontWeight = "bold";
e.style.color = "blue";

Соглашения об именах: CSS-свойства в JavaScript

Многие CSS-свойства стиля, такие как font-size, содержат в своих именах дефис. В языке JavaScript дефис интерпретируется как знак минус, поэтому нельзя записать выражение, приведенное ниже:

e.style.font-size = "24pt"; // Syntax error!

Таким образом, имена свойств объекта CSSStyleDeclaration слегка отличаются от имен реальных CSS-свойств. Если имя CSS-свойства содержит дефисы, имя свойства объекта CSSStyleDeclaration образуется путем удаления дефисов и перевода в верхний регистр буквы, непосредственно следующей за каждым из них. Другими словами, CSS-свойство border-left-width доступно через свойство borderLeftWidth, а к CSS-свойству font-family можно обратиться следующим образом:

e.style.fontFamily = "sans-serif";

Кроме того, когда CSS-свойство, такое как float, имеет имя, совпадающее с зарезервированным словом языка JavaScript, к этому имени добавляется префикс «ess», чтобы создать допустимое имя свойства объекта CSSStyleDeclaration. То есть, чтобы прочитать или изменить значение CSS-свойства float элемента, следует использовать свойство cssFloat объекта CSSStyleDeclaration.

При работе со свойствами стиля объекта CSSStyleDeclaration не забывайте, что все значения должны задаваться в виде строк. В таблице стилей или атрибуте style можно написать:

position: absolute; font-family: sans-serif; background-color: tfffffff;

Чтобы сделать то же самое для элемента e в JavaScript, необходимо заключить все значения в кавычки:

e.style.position = "absolute"; e.style.fontFamily = "sans-serif"; e.style.backgroundColor = "tfffffff";

Обратите внимание, что точки с запятыми не входят в строковые значения. Это точки с запятой, употребляемые в синтаксисе языка JavaScript. Точки с запятой, используемые в таблицах стилей CSS, не нужны в строковых значениях, устанавливаемых с помощью JavaScript.

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

e.style.left = 300; // Неправильно: это число, а не строка
e.style.left = "300"; // Неправильно: отсутствуют единицы измерения

Единицы измерения обязательны при установке свойств стиля в JavaScript – так же, как при установке свойств стиля в таблицах стилей. Ниже приводится правильный способ установки значения свойства left элемента e, равным 300 пикселам:

e.style.left = "ЗООрх";

Чтобы установить свойство left равным вычисляемому значению, обязательно добавьте единицы измерения в конце вычислений:

e.style.left = (х0 + left_margin + left_border + left_padding) + "px";

Как побочный эффект, добавление строки с единицами измерения преобразует вычисленное значение из числа в строку.

Напомню, что некоторые CSS-свойства, такие как margin, представляют собой сокращенную форму записи других свойств, таких как margin-top, margin-right, margin-bottom и margin-left. Объект CSSStyleDeclaration имеет свойства, соответствующие этим сокращенным формам записи свойств. Например, свойство margin можно установить следующим образом:

e.style.margin = topMargin + "рх " + rightMargin + "рх " +
bottomMargin + "рх " + leftMargin + "рх";

Хотя, возможно, кому-то будет проще установить четыре свойства полей по отдельности:

e.style.marginTop = topMargin + "рх";
e.style.marginRight = rightMargin + "рх";
e.style.marginBottom = bottomMargin + "рх";
e.style.marginLeft = leftMargin + "рх";

Атрибут style HTML-элемента – это его встроенный стиль, и он переопределяет любые правила стилей в таблице CSS. Встроенные стили в целом удобно использовать для установки значений стиля, и именно такой подход использовался во всех приведенных выше примерах. Сценарии могут читать свойства объекта CSSStyleDeclaration, представляющего встроенные стили, но они возвращают осмысленные значения, только если были ранее установлены сценарием на языке JavaScript или если HTML-элемент имеет встроенный атрибут style, установивший нужные свойства. Например, документ может включать таблицу стилей, устанавливающую левое поле для всех абзацев равным 30 пикселам, но если прочитать свойство leftMargin одного из этих элементов, будет получена пустая строка, если только этот абзац не имеет атрибут style, переопределяющий значение, установленное таблицей стилей.

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

Иногда бывает проще прочитать или записать единственную строку во встроенный стиль элемента, чем обращаться к объекту CSSStyleDeclaration. Для этого можно использовать методы getAttribute() и setAttribute() объекта Element или свойство cssText объекта CSSStyleDeclaration:

// Обе инструкции, следующие ниже, записывают в атрибут style
// элемента e строку s:
e.setAttribute("style", s);
e.style.cssText = s;
// Обе инструкции, следующие ниже, получают значение атрибута style
// элемента e в виде строки:
s = e.getAttribute("style");
s = e.style.cssText;

содержание 16.3.1. Создание анимационных эффектов средствами CSS

Одной из наиболее типичных областей применения CSS является воспроизведение визуальных анимационных эффектов. Реализовать их можно с помощью метода setTimeout() или setInterval() (раздел 14.1), используя их для организации многократных вызовов функции, изменяющей встроенный стиль элемента. Пример 16.3 демонстрирует две такие функции, shake() и fadeOut(). Функция shake() перемещает, или «встряхивает» (shakes), элемент из стороны в сторону. Бе можно использовать, например, для привлечения внимания пользователя в случае ввода некорректных данных. Функция fadeOut() уменьшает непрозрачность элемента в течение указанного периода времени (по умолчанию 500 миллисекунд), вызывая эффект его растворения до полного исчезновения.

Пример 16.3. Воспроизведение анимационных эффектов средствами CSS

// Делает элемент e относительно позиционируемым и перемещает его влево и вправо.
// Первым аргументом может быть объект элемента или значение атрибута id требуемого
// элемента. Если во втором аргументе передать функцию, она будет вызвана с элементом e
// в виде аргумента по завершении воспроизведения анимации. Третий аргумент определяет
// величину смещения элемента e. По умолчанию принимает значение 5 пикселов.
// Четвертый аргумент определяет, как долго должен воспроизводиться эффект.
// По умолчанию эффект длится 500 мсек.
function shake(e, oncomplete, distance, time) {
  // Обработка аргументов
  if (typeof e === "string") e = document.getElementByld(e);
  if (!time) time = 500;
  if (!distance) distance = 5;

  var originalStyle = e.style.cssText;     // Сохранить оригинальный стиль e
  e.style.position = "relative";           // Сделать относит, позиционируемым
  var start = (new Date()).getTime();      // Запомнить момент начала анимации
  animate();                               // Запустить анимацию

  // Эта функция проверяет прошедшее время и изменяет координаты e.
  // Если анимацию пора завершать, восстанавливает первоначальное состояние
  // элемента e. Иначе изменяет координаты e и планирует следующий свой вызов.
  function animate() {
    var now = (new Date()).getTime();      // Получить текущее время
    var elapsed = now-start;               // Сколько прошло времени с начала?
    var fraction = elapsed/time;           // Доля от требуемого времени?

    if (fraction < 1) {                    // Если рано завершать анимацию
      // Вычислить координату x элемента e как функцию от доли общего
      // времени анимации. Здесь используется синусоидальная функция,
      // а доля общего времени воспроизведения умножается на 4pi,
      // поэтому перемещение взад и вперед выполняется дважды,
      var x = distance * Math.sin(fraction*4*Math.PI);
      e.style.left = x + "px";

      // Попробовать вызвать себя через 25 мсек или в конце запланированного
      // отрезка общего времени воспроизведения. Мы стремимся сделать
      // анимацию гладкой, воспроизводя ее со скоростью 40 кадров/сек.
      setTimeout(animate, Math.min(25, time-elapsed));
    }
    else { // Иначе анимацию пора завершать
      e.style.cssText = originalStyle // Восстановить первонач. стиль
      if (oncomplete) oncomplete(e); // Вызвать ф-цию обратного вызова
    }
  }
}

// Растворяет e от состояния полной непрозрачности до состояния полной прозрачности
// за указанное количество миллисекунд. Предполагается, что. когда вызывается
// эта функция, e полностью непрозрачен, oncomplete - необязательная функция.
// которая будет вызвана с элементом e в виде аргумента по завершении анимации.
// Если аргумент time не задан, устанавливается интервал 500 мсек.
// Эта функция не работает в IE, но ее можно модифицировать так, чтобы
// в дополнение к свойству opacity она использовала нестандартное
// свойство filter, реализованное в IE.
function fadeOut(e, oncomplete, time) {
if (typeof e === "string") e = document.getElementById(e);
if (!time) time = 500;

// В качестве простой "функции перехода", чтобы сделать анимацию немного
// нелинейной, используется Math.sqrt: сначала растворение идет быстро,
// а затем несколько замедляется,
  var ease = Math.sqrt;

  var start = (new Date()).getTime(); // Запомнить момент начала анимации
  animate(); // И запустить анимацию
  function animate() {
    var elapsed = (new Date()).getTime()-start; // Прошедшее время
    var fraction = elapsed/time; // Доля от общего времени
    if (fraction < 1) { // Если не пора завершать
      var opacity = 1 - ease(fraction); // Вычислить непрозрачн.
      e.style.opacity = String(opacity); // Установить ее в e
      setTimeout(animate, // Запланировать очередной
      Math.min(25, time-elapsed)); // кадр
    }
    else { // Иначе завершить
      e.style.opacity = "0"; // Сделать e полностью прозрачным
      if (oncomplete) oncomplete(e); // Вызвать ф-цию обратного вызова
    }
  }
}

Обе функции, shake() и fadeOut(), принимают необязательную функцию обратного вызова во втором аргументе. Если эта функция указана, она будет вызвана по завершении воспроизведения анимационного эффекта. Элемент, к которому применялся анимационный эффект, будет передан функции обратного вызова в виде аргумента. Следующая разметка HTML создает кнопку, для которой после щелчка на ней воспроизводится эффект встряхивания, а затем эффект растворения:

Обратите внимание, насколько функции shake() и fadeOut() похожи друг на друга. Они обе могут служить шаблонами для реализации похожих анимационных эффектов с использованием CSS-свойств. Однако клиентские библиотеки, такие как jQuery, обычно поддерживают набор предопределенных визуальных эффектов, поэтому вам вообще может никогда не потребоваться писать собственные функции воспроизведения анимационных эффектов, такие как shake(), если только вам не понадобится создать какой-нибудь сложный визуальный эффект. Одной из первых и наиболее примечательных библиотек визуальных эффектов является библиотека Scriptaculous, которая предназначалась для работы в составе фреймворка Prototype. За дополнительной информацией обращайтесь по адресу http://script.aculo.us/ и http://scripty2.com/. Модуль «CSS3 Transitions» определяет еще один способ реализации анимационных эффектов с помощью таблиц стилей, полностью устраняющий необходимость писать программный код. Например, вместо функции fadeOutQ можно было бы определить правило CSS, как показано ниже:

.fadeable { transition: opacity .5s ease-in }

Это правило говорит, что всякий раз, когда изменяется непрозрачность элемента с классом «fadeable», это изменение должно протекать плавно (от текущего до нового значения) в течение половины секунды с использованием нелинейной функции перехода. Модуль «CSS Transitions» еще не был стандартизован, но его положения уже реализованы в браузерах Safari и Chrome в виде свойства -webkit-transition. На момент написания этих строк в Firefox 4 также была добавлена поддержка свойства -moz-transition.

содержание 16.4. Вычисленные стили содержание

Свойство style элемента определяет встроенный стиль элемента. Оно имеет преимущество перед всеми таблицами стилей и с успехом может применяться для установки CSS-свойств для изменения визуального представления элемента. Однако в общем случае к нему нет смысла обращаться, когда требуется узнать фактически примененные к элементу стили. То, что требуется в этом случае, называется вычисленным стилем. Вычисленный стиль элемента – это набор значений свойств, которые браузер получил (или вычислил) из встроенного стиля и всех правил из всех таблиц стилей, которые применяются к элементу: это набор свойств, фактически используемый при отображении элемента. Подобно встроенным стилям, вычисленные стили представлены объектом CSSStyleDeclaration. Однако в отличие от встроенных стилей вычисленные стили доступны только для чтения. Эти стили нельзя изменить, но вычисленный объект CSSStyleDeclaration позволяет точно узнать значения свойств стилей, которые браузер использовал при отображении соответствующего элемента.

Получить вычисленный стиль элемента можно с помощью метода getComputedStyle() объекта Window. Первым аргументом этому методу передается элемент, вычисленный стиль которого требуется вернуть. Второй аргумент является обязательным, и в нем обычно передается значение null или пустая строка, но в нем также может передаваться строка с именем псевдоэлемента CSS, таким как «:before», «:after», «:first-line» или «:first-letter»:

var title = document.getElementById("section1title");
var titlestyles = window.getComputedStyle(element, null);

Возвращаемым значением метода getComputedStyle() является объект CSSStyleDeclaration, представляющий все стили, применяемые к указанному элементу (или псевдоэлементу). Между объектами CSSStyleDeclaration, представляющими встроенные стили и вычисленные стили, существует множество существенных отличий:

Вычисленные и встроенные стили можно использовать совместно. В примере 16.4 определяются функции scale() и scaleColor(). Первая читает и анализирует вычисленный размер текста указанного элемента; вторая читает и анализирует вычисленный цвет фона элемента. Затем обе функции умножают полученное значение на заданное число и устанавливают результат как встроенный стиль элемента. (Эти функции не работают в IE8 и в более ранних версиях: как вы узнаете далее, эти версии IE не поддерживают метод getComputedStyle().)

Пример 16.4. Определение вычисленных стилей и установка встроенных стилей

  //Умножает размер текста элемента e на указанное число factor
  function scale(e, factor) {
    // Определить текущий размер текста, получив вычисленный стиль
    var size = parseInt(window.getComputedStyle(e,""). fontSize);
    // И использовать встроенный стиль, чтобы увеличить этот размер
    e.style.fontSize = factor*size + "рх";
  }
  // Изменяет цвет фона элемента e, умножая компоненты цвета на указанное число.
  // Значение factor > 1 осветляет цвет элемента, a factor < 1 затемняет его.
  function scaleColor(e, factor) {
    var color = window.getComputedStyle(e, ""').backgroundColor; // Получить
    var components = color.match(/[\d\.]+/g); // Выбрать компоненты r.g.b и а
    for(var i = 0; i < 3; i++) { // Цикл по г, g и b
    var x = Number(components[i]) * factor;// Умножить каждый из них
    х = Math.round(Math.min(Math.max(x, 0). 255)); // Округлить и установить границы
    components[i] = String(x);
  }
  if (components.length == 3) // Цвет rgb()
    e.style.backgroundColor = "rgb(" + components.join() + ")";
  else // Цвет rgba()
    e.style.backgroundColor = "rgba(" + components.join() + ")";
}

Работа с вычисленными стилями может оказаться весьма непростым делом, и обращение к ним не всегда возвращает ожидаемую информацию. Рассмотрим в качестве примера свойство font-family: оно принимает список разделенных запятыми имен семейств шрифтов для совместимости. При чтении свойства fontFamily вычисленного стиля вы ждете значение наиболее конкретного стиля font-family, применяемого к элементу. А в этом случае может вернуться такое значение, как «arial,helvetica,sans-serif», которое ничего не говорит о гарнитуре фактически используемого шрифта. Аналогично, если элемент не является абсолютно позиционируемым, при попытке определить его размеры или положение через свойства top и left вычисленного стиля часто возвращается значение «auto». Это вполне допустимое в CSS значение, но наверняка совсем не то, что вы ожидали бы получить.

Метод getComputedStyle() не поддерживается в IE8 и в более ранних версиях, но, как ожидается, он будет реализован в IE9. В IE все HTML-элементы имеют свойство currentStyle, значением которого является объект CSSStyleDeclaration. Свойство currentStyle в IE объединяет встроенные стили с таблицами стилей, но оно не является по-настоящему вычисленным стилем, потому что не преобразует относительные значения в абсолютные. При чтении свойств текущего стиля в IE могут возвращаться размеры в относительных единицах измерения, таких как «%» или «em», а цвета в виде неточных названий, таких как «red».

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

содержание 16.5. CSS-классы содержание

Альтернативой использованию отдельных CSS-стилей через свойство style является управление значением HTML-атрибута class. Изменение класса элемента изменяет набор селекторов стилей, применяемых к элементу, что может приводить к изменениям значений сразу нескольких CSS-свойств. Предположим, например, что вам требуется привлечь внимание пользователя к отдельным абзацам (или другим элементам) в документе. В этом случае можно было бы сначала определить особый стиль оформления для любых элементов с классом «attention»:

.attention { /* Стили для элементов, требующих внимания пользователя */
background-color: yellow; /* Желтый фон */
font-weight: bold: /* Полужирный шрифт */
border: solid black 2px; /* Черная рамка */
}

Идентификатор class в языке JavaScript является зарезервированным словом, поэтому HTML-атрибут class в JavaScript-сценариях доступен в виде свойства с именем className. Ниже приводится пример, который устанавливает и очищает свойство className элемента, добавляя и убирая класс «attention»:

function grabAttention(e) { е.className = "attention"; }
function releaseAttention(e) { e.className = ""; }

HTML-элементы могут быть членами более чем одного CSS-класса – атрибут class может содержать целый список имен классов, разделенных пробелами. Имя className не совсем точно отражает смысл свойства: правильнее было бы дать ему имя classNames . Функции выше предполагают, что свойство className будет определять ноль или одно имя класса, и они непригодны в случаях, когда может использоваться более одного имени класса. Если элемент уже принадлежит некоторому классу, вызов функции grabAttention() для этого элемента затрет имя класса, присутствующее в свойстве className .

Стандарт HTML5 решает эту проблему, определяя свойство classList во всех элементах. Значением этого свойства является объект DOMTokenList: подобный массиву объект (раздел 7.11), доступный только для чтения, элементы которого содержат отдельные имена классов, присвоенных элементу. Однако самыми важными в нем являются не элементы массива, а методы add() и remove(), добавляющие и удаляющие отдельные имена классов из атрибута class элемента. Метод toggle() добавляет имя класса, если оно отсутствует, и удаляет в противном случае. Наконец, метод contains() проверяет присутствие указанного имени класса в атрибуте class.

Подобно другим классам коллекций в модели DOM, объект DOMTokenList является «живым» представлением множества классов в элементе, а не статическим слепком, который был действителен только в момент обращения к свойству classList. Если сценарий получит объект DOMTokenList, обратившись к свойству classList элемента, и затем изменит свойство className этого элемента, то выполненные изменения немедленно отразятся на полученном объекте DOMTokenList. Аналогично любые изменения, выполненные в объекте DOMTokenList, немедленно отразятся на значении свойства className.

На момент написания этих строк свойство classList не поддерживалось ни одним из текущих браузеров. Однако эту удобную функциональность легко можно реализовать самому, как показано в примере 16.5. Подобная реализация, позволяющая интерпретировать атрибут class элемента как множество имен классов, существенно упрощает выполнение многих задач, связанных с обработкой CSS.

Пример 16.5. classList(): интерпретирует className, как множество CSS-классов

/*
* Возвращает свойство classList элемента e. если оно содержит один класс.
* Иначе возвращает объект, имитирующий интерфейс DOMTokenList.
* Возвращаемый объект имеет методы contains(), add(), remove(), toggle() и toString(),
* позволяющие проверять и изменять набор классов элемента e. Если свойство classList
* имеет встроенную поддержку в браузере, функция возвращает объект, подобный массиву,
* который имеет свойство length и поддерживает возможность индексирования массива.
* Имитация объекта DOMTokenList не подобна массиву, но имеет метод toArray().
* который возвращает истинный массив имен классов элемента.
•/
function classList(e) {
  if (e.classList) return e.classList; // Вернуть e.classList, если имеется
  else return new CSSClassList(e);     // Иначе попытаться подделать его
}

// CSSClassList - класс JavaScript, имитирующий объект DOMTokenList
function CSSClassList(e) { this.e = e; }

// Возвращает true, если e.className содержит класс c, иначе - false
CSSClassList.prototype.contains = function(c) {
  // Проверить, является ли c допустимым именем класса
  if (c.length ===0 || cindexOff ") != -1)
    throw new Error("Недопустимое имя класса: '" + c + );
  // Сначала проверить общие случаи
  var classes = this.e.className;
  if (!classes) return false;          // e вообще не имеет классов
  if (classes === c) return true;      // e имеет единственный класс,
                                       // имя которого точно совпадает c искомым

  // Иначе использовать RegExp для поиска c как отдельного слова
  // \b - в регулярных выражениях соответствует границе слова,
  return classes.search("\\b" + c + "\\b") != -1;
};

// Добавляет имя класса c в e.className. если оно отсутствует в списке
CSSClassList.prototype.add = function(c) {
  if (this.contains(c)) return;         // Ничего не делать, если имя уже в списке
  var classes = this.e.className;
  if (classes && classes[classes.length-1] != " ")
  c = " "' + c;                         // Добавить пробел, если необходим
  this.e.className += c;                // Добавить имя c в className
};

// Удаляет все вхождения c из e.className
CSSClassList.prototype.remove = function(c) {
  // Убедиться, что c - допустимое имя класса
  if (c.length ===0 || c.indexOfC ") != -1)
  throw new Error("Недопустимое имя класса: '" + c + );
  // Удалить все вхождения имени c как слова и все завершающие пробелы
  var pattern = new RegExp("\\b" + c + "\\b\\s*", "g");
  this.e.className = this.e.className.replace(pattern, "");
};

// Добавляет имя c в e.className. если оно отсутствует в списке, и возвращает true.
// Иначе удаляет все вхождения имени c из e.className и возвращает false.
CSSClassList.prototype.toggle = function(c) {
  if (this.contains(c)) { // Если e.className содержит c
    this.remove(c);       // удалить его.
    return false;
  }
  else {                  // Иначе:
    this.add(c);          // добавить его.
    return true;
  }
};

// Возвращает само значение e.className
CSSClassList.prototype.toString = function() { return this.e.className; };
// Возвращает имена из e.className
CSSClassList.prototype.toArray = function() {
  return this.e.className.match(/\b\w+\b/g) 11 [];
}

содержание 16.6. Управление таблицами стилей содержание

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

При работе с самими таблицами стилей вам придется столкнуться с двумя типами объектов. Первый тип – это объекты Element, представляющие элементы <style> и <link>, которые содержат или ссылаются на таблицы стилей. Это обычные элементы документа, и если в них определить атрибут id, вы сможете выбирать их с помощью метода document.getElementById(). Второй тип объектов – объекты CSSStyleSheet, представляющие сами таблицы стилей. Свойство document.stylesheets возвращает доступный только для чтения объект, подобный массиву, содержащий объекты CSSStyleSheet, представляющие таблицы стилей документа. Если в элементе <style> или <link>, определяющем или ссылающемся на таблицу стилей, определить атрибут title, этот объект будет доступен как свойство объекта CSSStyleSheet с именем, указанным в атрибуте title.

Следующие разделы описывают, какие операции могут выполняться с этими элементами <style> и <link> и объектами таблиц стилей.

содержание 16.6.1. Включение и выключение таблиц стилей

Простейший прием работы с таблицами стилей является к тому же самым переносимым и надежным. Элементы <style> и <link> и объекты CSSStyleSheet определяют свойство disabled, доступное сценариям на языке JavaScript для чтения и записи. Как следует из его имени, если свойство disabled принимает значение true, таблица стилей оказывается отключенной и будет игнорироваться браузером. * Это наглядно демонстрирует функция document.styleSheets(), представленная ниже. Если передать ей число, она будет интерпретировать его как индекс в массиве document.styleSheets. Если передать ей строку, она будет интерпретировать ее как селектор CSS, передаст ее методу document.querySelectorAll() (раздел 15.2.5) и установит в значение true свойство disabled всех полученных элементов:

function disableStylesheet(ss) {
  if (typeof ss === "number")
    document.styleSheets[ss].disabled = true;
  else {
    var sheets = document.querySelectorAll(ss);
    for(var i = 0; i < sheets.length; i++)
    sheets[i].disabled = true;
  }
}

содержание 16.6.2. Получение, вставка и удаление правил из таблиц стиле

В дополнение к возможности включения и отключения таблиц стилей объект CSSStyleSheet также определяет API для получения, вставки и удаления правил стиля из таблиц стилей. IE8 и более ранние версии реализуют несколько иной API, отличный от стандартного, реализуемого другими браузерами. Как правило, непосредственное манипулирование таблицами стилей редко бывает полезным. Вместо того чтобы добавлять новые правила в таблицы стилей, обычно лучше оставить их статичными и работать со свойством className элемента. В то же время, если необходимо предоставить пользователю возможность полного управления таблицами стилей веб-страницы, может потребоваться организовать динамическое манипулирование таблицами. Объекты CSSStyleSheet хранятся в массиве document.styleSheets[]. Объект CSSStyleSheet имеет свойство cssRules[], хранящее массив правил стилей:

var firstRule = document.styleSheets[0].cssRules[0];

В IE это свойство носит имя rules, а не cssRules. Элементами массива cssRules[] или rules[] являются объекты CSSRule. В стандартном API объект CSSRule может представлять CSS-правила любого типа, включая @-правила, такие как директивы @import и @раде. Однако в IE массив rules[] может содержать только фактические правила таблицы стилей. Объект CSSRule имеет два свойства, которые могут использоваться переносимым способом. (В стандартном API правила, не относящиеся к правилам стилей, не имеют этих свойств, и потому, возможно, вам потребуется пропускать их при обходе таблицы стилей.) Свойство selectorText – это CSS-селектор для данного правила, а свойство style – это ссылка на доступный для записи объект CSSStyleDeclaration, который описывает стили, связанные с этим селектором. Напомню, что CSSStyleDeclaration – это тот же самый тип, который используется для представления встроенных и вычисленных стилей. Объект CSSStyleDeclaration может применяться для чтения существующих или создания новых стилей в правилах. Нередко при обходе таблицы стилей интерес представляет сам текст правила, а не, разобранное его представление. В этом случае можно использовать свойство cssText объекта CSSStyleDeclarationn, в котором содержатся правила в текстовом представлении. В дополнение к возможности получения и изменения существующих правил таблиц стилей имеется возможность добавлять правила в таблицу стилей и удалять их из таблицы. Стандартный прикладной интерфейс определяет методы insertRule() и deleteRule(), позволяющие добавлять и удалять правила:

document.styleSheets[0].insertRule("H1 { text-weight: bold; }", 0);

Браузер IE не поддерживает методы insertRule() и deleteRule(), но определяет практически эквивалентные им функции addRule() и removeRule(). Единственное существенное отличие (помимо имен функций) состоит в том, что addRule() ожидает получить селектор и стиль в текстовом виде в двух отдельных аргументах. Следующий пример реализует обход правил в таблице стилей и демонстрирует API, внося несколько сомнительных изменений в таблицу:

var ss = document.styleSheets[0];             // Извлечь первую таблицу стилей
var rules = ss.cssRules?ss.cssRules:ss.rules; // Извлечь правила
for(var i = 0; i < rules.length; i++) {       // Цикл по этим правилам
  var rule = rules[i];
  if (!rule.selectorText) continue;           // Пропустить ©import и др. директивы
  var selector = rule.selectorText;           //Селектор
  var ruleText = rule.style.cssText;          // Стили в текстовом виде
  // Если правило применяется к элементам h1, применить его и к элементам h2
  // Учтите, что этот прием сработает, только если селектор
  // в точности будет иметь вид "h1"
  if (selector == "h1") {
    if (ss.insertRule) ss.insertRule("h2 {" + ruleText + "}", rules.length);
  else if (ss.addRule) ss.addRule("h2", ruleText, rules.length);
  }
  // Если правило устанавливает свойство text-decoration, удалить его.
  if (rule.style.textDecoration) {
    if (ss.deleteRule) ss.deleteRule(i);
    else if (ss.removeRule) ss.removeRule(i);
    i--; // Скорректировать переменную цикла, поскольку прежнее правило с
    //индексом i+1 теперь стало правилом с индексом i
  }
}

содержание 16.6.3. Создание новых таблиц стилей

Наконец, имеется возможность создавать совершенно новые таблицы стилей и добавлять их в документ. В большинстве браузеров эта операция выполняется с помощью стандартных приемов, реализованных в модели DOM: создается новый элемент <style> и вставляется в документ в раздел <head>, затем с помощью свойства innerHTML добавляется содержимое таблицы стилей. Однако в IE8 и в более ранних версиях новый объект CSSStyleSheet необходимо создавать с помощью нестандартного метода document.createStyleSheet(), а текст таблицы стилей добавлять с помощью свойства cssText. Пример 16.6 демонстрирует создание новых таблиц.

Пример 16.6. Создание новой таблицы стилей

// Добавляет таблицу стилей в документ и заполняет ее указанными стилями.
// Аргумент styles может быть строкой или объектом. Если это строка.
// она интерпретируется как текст таблицы стилей. Если это объект, то каждое
// его свойство должно определять правило стиля, добавляемое в таблицу.
// Именами свойств являются селекторы, а их значениями - соответствующие стили
function addStyles(styles) {
  // Сначала необходимо создать новую таблицу стилей
  var styleElt, styleSheet;
  if (document.createStyleSheet) { // Если определен IE API, использовать его
    styleSheet = document.createStyleSheet();
  }
  else {
    var head = document.getElementsByTagName("head")[0]
    styleElt = document.createElement("style"); // Новый элемент <style>
    head.appendChild(styleElt); // Вставить в <head>
    // Теперь новая таблица находится в конце массива
    styleSheet = document.styleSheets[document.styleSheets.length-1]
  }
  // Вставить стили в таблицу
  if (typeof styles === "string") {
    // Аргумент содержит текстовое определение таблицы стилей
    if (styleElt) styleElt.innerHTML = styles;
    else styleSheet.cssText = styles; // The IE API   }
    else {
    // Аргумент - объект с правилами для вставки
    var i = 0;
    for(selector in styles) {
      if (styleSheet.insertRule) {
        var rule = selector + " {" + styles[selector] + "}";
        styleSheet.insertRule(rule, i++);
      }
      else {
        styleSheet.addRule(selector, styles[selector], i++);
      }
    }
  }
}