Управление стилями

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

<!DOCTYPE html>
<html>
<head>
    <title>Уроки по JavaScript</title>
</head>
<style>
.msg {
    width: 400px;
    margin: 0 auto;
    text-align: center;
    background: #20454B;
    padding: 5px;
    border-radius: 5px;
    color: #eee;
    font-size: 24px;
    box-shadow: 5px 5px 4px 4px #aaa;
}
</style>
<body>
<div class="msg">Важная информация!</div>
<script>
</script>
</body>
</html>

На данный момент вам должно быть известно, что внешний вид того или иного тега в документе следует прописывать в каскадных таблицах стилей (CSS) и подключать через атрибут class, например:

<div class="msg">Информация</div>

Второй способ – это использовать атрибут style и уже в нем в виде строки записывать стили оформления:

<div style="position:absolute;top:200px;left:50%">
    Информация 2
</div>

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

Итак, чтобы на уровне JavaScript узнать, какие классы подключены к определенному элементу, используется свойство объекта

elem. className

А для управления свойствами в атрибуте style, идет обращение к объекту:

elem.style

Например:

let elem = document.querySelector("div.msg");
console.log(elem.className);
let elem2 = elem.nextSibling.nextSibling;
console.log(elem2.style.top);

Здесь мы дважды обращаемся к свойству nextSibling для перехода ко второму div, так как не нужно забывать, что перенос строки – это текстовый элемент, стоящий между этими двумя дивами.

Оба этих свойства className и style доступны и для чтения и для записи. Например, определим вот такой класс стилей:

<style>
.message {
    width: 200px;
    padding: 10px;
    background: #eee;
}
</style>

И заменим существующий на него:

let elem = document.querySelector("div.msg");
elem.className = "message";

Теперь наш div отображается с этими новыми стилями. Но что, если у нас есть вот такое расширение класса стилей:

.message.ex {
       color: #0000CC;
}

и мы хотим его применить к элементу div? Напомню, что через атрибут это расширение записывается так:

<div class="message ex"></div>

то есть, через пробел. На уровне JavaScript для добавления (или удаления) таких дополнений используется коллекция

elem.classList

у которой есть такие методы:

  • elem.classList.add/remove("class") – добавить/удалить класс;
  • elem.classList.toggle("class") – добавить класс, если его нет, иначе удалить;
  • elem.classList.contains("class") – проверка наличия класса, возвращает true/false.

Добавим наше расширение к элементу div:

elem.classList.add("ex");

Теперь мы видим синий цвет текста, то есть, дополнение было успешно применено. По аналогии работают и все остальные методы свойства classList.

Свойство classList является итерируемым объектом, поэтому мы можем перебирать его элементы с помощью цикла for of:

for(let cl of elem.classList)
    console.log(cl);

Перейдем теперь к свойству style. Мы также можем напрямую управлять стилями элемента через него. Например, переместим наш второй div на несколько пикселей на экране браузера. Сделаем это так:

let elem2 = elem.nextSibling.nextSibling;
let coordY = 0;
let idMove = setInterval(function() {
       coordY += 5;
       elem2.style.top = coordY+"px";
}, 50);
 
setTimeout(()=>clearInterval(idMove), 3000);

В результате наш элемент будет динамически смещаться по вертикали в течение трех секунд. Обратите внимание на указание единиц измерения «px». Без этого свойство top работать не будет. Единицы измерения у всех подобных свойств, например, width, left, margin, font-size и т.п. указывать обязательно!

Далее, если нужно через style обратиться к свойству, состоящему из составного имени, например,

font-size

то следует использовать верблюжью форму записи:

elem.style.fontSize = "24px";

Если в имени свойства имеется префикс:

-moz-border-radius, -webkit-border-radius

то оно начинается с заглавной буквы:

elem.style.MozBorderRadius = "5px";

Наконец, если нам нужно «сбросить» какое-либо свойство через style, то для этого достаточно присвоить ему пустую строку. Например:

let elem2 = elem.nextSibling.nextSibling;
let idMove = setInterval(function() {
    if(!elem2.style.display) elem2.style.display = "none";
    else elem2.style.display = "";
}, 100);
 
setTimeout(()=>clearInterval(idMove), 3000);

Мы здесь проверяем: если свойство elem2.style.display содержит пустую строку, то присваиваем значение «none», чтобы скрыть элемент. Иначе, «сбрасываем» это свойство, присваивая пустую строку. В результате элемент div начинает мигать с интервалом в 100 мс.

Во всех наших примерах со style мы работали с отдельными свойствами: top, display и т.п. Но что если мы хотим прописать сразу несколько свойств в виде строки:

`color:red; font-size: 18px; background-color: green`

Для этого следует все это присваивать специальному свойству cssText следующим образом:

elem.style.cssText = `color:red; font-size: 18px; background-color: green`;

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

Наконец, следует знать, что свойства в style не синхронизированы со свойствами, указанными в CSS и подключенные к данному элементу. Например, наш элемент:

let elem = document.querySelector("div.msg");
elem.className = "message";
elem.classList.add("ex");

Имеет свойства, прописанные в классе message и его расширении ex. Но, при попытке их вывода через style:

console.log(elem.style.width);

увидим пустую строку. Но, что если мы хотим увеличить ширину на 20 пикселей? Как нам получить текущие свойства элемента? Для этого существует специальный метод:

let objStyles = getComputedStyle(element, [pseudo]);

который возвращает объект objStyles со всеми текущими (актуальными) стилями для элемента, указанным в аргументе element. Если же нам нужен стиль не самого элемента, а его псевдоэлемента, например, :hover, то этот псевдокласс и указывается в аргументе pseudo. Если он не нужен, то не пишем его. Например:

let objStyles = getComputedStyle(elem);
console.log(objStyles.width);

Теперь мы видим корректное значение 200px. Здесь стоит обращать внимание на то, что метод getComputedStyle корректно возвращает точные свойства, вроде paddingTop/paddingBottom/paddingLeft вместо общего свойства padding. Дело в том, что некоторые браузеры некорректно или совсем не формируют общие свойства вроде margin, padding и им подобные, поэтому всегда обращайтесь к соответствующим конкретным значениям!

Также есть одно ограничение на получение стилей псевдокласса :visited у посещенных ссылок. Доступ к нему закрыт на уровне JavaScript-машины, чтобы скрипт не мог знать: была ли посещена та или иная ссылка.

Итак, на этом занятии мы с вами рассмотрели способы управления оформлением элементов HTML-страницы через CSS-классы и свойство style. Теперь у вас есть базовая информация как все это работает.

Видео по теме