В любом 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. Теперь у вас
есть базовая информация как все это работает.