Мастер-классы по Javascript Екатеринбург Ростов-на-Дону Москва Узнать больше...
Содержание (скрыть) Содержание (показать)

Стили и классы, getComputedStyle

  1. className
  2. classList
  3. style
    1. style.cssText
    2. Получение информации о style
  4. getComputedStyle и currentStyle
  5. Итого

Эта глава — о свойствах стиля, получении о них информации и изменении при помощи JavaScript.

Перед прочтением, убедитесь, что хорошо знакомы с CSS Box Model. Вы должны хорошо понимать, что такое padding, margin, border.

className

Свойство className соответствует HTML-атрибуту class.

Пример его использования (добавление класса):

<body class="class1 class2">
<script>
  alert(document.body.className);
*!*
  document.body.className += ' class3';
*/!*
</script>
</body>

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

Все JavaScript-фреймворки имеют встроенные функции для добавления, удаления и проверки класса.

Можно написать такую функцию и самостоятельно, например:

function addClass(el, cls) { 
  var c = el.className.split(' ');
  for (var i=0; i<c.length; i++) {
    if (c[i] == cls) return;
  }
  c.push(cls);
  el.className = c.join(' ');
}

function removeClass(el, cls) {
  var c = el.className.split(' ');
  for (var i=0; i<c.length; i++) {
    if (c[i] == cls) c.splice(i--, 1);
  }

  el.className = c.join(' ');
}

function hasClass(el, cls) {
  for (var c = el.className.split(' '),i=c.length-1; i>=0; i--) {
    if (c[i] == cls) return true;
  }
  return false;
}

Сделайте желтыми ссылки внешние ссылки. Все относительные ссылки и абсолютные с доменом javascript.ru считаются внутренними. Желтый цвет должен обеспечиваться установкой класса external.

<style>
.external { background-color: yellow }
</style>
<ul>
 <li><a href="http://google.com">http://google.com</a></li>
 <li><a href="/tutorial">/tutorial.html</a></li>
 <li><a href="ftp://ftp.com/my.zip">ftp://ftp.com/my.zip</a></li>
 <li><a href="http://nodejs.org">http://nodejs.org</a></li>
 <li><a href="http://javascript.ru/test">http://javascript.ru/test</a></li>
 <li><a href="ftp://javascript.ru/file">ftp://javascript.ru/file</a></li>
</ul>

Результат:

Алгоритм
Решение
Алгоритм

Сначала можно найти ссылки, например, при помощи document.getElementsByTagName('a').

Как вы думаете, для проверки адреса нужно получить использовать свойство href, или атрибут getAttribute('href') ? В чем будет различие?

Раскрыть ответ

Свойство будет содержать полный путь ссылки (во всех браузерах, кроме IE<9), а атрибут — значение, указанное в HTML. В данном случае подойдёт и то и другое.

Правила опередения:

  • Cсылки без протокола :// являются заведомо внутренними.
  • Там, где протокол есть — нужно создать новую строку из того, что идёт после :// (indexOf + slice) и проверить начало на совпадение с javascript.ru.
Решение
Решение

Код решения: tutorial/browser/dom/markLinks.html

classList

Свойство classList поддерживается во всех современных браузерах, но не в IE<10. Поэтому, скорее всего, эта секция будет для вас ознакомительной, на будущее Smile

Оно предоставляет удобный интерфейс для работы с классами элемента:

  • elem.classList.contains(cls) — проверяет, есть ли у элемента класс cls
  • elem.classList.add/remove(cls) — добавляют/удаляют класс cls
  • elem.classList.toggle(cls) — добавляет класс cls, если его нет, а если есть — удаляет.

Вы можете пользоваться им, если не нужно поддерживать IE<10.

style

Свойство style дает доступ к стилю элемента. Это свойство можно как читать, так и править.

С помощью него можно изменять большинство CSS-свойств, например element.style.width='100px' работает так, как будто у элемента есть атрибут style="width:100px".

Так же, как и в CSS, вам нужно указывать единицы измерения: ‘px’, ‘pt’, ‘%’ или ‘em’.

Для свойств, названия которых состоят из нескольких слов, используется вотТакаяЗапись:

background-color  => backgroundColor
z-index           => zIndex
border-left-width => borderLeftWidth

Значение style всегда перезаписывает CSS-свойства, поэтому вы можете внести изменения, а затем вернуть все как было, присвоив style пустую строку: elem.style.width=''.

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

// введите пустое значение, чтобы сбросить цвет
document.body.style.backgroundColor = prompt('background color?', 'green')

Специфические свойства браузеров, типа -moz-border-radius, -webkit-border-radius, записываются следующим способом:

button.style.MozBorderRadius = '5px'
button.style.WebkitBorderRadius = '5px'

Конечно, лучше хранить их в отдельных классах, а применять к элементу путем добавления/удаления elem.className.

style.cssText

Свойство style.cssText позволяет читать/записывать целую декларацию:

<div>Button</div>

<script>
  var div = document.body.children[0];
 
  div.style.cssText="*!*color: red !important;*/!* \
    background-color: yellow; \
    width: 100px; \
    text-align: center; \
    *!*blabla: 5; \*/!*
  ";

  alert(div.style.cssText);
</script>

Браузер парсит cssText и применяет известные ему свойства. Нет никаких ограничений на запись несуществующих свойств, типа blabla - большинство браузеров его просто проигнорируют.

Например, свойство blabla не отобразится в Firefox.

style.cssText - это единственный способ добавить !important.

При установке style.cssText все существующие свойства style перезаписываются. Поэтому, по возможности, используют более конкретные подсвойства style: style.color, style.width и т.п.

Получение информации о style

Зачастую перед нами встают задачи, для решения которых нужно узнать размер элемента, отступ и т.п.

Свойство style позволяет читать эту информацию, но лишь ту, которая доступна напрямую из свойства/атрибута "style":

<body style="color:red">
  Красный текст
  <script> 
    alert(document.body.style.color); // red 
  </script>
</body>

Если же стиль получен из CSS, особенно когда задано составное свойство (margin вместо margin-top), то style «не знает» об этом.

Попытка получить marginTop в этом примере, будет неудачной:

<style>
  body { margin: 10px }
</style>
<body>
  <script> 
    alert(document.body.style.marginTop) 
  </script>
</body>

..А вот если сначала присвоить свойство через style, а затем прочесть, то все сработает отлично:

<body>
  <script> 
    document.body.style.margin = '20px';
    alert(document.body.style.marginTop); // 20px! 
  </script>
</body>

Обратите внимание на то, как браузер «распаковал» свойство style.margin, предоставив для чтения style.marginTop. Тоже самое произойдет и для border, background и т.д.

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

В примере ниже, color будет показан в виде rgb(...) в Firefox:

<body style="color:#abc">
  <script> 
    alert(document.body.style.color);  // rgb(170, 187, 204)
  </script>
</body>

В следующей задаче охватываются наиболее используемые свойства.

Возьмите документ, расположенный по адресу tutorial/browser/dom/roundedButton/source.html и создайте ссылку <A> с заданным стилем, используя JavaScript.

В примере ниже кнопка создана при помощи HTML/CSS. В решении кнопка должна создаваться, настраиваться и добавляться в документ при помощи только JavaScript, без тегов <style> и <a>.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
  .button {
    -moz-border-radius: 8px;
    -webkit-border-radius: 8px;
    border-radius: 8px;
    border: 2px groove green;
    display: block;
    height: 30px;
    line-height: 30px;
    width: 100px;
    text-decoration: none;
    text-align: center;
    color: red;
    font-weight: bold;
  }
</style>
</head>
<body>

<a class="button" href="/">Нажми меня</a>

</body>
</html>
Показать в отдельном окне

Проверьте себя: вспомните, что означает каждое свойство, опишите зачем оно здесь.

Решение
Решение

Есть два варианта.

  1. Можно использовать свойство elem.style.cssText и присвоить стиль в текстовом виде. При этом все присвоенные ранее свойства elem.style будут удалены.
  2. Можно назначить подсвойства elem.style одно за другим. Это более безопасно, т.к. меняет только явно присваемые свойства.

Мы выберем второй пусть в решении: tutorial/browser/dom/roundedButton/solution.html.

Описание CSS-свойств:

.button {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
  border: 2px groove green;
  display: block;
  height: 30px;
  line-height: 30px;
  width: 100px;
  text-decoration: none;
  text-align: center;
  color: red;
  font-weight: bold;
}

*-border-radius
Добавляет скругленные углы. Свойство присваивается в вариантах для Firefox -moz-..., Chrome/Safari -webkit-... и стандартное CSS3-свойство для тех, кто его поддерживает (Opera).
display
По умолчанию, у A это свойство имеет значение display: inline.
height, line-height
Устанавливает высоту и делает текст вертикально центрированным путем установки line-height в значение, равное высоте. Такой способ центрирования текста работает, если он состоит из одной строки.
text-align
Центрирует текст горизонтально.
color, font-weight
Делает текст красным и жирным.

Лучше не присваивать свойства в JavaScript, если оформление можно вынести в CSS.

В отличие от разобранного примера, как правило, JavaScript лишь добавляет или убирает класс, а стили настраиваются уже в CSS.

getComputedStyle и currentStyle

Свойство style дает доступ только к той информации, которые хранится в elem.style.

Он не скажет ничего об отступе, определенном в CSS:

<style>
  body { margin: 10px }
</style>
<body>

  <script> 
    alert(document.body.style.marginTop) 
  </script>

</body>

А если мы хотим, например, сделать анимацию и плавно увеличивать отступ на 10px? Как нам сделать это? Для начала, нам надо получить текущее значение.

Для того, чтобы получить текущее значение свойства, используется метод window.getComputedStyle, описанный в стандарте DOM Level 2.

Его синтаксис таков:

getComputedStyle(element, pseudo)

element
Элемент, значения для которого нужно получить
pseudo
Псевдо-селектор, например 'hover' или null, если он не нужен.

Поддерживается всеми браузерами, кроме IE<9. Следующий код будет работать во всех не-IE браузерах и в IE9+:

<style>
  body { margin: 10px }
</style>
<body>

  <script> 
    var computedStyle = getComputedStyle(document.body, null)
    alert(computedStyle.marginTop) 
  </script>

</body>

В IE до 9 версии есть свое свойство currentStyle, что почти то же самое.

Фишка в том, что currentStyle возвращает значение ‘как есть’, в тех единицах измерения, в которых он задано в CSS, а не в пикселях.
Давайте посмотрим:

<style>
  body { margin: 10% }
</style>
<body>
  <script> 
    var elem = document.body;

    if (window.getComputedStyle) {
      var computedStyle = getComputedStyle(elem, null)
    } else {
      computedStyle = elem.currentStyle
    }

    var marginTop = computedStyle.marginTop;
    alert(marginTop);
  </script>
</body>

Можно написать кросс-браузерный код и короче:

var marginTop = window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle;

Некоторые особенности этого метода:

  1. В Firefox пиксели могут быть дробными. Это особенность getComputedStyle в Firefox.
  2. В IE свойство currentStyle сохраняет единицы измерения. Предыдущий пример выдаст проценты. Единицы измерения также сохраняются для ряда свойств в Safari (это баг).

IE<9: перевод pt,em,% в пиксели

Этот материал — дополнительный. Он не обязателен для освоения.

В IE для того, чтобы получить из процентов реальное значение в пикселях существует метод «runtimeStyle+pixel», описанный Дином Эдвардсом.

Он основан на свойствах runtimeStyle и pixelLeft, работающих только в IE.

В следующем примере функция getIEComputedStyle(elem, prop) получает значение в пикселях для свойства prop, используя elem.currentStyle и метод Дина Эдвардса.

Если вам интересно, как он работает, ознакомьтесь со свойствами с runtimeStyle и pixelLeft в MSDN и раскройте код.

function getIEComputedStyle(elem, prop) {
  var value = elem.currentStyle[prop] || 0

  // we use 'left' property as a place holder so backup values
  var leftCopy = elem.style.left
  var runtimeLeftCopy = elem.runtimeStyle.left

  // assign to runtimeStyle and get pixel value
  elem.runtimeStyle.left = elem.currentStyle.left
  elem.style.left = (prop === "fontSize") ? "1em" : value
  value = elem.style.pixelLeft + "px";

  // restore values for left
  elem.style.left = leftCopy 
  elem.runtimeStyle.left = runtimeLeftCopy 
 
  return value
}

Рабочий пример (только IE):

<style> #margin-test { margin: 1%; border: 1px solid black; } </style>
<div id="margin-test">Тестовый элемент с margin 1%</div>

<script>
  var elem = document.getElementById('margin-test')
  if (!elem.getComputedStyle) // старые IE
    document.write(getIEComputedStyle(elem, 'marginTop')) 
  else 
    document.write('Пример работает только в IE<9')
</script>
Тестовый элемент с margin 1%

Современные Javascript-фреймворки используют этот прием для эмуляции getComputedStyle в старых IE.

Итого

Все DOM-элементы предоставляют следующие свойства.

  • Свойство className всегда синхронизируется с атрибутом class.
  • Свойство style - это объект, в котором CSS-свойства пишутся вотТак. Он хорошо работает для записи свойств. И позволяет читать свойства заданные им или атрибутом «style», но не описанные в CSS.
  • cssText позволяет получать/записывать полный набор свойств для style в текстовом виде. С помощью style вы не можете добавить !important, но можете сделать это с cssText.
  • Свойство currentStyle(IE) и метод getComputedStyle (стандарт) позволяют получить живое значение свойств стилей, после того, как эти стили были применены.

    Примечания:

    1. Firefox может вернуть дробное значение.
    2. Старый IE и Safari возвращают значение в заданных единицах измерения, не приводя их к пикселям.

Комментарии

  1. Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  2. Если ваш комментарий касается задачи -- откройте её в отдельном окне и напишите там.
  3. Комментарии без смысла, с рекламой или не о статье вообще - удаляются.
Наверх

Содержание

Реклама

Нашли опечатку?

Нашли опечатку на сайте? Что-то кажется странным?
Выделите соответствующий текст и нажмите Ctrl+Enter!

Последние Комментарии

Помоги другим!

Помоги другим узнать о хорошей статье!