Блочная и строчная вёрстка
Вы, возможно, уже заметили, что элементы разных типов имеют разную вёрстку. Некоторые элементы, такие как абзацы (<p>
) и заголовки (<h1>
), занимают всю ширину документа и отображаются на отдельной строке. Такие элементы называются блочными (Block). Другие элементы, например ссылки (<a>
) или элементы <strong>
, отображаются рядом с окружающим текстом на одной строке. Мы называем такие элементы строчными (Inline).
Для любого конкретного документа браузер может вычислить размер и положение каждого элемента на основе его типа и содержимого. Затем он использует эту информацию для отрисовки документа.
В JavaScript можно получить доступ к размеру и положению элементов.
Свойства offsetWidth
и offsetHeight
дают начальное положение элемента (в пикселях). Пиксель — это основная единица измерения в браузере. Обычно он соответствует наименьшей точке, которую можно нарисовать на экране, но на современных дисплеях можно рисовать очень маленькие точки, которые могут быть неактуальными, и пиксели браузера могут охватывать несколько точек дисплея.
Точно так же clientWidth
и clientHeight
предоставляют вам размер пространства внутри элемента, игнорируя ширину рамки.
<p style="border: 3px solid red">
I'm boxed in
</p>
<script>
let para = document.body.getElementsByTagName("p")[0];
console.log("clientHeight:", para.clientHeight);
console.log("offsetHeight:", para.offsetHeight);
</script>
Метод getBoundingClientRect
— это наиболее эффективный способ получить точное местоположение элемента на экране. Этот метод возвращает объект с четырьмя свойствами: top
, bottom
, left
и right
, которые указывают положение элемента относительно верхнего левого угла экрана (в пикселях). Если вы хотите узнать его положение относительно всего документа, вам нужно добавить его позицию прокрутки, которую вы можете найти в привязках pageXOffset
и pageYOffset
.
Нам также нужно приложить некоторые усилия, чтобы завершить вёрстку документа. Чтобы ускорить процесс, браузер не сразу перерисовывает весь документ каждый раз, когда вы его изменяете, а по возможности ждёт и откладывает перерисовку. Когда программа JavaScript, которая изменяет документ, завершается, браузер вычисляет новую вёрстку и отображает изменённый документ на экране. Если программа считывает свойства, такие как offsetHeight
и getBoundingClientRect
, чтобы получить положение или размер некоторых элементов, браузеру также необходимо вычислить вёрстку, чтобы предоставить правильную информацию.
Если программа многократно считывает информацию о вёрстке DOM или изменяет DOM, это может вызвать большое количество вычислений вёрстки, что приводит к очень медленной работе. Следующий код демонстрирует пример. Он содержит две разные программы, которые используют символ X
для создания линии длиной 2000 пикселей и измеряют время выполнения каждой задачи.
<p><span id="one"></span></p>
<p><span id="two"></span></p>
<script>
function time(name, action) {
let start = Date.now(); // Current time in milliseconds
action();
console.log(name, "took", Date.now() - start, "ms");
}
time("naive", () => {
let target = document.getElementById("one");
while (target.offsetWidth < 2000) {
target.appendChild(document.createTextNode("X"));
}
});
// → naive took 32 ms
time("clever", function() {
let target = document.getElementById("two");
target.appendChild(document.createTextNode("XXXXX"));
let total = Math.ceil(2000 / (target.offsetWidth / 5));
target.firstChild.nodeValue = "X".repeat(total);
});
// → clever took 1 ms
</script>
Стиль
Мы видели, что отрисовка различных HTML-элементов различается. Некоторые элементы отображаются как блоки, а некоторые — как встроенные. Мы также можем добавлять стили, например, использовать <strong>
для выделения текста жирным шрифтом или использовать <a>
для того, чтобы сделать текст синим и добавить подчёркивание.
Способ отображения изображений с помощью тега <img>
или ссылок, созданных с помощью <a>
, тесно связан с типом элемента. Однако по умолчанию стиль элемента, такой как цвет текста или наличие подчёркивания, можно изменить. Здесь показан пример использования атрибута style
.
<p><a href=".">Normal link</a></p>
<p><a href="." style="color: green">Green link</a></p>
Атрибут стиля может содержать одно или несколько объявлений, формат которых представляет собой атрибут (например, color
) с последующим двоеточием и значением (например, green
). Когда есть несколько объявлений, разные атрибуты должны быть разделены точкой с запятой, например color:red;border:none
.
Многие аспекты документа могут зависеть от стиля. Например, атрибут display
управляет тем, отображается ли элемент как блок или встроенный элемент.
This text is displayed <strong>inline</strong>,
<strong style="display: block">as a block</strong>, and
<strong style="display: none">not at all</strong>.
Тег block
завершает строку, на которой он находится, потому что блочные элементы не отображаются встроенными вместе с окружающим текстом. Последний тег вообще не отображается, потому что display:none
предотвращает отображение элемента на экране. Это один из способов скрыть элемент. Лучший способ — полностью удалить его из документа, потому что позже вернуть его обратно будет легко.
JavaScript-код может управлять стилем элемента через атрибут style
элемента. Этот атрибут сохраняет объект, который содержит все возможные атрибуты стиля, значения которых являются строками, и мы можем записать строки в атрибут, чтобы изменить стиль некоторых аспектов элемента.
<p id="para" style="color: purple">
Nice text
</p>
<script>
let para = document.getElementById("para");
console.log(para.style.color);
para.style.color = "magenta";
</script>
Некоторые имена атрибутов стиля содержат дефисы, например font-family
. Поскольку эти имена не подходят для использования в JavaScript (вы должны написать их как style["font-family"]
), в JavaScript имена свойств объекта стиля удаляются дефисом и заглавной буквой после дефиса (например, style.fontFamily
).
Каскадные таблицы стилей
Мы называем систему стилей HTML каскадными таблицами стилей (CSS), что означает каскадные таблицы стилей. Таблицы стилей представляют собой набор правил, указывающих, как добавлять стили к элементам в документе. Вы можете написать CSS в теге <style>
.
<style>
strong {
font-style: italic;
color: gray;
}
</style>
<p>Now <strong>strong text</strong> is italic and gray.</p>
Термин «каскадный» относится к объединению нескольких правил для создания окончательного стиля элемента. В этом примере правило <style>
переопределяет значение по умолчанию font-weight:bold
для тега <strong>
, добавляя стили font-style
и color
к тегу <strong>
.
Когда несколько правил определяют один и тот же атрибут, последнее правило имеет наивысший приоритет. Поэтому, если правило <style>
содержит font-weight:normal
, что противоречит значению по умолчанию для font-weight
, текст будет отображаться обычным шрифтом, а не жирным. Атрибуты стиля в элементе будут напрямую влиять на узел, и они часто имеют наивысший приоритет.
Мы можем использовать имена тегов в правилах CSS для нацеливания на теги. Правило .abc
применяется ко всем элементам, класс которых содержит abc
. Правило #xyz
применяется к элементу с идентификатором xyz
(который должен быть уникальным в документе).
.subtle {
color: gray;
font-size: 80%;
}
#header {
background: blue;
color: white;
}
/* p elements with id main and with classes a and b */
p#main.a.b {
margin-bottom: 20px;
}
``` **Приоритет правил склоняется в сторону недавно определённых, которые применяются только при условии специфичности.** Специфичность используется для оценки точности соответствия элементов при описании правила. Специфичность зависит от количества и типа элементов (tag, class или id) в правиле. Например, целевое правило p.a более конкретно, чем p или .a, поэтому имеет более высокий приоритет.
**p>a** — этот синтаксис применяет стиль к прямым дочерним узлам тега <p>. Аналогично, **p a** применяется ко всем тегам <a> внутри всех тегов <p>, независимо от того, являются ли они прямыми дочерними узлами.
#### **Выбор селектора**
В этой книге не будет использоваться слишком много таблиц стилей. Хотя понимание таблиц стилей крайне важно для разработки программ для браузеров, для правильного понимания всех поддерживаемых свойств и их использования может потребоваться две-три книги.
Основная причина введения синтаксиса селекторов (используется в таблицах стилей для определения элементов, на которые действует стиль) заключается в том, что этот микроязык также является эффективным способом поиска DOM-элементов.
Объекты document и element определяют метод querySelectorAll, который принимает строку селектора и возвращает массивный объект, содержащий все совпадающие элементы.
```html
<p>And if you go chasing
<span class="animal">rabbits</span></p>
<p>And you know you're going to fall</p>
<p>Tell 'em a <span class="character">hookah smoking
<span class="animal">caterpillar</span></span></p>
<p>Has given you the call</p>
<script>
function count(selector) {
return document.querySelectorAll(selector).length;
}
console.log(count("p")); // All <p> elements
// → 4
console.log(count(".animal")); // Class animal
// → 2
console.log(count("p .animal")); // Animal inside of <p>
// → 2
console.log(count("p > .animal")); // Direct child of <p>
// → 1
</script>
В отличие от таких методов, как getElementsByTagName, объекты, возвращаемые querySelectorAll, не изменяются динамически. Их содержимое не изменяется при изменении документа. Однако это не настоящий массив, поэтому, если вы собираетесь рассматривать его как реальный массив, вам всё равно нужно вызвать Array.from.
Метод querySelector, у которого нет All, работает аналогично querySelectorAll. Этот метод очень полезен, когда вы хотите найти один конкретный элемент. Он возвращает первый совпавший элемент или null, если совпадений нет.
Свойство style — мощный инструмент для компоновки. По умолчанию значение этого свойства равно static, что означает, что элемент находится в исходном положении в документе. Если этому свойству присвоено значение relative, элемент остаётся на своём месте в документе, но его свойства top и left смещаются относительно исходного положения. Если свойство установлено в absolute, элемент удаляется из обычного потока документа и не занимает места, а перекрывает другие элементы. Его свойства top и left смещены относительно ближайшего элемента с другим значением свойства position, отличным от static. Если такого элемента нет, смещение происходит относительно всего документа.
Мы можем использовать это свойство для создания анимации. Следующий документ показывает изображение кошки, которое перемещается по эллиптической траектории.
<p style="text-align: center">
<img src="img/cat.png" style="position: relative">
</p>
<script>
let cat = document.querySelector("img");
let angle = Math.PI / 2;
function animate(time, lastTime) {
if (lastTime != null) {
angle += (time - lastTime) * 0.001;
}
lastTime = time;
cat.style.top = (Math.sin(angle) * 20) + "px";
cat.style.left = (Math.cos(angle) * 200) + "px";
requestAnimationFrame(newTime => animate(newTime, time));
}
requestAnimationFrame(animate);
</script>
Наше изображение находится в центре страницы, и для его перемещения мы должны постоянно обновлять свойства top и left изображения.
Скрипт использует requestAnimationFrame для вызова функции animate каждый раз, когда браузер готов перерисовать экран. Функция animate снова вызывает requestAnimationFrame, чтобы подготовиться к следующему обновлению. Когда окно (или ярлык) активируется, частота обновления составляет примерно 60 раз в секунду, что достаточно для создания плавной анимации.
Если мы просто зациклимся на обновлении DOM, страница остановится, и ничего не отобразится. Браузер не будет обновлять отображение во время выполнения JavaScript-программы и не позволит выполнять какие-либо действия на странице, такие как взаимодействие с пользователем. Вот почему нам нужен requestAnimationFrame: он сообщает браузеру, что JavaScript-программа завершила свою работу, поэтому браузер может продолжить выполнение других задач, таких как обновление экрана и реагирование на действия пользователя.
Функция генерации анимации передаётся в requestAnimationFrame в качестве параметра. Чтобы гарантировать, что движение кошки стабильно и плавно, оно основано на скорости, а угол изменяется на разницу между текущим и предыдущим выполнением функции. Если кошка будет двигаться только на несколько шагов за раз, её движения могут показаться немного медленными, например, другая задача, выполняемая на том же компьютере, может привести к тому, что функция будет выполнена через несколько секунд после запуска.
Для перемещения кошки по эллипсу мы используем тригонометрические функции Math.cos и Math.sin. Возможно, вы не знакомы с этими вычислениями, но я кратко объясню их здесь, потому что вы иногда будете сталкиваться с ними в этой книге.
Функции Math.cos и Math.sin очень полезны, и мы можем использовать угол в 1 радиан для вычисления положения точки на окружности с центром в точке (0,0). Обе функции интерпретируют аргумент как положение точки на окружности, где 0 представляет самую правую точку окружности и увеличивается против часовой стрелки до 2π (примерно 6,28), проходя по всей окружности. Math.cos вычисляет x-координату точки на окружности, а Math.sin вычисляет y-координату. Позиции за пределами 2π или меньше 0 являются допустимыми. Поскольку радианы повторяются, a+2π имеет тот же угол, что и a.
Единицей измерения угла является радиан — полный круг равен 2π радианам, аналогично 360 градусам в градусах. Константа π в JavaScript представлена как Math.PI.
Код анимации кошки сохраняет счётчик с именем angle, который отслеживает угол кошки на окружности, и увеличивает значение счётчика каждый раз при вызове функции animate. Затем мы используем этот угол для расчёта текущего положения элемента изображения. Значение top — это результат Math.sin, умноженный на 20, представляющий вертикальный радиус окружности. Значение left — это результат Math.cos, умноженный на 200, так что окружность шире, чем выше, в результате чего кошка движется по эллиптическому пути.
Здесь следует отметить, что значения стиля обычно требуют указания единиц измерения. В этом примере мы добавляем px после чисел, чтобы сообщить браузеру, что мы хотим использовать пиксели в качестве единицы измерения (а не сантиметры, em или другие единицы). Мы легко можем забыть добавить эти единицы. Если мы не добавим единицы к числам в стиле, браузер в конечном итоге проигнорирует стиль, за исключением случаев, когда число равно 0, в этом случае любая единица даст одинаковый результат.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )