Xpoint
   [напомнить пароль]

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

Оглавление

Поддержка

Динамическое изменение стилей элементов поддерживается почти в одинаковой форме всеми современными браузерами: Internet Explorer 4+, Mozilla 1.0+ (соответственно Netscape 7.0+, все версии Firefox и т.д.) и Opera как минимум с версии 7.20.

Изменение класса элемента

Самый простой и надёжный способ изменить отображение элемента - это изменение его класса, то есть свойства className. Пример:

<html>
<head>
<style type="text/css">
.class1 {
  color: white;
  background-color: black;
}
.class2 {
  color: blue;
  background-color: green;
}
</style>
</head>
<body>
<div onclick="this.className = (this.className == 'class2' ? 'class1' : 'class2')">
Click here multiple times
</div>
</body>
</html>

Напомним, что элементу можно присвоить более одного класса, для этого нужно просто разделить их названия пробелом.

Преимущества этого подхода:

  • можно менять несколько CSS-свойств одновременно
  • в JavaScript используются только названия классов, CSS-код определён отдельно
  • изменения легко обратимы, достаточно вернуть старое значение класса

Недостаток:

  • Стили предопределены, соответственно количество возможностей ограничено

Нередко стили используют для того, чтобы динамически передвигать элементы с абсолютным позиционированием; для этого переопределением класса элемента не обойтись.

Пример реализации

К сожалению, в стандарте DOM нет никаких механизмов для работы с множеством классов элемента — есть только свойство className, напрямую отображающее атрибут class — т.е. строку с пробелами. Предлагаемый объект-обёртка позволяет облегчить работу с множественными классами.

// класс-обёртка, явным образом обычно не создаётся (см. ниже)
function CssClassesHandler(object) { this.object = object }

CssClassesHandler.prototype = {
    object      : null,
    
    // возвращает все классы элемента в виде массива строк
    all         : function() {
                    return this.object.className.split(/\s+/)
                },

    // назначен ли элементу данный класс?
    exists      : function(className) {
                    var classes = this.all()
                    for(var i = 0; i < classes.length; i++)
                        if(classes[i] == className) return true
                    return false
                },

    // назначает элементу класс
    add         : function(className) {
                    var classes = this.all()
                    for(var i = 0; i < classes.length; i++)
                        if(classes[i] == className) return
                    this.object.className = this.object.className + " " + className
                },

    // удаляет класс из назначенных элементу.
    // можно указать как имя класса, так и регулярное выражение,
    // которое будет сравниваться отдельно с каждым из назначенных классов.
    remove      : function(className) {
                    var classes = this.all()
                    var cn = ""
                    for(var i = 0; i < classes.length; i++) {
                        var isMatch = (typeof className.test == "function")
                            ? className.test(classes[i])
                            : (classes[i] == className)
                        if(!isMatch) cn = cn + " " + classes[i]
                    }
                    this.object.className = cn.substr(1)
                },

    // назначает/удаляет класс в зависимости от булевского параметра state
    set         : function(className, state) {
                    if(state)
                        this.add(className)
                    else
                        this.remove(className)
                },

    // назначает элементу класс, если он ещё не назначен, в противном случае удаляет
    flip        : function(className) {
                    if(this.exists(className))
                        this.remove(className)
                    else
                        this.add(className)
                }
}

// функция, создающая класс-обёртку для данного элемента
function CssClasses(object) {
    return new CssClassesHandler(object)
}

Пример использования:

div = document.getElementById('someId')

CssClasses(div).add('someClass')
CssClasses(div).remove('someClass')
CssClasses(div).flip('someClass')

Изменение индивидуальных стилей элементов

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

var element = document.getElementById('testElement');
element.style.left = '400px';
element.style.marginTop = '10px';

// Следующая строчка не покажет ничего, если элементу не задать display в атрибуте style
alert(element.style.display);

Свойства объекта style названы так же, как и соответствующие CSS-свойства, но пишутся без дефисов, а следующие за дефисом буквы переведены в заглавный регистр (так из margin-top получилось marginTop). Все свойства доступны для чтения и записи, но читается/меняется при этом исключительно значение атрибута style этого элемента. То есть, читать действующие на данный момент стили элемента нужно иначе.

Доступ к действующим стилям элементов

К сожалению, для определения действующих стилей помимо стандарта DOM2 существует ещё реализация, которая используется в Internet Explorer. DOM2 определяет метод getComputedStyle() объекта document.defaultView, который возвращает действующие стили для комбинации элемента и псевдо-элемента (к примеру, 'hover' или 'active'):

var element = document.getElementById('testElement');
var computedStyle = document.defaultView.getComputedStyle(element, null);
alert(computedStyle.display);

В Internet Explorer вместо этого у каждого элемента есть свойство currentStyle, аналогичное свойству style, но содержащее все действующие стили. Возможность учитывать псевдо-элементы в этом варианте отсутствует. То есть, код, аналогичный предыдущему, выглядел бы в IE так:

var element = document.getElementById('testElement');
alert(element.currentStyle.display);

К счастью, оба варианта несложно объединить. Достаточно написать в начале скрипта:

if (typeof document.defaultView == 'undefined')
  document.defaultView = {};

if (typeof document.defaultView.getComputedStyle == 'undefined')
{
  document.defaultView.getComputedStyle = function(element, pseudoElement)
  {
    return element.currentStyle;
  }
}

После этого можно везде пользоваться функцией document.defaultView.getComputedStyle() - если не использовать псевдо-элементы, всё будет работать правильно в любом браузере, в принципе поддерживающем доступ к действующим стилям.

Изменение таблиц стилей

Иногда стили нужно менять для многих элементов одновременно, что делается проще всего изменением определений в таблице стилей. Эта тема обсуждается в статье Работа с таблицами стилей.

Комментарии

2006-07-07 18:30:06 [обр] Александр Носов[досье]

Хотелось бы знать способ, с помощью которого можно было бы достучатся до стилей элемента в MAC-Safari?

У меня, к сожалению, полного доступа к MAC'у нет. Пэтому, единственное что я смог выяснить:
 - element.currentStyle - такого свойства нет, т.к. браузер построен на Мозиловском движке;
 - document.defaultView - такое свойство есть, но это функция(!) и соответствеено у этой функции не может быть свойства document.defaultView.getComputedStyle;

Гугление, пока тоже не принесло мне результата. :(

Владельцы MAC'ов отзовитесь - помогите !!

спустя 1 минуту [обр] Александр Носов[досье]
P.S. Я тестил на MAC-Safari 1.1
спустя 1 день 21 час [обр] Владимир Палант[досье]

Александр Носов[досье]
Safari построен не на Gecko, а на KHTML. Не обращайте внимание на чушь типа "KHTML, like Gecko".

Safari 1.1 в природе ИМХО уже не встречается, актуальны сейчас 1.3 и 2.0. Думаю, что там все будет нормально.

спустя 1 год 3 месяца [обр] dark-demon[досье]
сафари во многих случаях ведёт себя как мозилла, даже баги у них нередко одинаковые. так что без сорцев мозиллы на ранних этапах точно не обошлось :)
спустя 1 год [обр] Илья Cтpeльцын aka SelenIT[досье]
который возвращает действующие стили для комбинации элемента и псевдо-элемента (к примеру, 'hover' или 'active')
Все-таки, это не псевдоэлементы, а псевдоклассы — см. напр. http://lists.w3.org/Archives/Public/www-dom/2007JanMar/0022.html. Псевдоэлементы — это, видимо, :before, :after и иже с ними…
Powered by POEM™ Engine Copyright © 2002-2005