Опубликован: 01.07.2011 | Уровень: для всех | Доступ: платный
Лекция 10:

Динамический стиль - управление CSS с помощью JavaScript

< Лекция 9 || Лекция 10 || Лекция 11 >
Аннотация: Доступ к таблицам стилей. Свойства таблиц стилей. Добавление и удаление правил. Изменение стилей элементов. Имена классов элементов.

Введение

В данном месте раздела курса посвященного JavaScript вы уже рассмотрели реальные основы использования JavaScript, посмотрели, как находить элементы, используя DOM, и увидели, как манипулировать ими, если они были успешно найдены.

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

  • Доступ к таблицам стилей
  • Свойства таблиц стилей
  • Добавление и удаление правил
  • Изменение стилей элементов
  • Имена классов элементов
  • Заключение
  • Контрольные вопросы

Доступ к таблицам стилей

Браузер предоставляет интерфейс для взаимодействия с таблицами стилей - в коде JavaScript можно получить доступ к списку таблиц стилей, используя document.styleSheets. Свойство document.styleSheets возвращает список всех таблиц стилей, примененных к странице, включая внешние таблицы стилей, на которые ссылается элемент link, и внутренние таблицы стилей, расположенные внутри элементов style. Если элементы style имеют атрибуты id, можно ссылаться на них непосредственно с помощью document.getElementById(element_id).

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

var sheet = document.createElement('style');
sheet.innerHTML = "div {border: 2px solid black; background-color: blue;}";
document.body.appendChild(sheet);

Удаление таблицы стилей также выполняется очень просто. Сначала необходимо получить таблицу стилей, которую вы хотите удалить. Это можно сделать, используя document.getElementById, как показано в небольшом примере ниже. Чтобы удалить таблицу стилей, можно использовать функцию DOM parent.removeChild(element), где element является объектом таблицы стилей, которую необходимо удалить, а parent является узлом предком таблицы стилей. Как показано в примере ниже, чтобы удалить таблицу стилей ( sheetToBeRemoved ), вы сначала получаете предка таблицы стилей - var sheetParent = sheetToBeRemoved.parentNode - а затем вызываете removeChild с аргументом sheetToBeRemoved - sheetParent.removeChild(sheetToBeRemoved)

var sheetToBeRemoved = document.getElementById('styleSheetId');
var sheetParent = sheetToBeRemoved.parentNode;
sheetParent.removeChild(sheetToBeRemoved);

Пример доступа к таблицам стилей (http://dev.opera.com/articles/view/dynamic-style-css-javascript/accessingstylesheets.html) показывает как доступ ко всем таблицам стилей, так и добавление и удаление новой таблицы стилей на странице.

Свойства таблиц стилей

В JavaScript имеется объект stylesheet, который позволяет получить доступ к информации о таблице стилей, на которую ссылается текущая web-страница, такую как отключена она или нет, ее местоположение, и список правил CSS, которые она содержит. Полный список свойств объекта stylesheet (и многих других вещей также) можно найти в документации W3C по DOM таблиц стилей (Document Object Model Style Sheets - http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html).

Давайте рассмотрим (в данный момент) теоретический пример - пусть имеется web-сайт, где представлена серия технических статей. Мы хотим привлечь внимание к некоторым из этих статей с помощью интересной анимированной карусели, но как быть с пользователями, у которых JavaScript не включен по каким-то причинам? Вспоминая полученные знания о ненавязчивом JavaScript, мы хотим, чтобы функции Web-сайта также работали для этих пользователей, но мы можем захотеть оформить сайт для этих пользователей по-другому, чтобы им было удобно использовать сайт, даже без карусели.

Мы хотим иметь таблицу стилей, которая активируется, только если активируется JavaScript. Нам повезло - интерфейс DOM таблиц стилей предоставляет нам доступ к атрибуту disabled, который позволяет включать и выключать таблицы стилей.

Большинство свойств объекта stylesheet предназначены только для чтения, но некоторые, такие как disabled, можно изменять.

Можно также использовать свойства таблиц стилей, чтобы различать несколько таблиц стилей на странице. Свойство src может помочь идентифицировать внешние таблицы стилей, но не может указать внутренние элементы стиля. Лучший способ, который позволяет ссылаться как на внутренние, так и на внешние таблицы стилей по отдельности, состоит в использовании свойства title. При последовательном просмотре document.styleSheets можно различать таблицы стилей, использованные на странице. Следующий пример показывает, как это можно реализовать:

function getStyleSheet(unique_title) {
  for(var i=0; i<document.styleSheets.length; i++) {
    var sheet = document.styleSheets[i];
    if(sheet.title == unique_title) {
      return sheet;
    }
  }
}

Для каждого объекта stylesheet, извлеченного из массива styleSheets, можно получить доступ к его свойству title, чтобы проверить, что оно содержит заголовок, который требуется найти. Действующий пример этого можно видеть в примере по добавлению и удалению правил, который рассматривается в следующем разделе.

Переключение между различными таблицами стилей на основе предпочтений пользователей является достаточно общим свойством web-сайтов - используя, рассмотренные до сих приемы, можно задать несколько таблиц стилей и использовать только те, которые текущий посетитель сайта хотел бы увидеть. Давайте посмотрим на реальный пример - вначале оформляется текст, но когда атрибут disabled задается как true, определенный нами CSS будет отключен. Можно снова легко включить CSS, задавая disabled как false. Посмотрите пример со свойствами таблиц стилей (http://dev.opera.com/articles/view/dynamic-style-css-javascript/stylesheetproperties.html), чтобы увидеть, как это можно использовать.

Добавление и удаление правил

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

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

Объект stylesheet имеет две функции, которые помогают решить эту проблему. Первой является функция insertRule, которая выглядит следующим образом:

stylesheet.insertRule(rule,index)

где rule будет строкой, содержащей правило, которое мы хотим добавить в таблицу стилей. index определяет, где в списке правил таблицы стилей должно помещаться это правило. Вот как это может выглядеть.

stylesheet.insertRule(".have-border { border: 1px solid black;}", 0);

Я создал пример, чтобы показать, как используется функция insertRule. В этом примере есть список всех правил в таблице стилей. Когда нажимается кнопка, то добавляется правило с индексом 2, которое делает текст красным, добавляя свойство color: red в правило p { ... }. Посмотрите пример добавления и удаления правил (http://dev.opera.com/articles/view/dynamic-style-css-javascript/addingandremovingrules.html).

Если требуется удалить это правило, можно вызвать функцию stylesheet.deleteRule(index), где index будет индексом правила, которое будет удалено.

В примере демонстрации статей можно создать правило, которое делает свойство display равным none для всех статей о HTML и JavaScript - посмотрите в примере карусели (http://dev.opera.com/articles/view/dynamic-style-css-javascript/carousel.html), чтобы увидеть это в действии.

Примечание: IE не реализует правила в соответствии со стандартами. Вместо атрибута cssRules он использует rules. IE использует также removeRule вместо deleteRule и addRule(selector, rule, index) вместо insertRule.

Изменение стилей элементов

Теперь вы должны понимать, как редактировать таблицы стилей, соединенные со страницей, и создавать и модифицировать в них правила CSS. Что делать, если вы захотите изменить определенный элемент в DOM? Используя DOM API можно получить доступ к определенным элементам страницы. Возвращаясь к примеру карусели можно видеть, что функции определены таким образом, что при щелчке на статье эта статья выделяется, в то время как основной текст статьи выводится ниже.

С помощью DOM мы получаем доступ к объекту style, который описывает стиль документа. Этот объект style определен как CSSStyleDeclaration ; подробное объяснение этого можно найти в документации W3C по интерфейсу CSSStyleDeclaration (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration). Объект style работает не совсем так, как некоторые другие свойства, определенные в элементе HTML. В отличие от element.href или element.id, которые возвращают строки, element.style возвращает объект. Это означает, что невозможно задать стиль, присваивая строку для element.style.

Объект style имеет атрибуты, которые соответствуют различным заданным свойствам CSS. Например, style.color возвращает заданный на элементе цвет. Выполняя element.style.color = "red"; можно динамически изменять стиль. Ниже показана функция, которая превращает цвет элемента в красный, когда ей передается id элемента.

function colorElementRed(id) {
  var el = document.getElementById(id);
  el.style.color = "red";
}

Можно также использовать setAttribute(key, value) для задания стиля элемента. Например, задать цвет элемента как красный, вызывая на элементе element.setAttribute('style', 'color: red');, но будьте осторожны, так как это удаляет любые изменения, сделанные в объекте style.

Когда стиль элемента задается таким образом, то это то же самое, как если бы мы задавали его как объявление атрибута style элемента html. Этот стиль будет применяться только в том случае, когда важность и специфичность правила будут больше, чем другие примененные к элементу правила (специфичность объясняется в лекции 28 о наследовании и каскадировании CSS).

У некоторых из вас может возникнуть вопрос, что происходит, когда заданное свойство CSS имеет дефис. В этом случае синтаксис должен быть другой, так как, например, если написать element.style.font-size, JavaScript будет пытаться вычесть size из записи element.style.font, что будет совершенно не то, что требуется. Чтобы исключить эту проблему, все свойства CSS записаны в верблюжьей нотации ( CamelCase ). Как показано ниже, необходимо писать element.style.fontSize, чтобы получить доступ к размеру шрифта элемента. Например:

function changeElement(id) {
  var el = document.getElementById(id);
  el.style.color = "red";
  el.style.fontSize = "15px";
  el.style.backgroundColor = "#FFFFFF";
}

Помните объекты таблиц стилей? Свойство styleSheet.cssRules возвращает список объектов style, представляющих все правила CSS, содержащиеся в таблице стилей. Эти объекты style можно использовать также, как объекты style для других элементов. В этом случае вместо изменения одного определенного элемента на странице, изменения здесь будут изменять все элементы, к которым применяются правила CSS.

В примере ниже функция увеличения текста использует объект style, а функция уменьшения текста использует setAttribute. Если текст задан красным цветом, а затем вызывается setAttribute с кнопкой уменьшения текста, то можно заметить, что изменения будут переопределены. Посмотрите действующий пример изменения стилей элементов (http://dev.opera.com/articles/view/dynamic-style-css-javascript/changingelementstyles.html).

Имена классов элементов

Другой способ изменения стиля элемента состоит в изменении его атрибута class. class является зарезервированным словом в JavaScript, поэтому, чтобы получить доступ к классу элемента, мы используем element.className. Можно присоединять строки к className, если требуется добавить класс к элементу, или можно просто перезаписать className и задать ему совершенно новый класс. Посмотрите пример с именами классов элементов (http://dev.opera.com/articles/view/dynamic-style-css-javascript/elementclassnames.html).

Заключение

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

Контрольные вопросы

  • в чем различие между setAttribute и заданием стиля через объект CSSStyleDeclaration?
  • Укажите два способа, с помощью которых можно у всех изображений выводить зеленую границу, когда пользователь щелкает на кнопке.
  • Будет ли изменение объекта CSSStyleDeclaration элемента всегда изменять стиль элемента? Почему?
  • Укажите два способа доступа к определенной таблице стилей.

Об авторе


Грег Шехтер является пока новичком в отрасли web-технологий - он в настоящее время изучает программирование в Университете Иллинойса в Урбана-Шампань. Он стремится поскорее войти в отрасль web-приложений, где надеется создавать насыщенные и полезные web-сайты для пользователей во всем мире. Подробнее о Греге можно узнать на сайте GregTheBusker.com (http://gregthebusker.com/).

< Лекция 9 || Лекция 10 || Лекция 11 >
Сергей Крупко
Сергей Крупко
Как оплатить курс?
Галина Башкирова
Галина Башкирова
Темы Вкр для проф. переподготовки Профессиональное веб-программирование
Наталья Алмаева
Наталья Алмаева
Россия
Роман Паранин
Роман Паранин
Россия, Ярославль