коробочная модель
коробочная модельМодель макета, используемая элементом dom при отображении страницы.
Коробочная модель доступна черезbox-sizingНастройте его (свойство по умолчанию для box-sizing —content-box). По рассчитанной ширине и высоте площади можно разделить на:
- поле содержимого:
W3C 标准盒模型 - граница:
IE 盒模型 - обивка:
FireFox 曾经支持 - поле поля:
浏览器未实现
🚨 Теоретически выше 4 вида ящиков, но сейчасw3cа такжеmdnСпецификации поддерживаются толькоcontent-boxа такжеborder-box;
Состав коробочной модели, наизнанкуcontent(内容),padding(内边距),border(边框),margin(外边距).
content-box
Ширина и высота стандартной блочной модели W3C относятся к ширине и высоте части содержимого соответственно.помимо ширины и высотынарисовать отступ и границу элемента
Например 🌰:
<style>
#content {
width: 100px;
height: 50px;
border: 5px solid #242424;
margin: 10px;
padding: 20px;
background-color: lightblue;
}
</style>
<body>
<div id="content"></div>
</body>
Здесь мы обнаружим, что мы установили длину и ширину 100 * 50, и то, что представлено, представляет собой коробку 150 * 100.
Это из-за стандартной ширины элемента блочной модели (то есть ширины, которую мы установили в таблице стилей).width = content = 100px
Размер коробкиcontent + padding + border = 100px + 20px*2 + 5px*2 = 150px
border-box
Ширина блочной модели IE равна ширине части содержимого плюс отступы и границы. Любые отступы и границы, указанные для элемента, будут уже установлены.по ширине и высотерисовать
Добавьте к приведенному выше кодуbox-sizing: border-box:
<style>
#content {
width: 100px;
height: 50px;
border: 5px solid #242424;
margin: 10px;
padding: 20px;
background-color: lightblue;
+ box-sizing: border-box;
}
</style>
Ширина элемента модели блока IE равна его размеру блокаwidth = content + padding + border = 100px
Реальная ширина его содержимогоwidth - padding - boder = 100px - 20px*2 - 5px*2 = 50px
Сценарии применения 🎉:
border-boxГораздо удобнее иметь несколько дивов в горизонтальном макете, и тогда каждый занимает по 50%, и тогда как бы вы ни установили границы и отступы, горизонтальный макет не будет проталкиваться на следующую строку.
<style>
.column {
height: 50px;
width: 46%;
margin: 2% 2%;
float: left;
background: lightblue
}
</style>
<body>
<div>
<div class="column"></div>
<div class="column"></div>
</div>
</body>
Если вы добавите границу в 2 пикселя, она будет обернута:
.column {
height: 50px;
width: 46%;
margin: 2% 2%;
float: left;
background: lightblue;
+ border: 2px solid black;
}
плюсbox-sizing: border-box:
.column {
height: 50px;
width: 46%;
margin: 2% 2%;
float: left;
background: lightblue;
border: 2px solid black;
+ box-sizing: border-box;
}
потому что он настроен наborder-boxПосле этого границы и отступы включаются в заданную ширину и высоту. Это означает, что div с границей в 2 пикселя по-прежнему имеет ширину 50%.
BFC
концепция
Formatting contextдаW3C CSS2.1Понятие в спецификации. Это область рендеринга на странице и имеет набор правил рендеринга, которые определяют, как будут расположены его дочерние элементы и как они будут связаны и взаимодействовать с другими элементами. Наиболее распространенные контексты форматирования:BFCа такжеIFC.
BoxИ объект является базовой единицей макета, типа и элементов CSS.displayАтрибут, определяющий тип Box. Различные типы ящиков будут участвовать в разныхFormatting Context
-
block-level box: Значение display: блок, элемент списка, элемент таблицы. И участвовать в BFC (блокировать контекст форматирования); -
inline-level box: значение display — встроенный, встроенный блок, встроенный элемент таблицы. И участвовать в IFC (контекст встроенного форматирования)
BFC(Black formatting context)то есть контекст форматирования на уровне блоков,Это отдельная область рендеринга, вовлечена только коробка уровня BLCOK (коробка на уровне блока), что указывает, как выложены внутренний уровень уровня BLCOK, иРендеринг внутренних элементов не влияет на внешний мир
- Элементы соответствуют любому из следующих условий для формирования BFC:
-
bodyкорневой элемент - Плавающие элементы:
floatЗначение не равно none - Абсолютно позиционированные элементы
positionабсолютный | фиксированный -
displayЗначение inline-block | flex | inline-flex | table-cell | table-caption -
overflowЗначение не видно
- Характеристики BFC (Правила компоновки)
- В BFC как линейный блок (строковый блок состоит из всех встроенных элементов в строке до тех пор, пока строка не будет заполнена, а затем перенесена), так и блочный блок (блочный блок отображается как полная новая строка, если не указано иное) оба Аранжирует вертикально вдоль границы родительского элемента.
- Вертикальное расстояние Box определяется полем. Поля двух соседних блоков, принадлежащих одному и тому же BFC, будут перекрываться.
- Левая сторона поля поля каждого поля (блоков и строк) касается левой стороны поля границы содержащего блока (для форматирования слева направо, в противном случае наоборот). Это верно, даже если есть поплавки.
- Область BFC не будет перекрывать флоат-бокс.
- BFC — это изолированный и независимый контейнер на странице, и дочерние элементы внутри контейнера не будут влиять на внешние элементы. Наоборот.
- При расчете высоты БФК в расчете также участвуют плавающие элементы.
- Правила компоновки IFC
В контексте встроенного форматирования блоки располагаются горизонтально один за другим, начиная с верхней части содержащего блока. горизонтальноmargin,borderа такжеpaddingсохраняются между коробками. Боксы могут быть выровнены по вертикали по-разному: они выравниваются по верхнему или нижнему краю или по базовой линии текста внутри них. Прямоугольная область, содержащая эти поля, образует строку, называемую строкой.
Сценарии применения
Основными сценариями BFC должны быть:
- Не допустить
marginперекрытие - Может содержать плавающие элементы (очистить плавающие элементы)
- Может предотвратить закрытие элементов плавающими элементами
Предотвращение перекрытия полей
<style>
p {
width: 100px;
height: 50px;
background: lightblue;
margin: 50px;
}
</style>
<body>
<p></p>
<p></p>
</body>
2, в котором: BFC принадлежат одному и тому же (упоминаемому здесь как тело элемента) двух смежных полей. Возникает перекрытие блоков. Так вот шаг p тега только два 50px; Если вы хотите избежать перекрытия расстояния снаружи, его можно разместить в разных контейнерах BFC.
Если вы хотите избежать перекрывающихся полей, вы можете поместить любое из них в контейнер BFC;
🚨 Объявите селектор BFC и установите для переполнения значение hidden, чтобы сделать его контейнером BFC. В следующих примерах используется этот селектор.
<style>
p {
width: 100px;
height: 50px;
background: lightblue;
margin: 50px;
}
+ .bfc {
+ overflow: hidden;
+ }
</style>
<body>
<p></p>
+ <div class="bfc">
<p></p>
+ </div>
</body>
В этот момент поля двух блоков становятся равными 100px.
Может содержать плавающие элементы (очистить плавающие элементы)
<style>
div {
background: lightpink;
border: 1px solid lightpink;
overflow: hidden;
}
img {
float: left;
width: 100px;
}
</style>
<body>
<div>
<img src="./images/timg.jpg" alt="" />
</div>
</body>
Когда мы не устанавливаем высоту для родительского узла, а дочерний узел установлен как плавающий, он выходит за пределы потока документа, и происходит коллапс высоты, поэтому высота поля контейнера составляет всего 2 пикселя.
По последней особенности: при расчете высоты БФК в расчете участвует и плавающий элемент
Чтобы решить проблему коллапса высоты, просто активируйте BFC для родительского элемента, чтобы родительский элемент оборачивал плавающий элемент (очищал плавание).
- <div>
+ <div class="bfc">
<img src="./images/timg.jpg" alt="" />
</div>
Может предотвратить закрытие элементов плавающими элементами
<style>
.right {
background: lightpink;
height: 200px;
}
img {
float: left;
width: 100px;
}
</style>
<body>
<div>
<img src="./images/timg.jpg" alt="" />
<div class="right">hi girl!</div>
</div>
</body>
В это время второй элемент фактически частично закрыт плавающим элементом (но текстовая информация не будет закрыта плавающим элементом);
По признаку 4: область БТЧ не будет перекрываться с флоат-боксом.
Если вы хотите избежать перезаписи элемента, вы можете сделать правильный BFC сам по себе:
<div>
<img src="./images/timg.jpg" alt="" />
- <div class="right">hi girl!</div>
+ <div class="right bfc">hi girl!</div>
</div>
контекст стека
Веб-страницы и каждый их элемент имеют систему координат, а элементы HTML следуют воображаемой линии относительно пользователя.
z 轴расстановка,контекст стекаЭто трехмерная концепция этих HTML-элементов, которые занимают это пространство в порядке приоритета на основе атрибутов своих элементов.
Каскадный уровень
Каскадный уровень(уровень стека), также называемый
层叠级别,层叠水平это существительное, описывающее порядок размещения элементов, который определяет, где элементы размещаются вZ 轴Отобразить заказ. Чем выше уровень стека, тем больше отображается на переднем плане.
🎉 Вы можете понимать элемент, который создает контекст стека, как элемент, а другие элементы контекста, не связанные с стеком, можно понимать как общедоступные. Офицеры имеют более высокий ранг и, следовательно, ближе к наблюдателю по оси Z.
В семье этого чиновника есть прислуга и домработницы. Они тоже чиновники, сравнивать экономку магистратского дома с экономкой губернаторского дома бессмысленно, решать, хороши они или плохи, целиком и полностью зависит от их хозяина. Это имеет смысл только в том случае, если собственные подчиненные сравнивают размеры друг друга.
По аналогии с «каскадным контекстом» и «каскадным уровнем» можно сделать следующие выводы:
- Элементы, создающие контекст наложения, имеют более высокий уровень, чем другие элементы.
- Уровень укладки общих элементов определяется контекстом укладки, в котором они размещены.
- Сравнение сложенных уровней только в контексте текущего элемента стека имеет смысл
- В том же контексте наложения он описывает верхний и нижний порядок элементов контекста наложения в контексте наложения по оси Z.
Условия срабатывания
- корневой элемент документа (
html:<html></html>У него есть сам контекст стекирования, называемый «корневым контекстом стекирования». ) -
positionзначениеabsolute、relativeэлементы , иz-indexзначение неauto -
positionзначениеfixed、stickyЭлементы - css3 свойства
-
z-indexзначение неautoизflexдочерний элемент контейнера (родительский элементdisplay : flex|inline-flex) -
z-indexзначение неautoизgridдочерние элементы контейнера - элементаль
opacityзначение не 1 -
mix-blend-modeстоимость имущества неnormalЭлементы - элементаль
transform,filter,perspective,clip-path,mask,mask-image,mask-borderзначение неnone -
isolationСтоимость свойстваisolateЭлементы - существует
will-changeУказывается любой атрибут CSS, даже если вы не указываете значение этих свойств напрямую. -
-webkit-overflow-scrollingсвойство установленоtouchЭлементы -
containСтоимость свойстваlayout,paintили составное значение, содержащее один из них (например,contain: strict,contain: content) Элементы.
-
Каскадный порядок
Каскадный порядок(порядок укладки), также называемый
层叠次序,堆叠顺序В нем описываются правила порядка расположения элементов в одном контексте укладки.Видно, что упомянутые выше «контекст укладки» и «уровень укладки» — это понятие, а «порядок укладки» здесь — своего рода правило.
В том же контексте наложения порядок наложения упорядочен от низкого к высокому (более высокий уровень отображается перед более низким уровнем), как показано на следующем рисунке:
🚨 Зачем следовать этому каскадному порядку? Такие какborderа такжеbackgroundОбычно декоративные свойства, в то время как плавающие и блочные элементы обычно используются для макета, а встроенные элементы являются контентом. Самое главное на веб-странице — это, конечно, содержимое. Поэтому порядок каскадирования содержимого должен быть достаточно высоким. Когда происходит каскадирование, это очень хорошо. Важный текстовый и графический контент может быть предпочтительно представлен на экране.
Руководство по каскадированию
- 1 Сначала проверьте, находятся ли сравниваемые элементы в одном контексте стека:
- 1.1 В том же контексте стекирования уровни стекирования имеют смысл. В это время необходимо сравнить «внутренний уровень укладки элементов» (см. диаграмму «порядок укладки»), элементы с большим уровнем укладки будут перекрывать элементы с маленьким уровнем укладки,
z-indexимеет наивысший приоритет; - 1.2 В различных контекстах стекирования мы сравниваем «уровни стекирования родительских элементов». Порядок отображения элементов определяется уровнем наложения «родительского контекста наложения», независимо от его собственного уровня наложения;
- 1.1 В том же контексте стекирования уровни стекирования имеют смысл. В это время необходимо сравнить «внутренний уровень укладки элементов» (см. диаграмму «порядок укладки»), элементы с большим уровнем укладки будут перекрывать элементы с маленьким уровнем укладки,
- 2 Если уровень наложения и порядок наложения элементов совпадают, то
DOM 流Элементы сзади будут закрывать предыдущие элементы, следуя принципу «позже придет первым»;
🚨 Следует отметить, что элемент суждения находится вZ轴Порядок наложения элемента должен определяться контекстом наложения и уровнем наложения элемента. а не просто сравнивать элементы напрямуюz-indexразмер значения.
а такжеz-indexЗначение атрибута не влияет ни на один элемент, оно действует только наpositionатрибут неstaticвлияет на позиционированный элемент.
Пример
🌰 в том же контексте стека
<style>
.box {
position: relative;
}
.a,
.b,
.c,
.d {
position: absolute;
width: 100px;
color: white;
line-height: 100px;
text-align: center;
}
.a {
top: 20px;
left: 20px;
background: red;
}
.b {
top: 60px;
left: 60px;
background: lightblue;
z-index: 1;
}
.c {
top: 100px;
left: 100px;
background: pink;
}
.d {
width: 140px;
line-height: 140px;
top: 40px;
left: 40px;
background: orange;
z-index: -1;
}
</style>
<body>
<div class='box'>
<span class="a">a</span>
<span class="b">b</span>
</div>
<div class='box'>
<span class="c">c</span>
<span class="d">d</span>
</div>
</body>
проиллюстрировать:Поле родительского элемента a (красный), b (синий), c (розовый) и d (оранжевый) не установленоz-index, поэтому в соответствии с层叠等级结论2、3Зная, что в это время все они принадлежат<html></html>Элементы в корневом контексте наложения, сгенерированном тегом, принадлежат одному и тому же контексту наложения в соответствии с семиуровневым порядком наложения:
- a (красный), c (розовый) не установлены
z-index, также на уровне 6 в последовательности укладки, согласно层叠准则2существуетDOM 流Буква c (розовая) сзади закроет букву a (красную); - б (синий)
z-indexположительный, на уровне 7; - д (синий)
z-indexотрицательный, на уровне 2;
Таким образом, порядок отображения: b (синий) > c (розовый) > a (красный) > d (оранжевый)
🌰 в другом контексте стека
<style>
.box1 {
position: relative;
z-index: 1;
}
.box2 {
position: relative;
z-index: 0;
}
.a,
.b,
.c {
position: absolute;
width: 100px;
color: white;
line-height: 100px;
text-align: center;
}
.a {
top: 20px;
left: 20px;
background: red;
z-index: 10;
}
.b {
top: 60px;
left: 60px;
background: lightblue;
z-index: 20;
}
.c {
top: 100px;
left: 100px;
background: pink;
z-index: 999;
}
</style>
<body>
<div class='box1'>
<span class="a">a</span>
<span class="b">b</span>
</div>
<div class='box2'>
<span class="c">c</span>
</div>
</body>
проиллюстрировать:Хотя C (порошок)z-index999, намного больше, чем A (красный) и B (синий)z-index, но их родительский элемент создает новый контекст стека:
- A (красный), b (синий) родительский элемент box1, сгенерированный контекстом наложения
z-indexположительный, на уровне 7; - Контекст стека, сгенерированный родительским элементом box2 элемента c (розовый)
z-index0, на уровне 6; - согласно с
层叠准则1.2Порядок наложения контекста наложения, сгенерированного box1, больше, чем контекст наложения, сгенерированный box2, поэтому все элементы в box1 располагаются на box2, поэтому c (розовый) всегда ниже a (красный), b (синий); - согласно с
层叠等级结论3Поскольку оба элемента a (красный) и b (синий) находятся в контексте наложения, сгенерированном родительским элементом box1, они сравниваются только внутри, иz-indexДля положительного, то же самое на уровне 7, так что чейz-indexЗначение большое, кто на нем;
Таким образом, порядок отображения: b (синий) > a (красный) > c (розовый).
🌰 Влияние свойств в CSS3 на контекст стека
<style>
.box1 {
opacity: 0.99;
position: relative;
}
.box2 {
position: relative;
}
.a,
.b,
.c,
.d {
position: absolute;
width: 100px;
color: white;
line-height: 100px;
text-align: center;
}
.a {
top: 20px;
left: 20px;
background: red;
z-index: 999;
}
.b {
top: 60px;
left: 60px;
background: lightblue;
z-index: 999;
}
.c {
top: 100px;
left: 100px;
background: pink;
}
.d {
width: 140px;
line-height: 140px;
top: 40px;
left: 40px;
background: orange;
z-index: -1;
}
</style>
<body>
<div class='box1'>
<span class="a">a</span>
<span class="b">b</span>
</div>
<div class='box2'>
<span class="c">c</span>
<span class="d">d</span>
</div>
</body>
проиллюстрировать:Он был введен ранее, устанавливаяopacityКонтексты стекирования также могут быть сформированы, поэтому:
- box1 установлен
opacity, Box1 становится новым контекстом укладки; - Box2 не образует новый слой ламинированного контекста, согласно
层叠等级结论2、3Можно сделать вывод, что все элементы в нем принадлежат корневому контексту стека; - д (оранжевый)
z-indexНегатив относится к уровню 2 в порядке укладки - a (красный), b (синий) находятся на уровне 7,
z-indexтакое же значение вDOM 流Буква b (синяя) сзади закроет букву a (красную). - Родительские элементы box1 и c (розовый) a (красный), b (синий) не установлены
z-indexУровень 6 в порядке укладки, иDOM 流c (розовый) сзади закроет box1 , поэтому c (розовый) всегда находится на a (красный), b (синий) вверху;
Таким образом, порядок отображения следующий: c (розовый) > b (синий) > a (красный) > d (оранжевый)
🚨 Если непрозрачность не установлена:
проиллюстрировать:Видно, что box1 и box2 находятся на шестом уровне порядка укладки.
- Ни одна коробка1, ни Box2 не сформировала новый контекст укладки, поэтому элементы в нем все относятся к контексту укладки корня и напрямую сравниваются;
- a (красный), b (синий) относятся к 7-му уровню,
z-indexтакое же значение вDOM 流Буква b (синяя) сзади закроет букву a (красную). - c (порошок) не установлен
z-indexПринадлежит к уровню 6 в порядке укладки - д (оранжевый)
z-indexНегатив относится к уровню 2 в порядке укладки
Таким образом, порядок отображения: b (синий) > a (красный) > c (розовый) > d (оранжевый)
🌰 Сравните с другими элементами
<style>
.box1 {
width: 100px;
height: 100px;
background-color: lightblue;
}
.box2 {
margin-top: -50px;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
</body>
проиллюстрировать:
- И box1, и box2 принадлежат корневому контексту стека.
- потому что он не установлен
z-indexТаким образом, оба находятся на уровне 6 в порядке стека, наDOM 流box2 в конце перезапишет box1
Таким образом, порядок отображения: box2 > box1
🚨 Вы можете установить box1opacity:
.box1 {
+ opacity: 0.99;
width: 100px;
height: 100px;
background-color: lightblue;
}
Или установите поле 1transform:
.box1 {
+ transform: rotate(15deg);
width: 100px;
height: 100px;
background-color: lightblue;
}
потому что box1 добавляет конкретныйcss3свойства создают контекст стека, согласно层叠等级结论1Элементы, которые создают контексты укладки, всегда накладываются выше других элементов. Box1 создает контекст укладки (официально), поэтому box2 сложен.
Сценарии применения
<style>
.box1 {
float: left;
width: 100px;
height: 100px;
margin-right: -20px;
background-color: lightblue;
}
.box2 {
overflow: hidden;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
</body>
Плавающие блоки выше блочных блоков в соответствии с порядком укладки, поэтому блок 1 имеет приоритет над блоком 2.
Если вы хотите изменить уровень элемента и не хотите использовать позиционирование, вы можете использовать множество других методов.
такие как использованиеopacityБлочные блоки затем формируют контекст стека, в соответствии с层叠等级结论1В это время уровень блочного блока выше уровня плавающего блока, и код выглядит следующим образом:
.box2 {
overflow: hidden;
width: 100px;
height: 100px;
background-color: pink;
+ opacity: 0.99;
}
резюме
Здесь мы можем представить контекст наложения как трехмерное пространство с осью Z. Элементы внутреннего контекста наложения сортируются в соответствии с уровнем наложения, и элементы внутреннего контекста наложения также могут генерировать контексты наложения. родительский контекст наложения, сравните Уровень наложения внутреннего элемента контекста наложения и уровень наложения в основном определяются правилами порядка наложения.
Введите URL для отображения страницы
Для этого классического вопроса интервью вы можете проверить мою другую статью, которая знакомит с соответствующими знаниями о том, как работают браузеры.После понимания этого давайте разберемся с перерисовкой и перекомпоновкой:
Перерисовка и перекомпоновка
до чтенияВведите URL для отображения страницыЯ считаю, что в главе «Процесс рендеринга🍊» этой статьи вы уже должны иметь некоторое представление о перерисовке и перекомпоновке Вот краткое изложение:
- Браузер анализирует HTML в
DOM, который разбирает CSS наCSSOM, DOM и CSSOM объединяются для созданияRender Tree. - имеют
RenderTree, мы знаем стиль всех узлов - Макет (перекомпоновка): Согласно сгенерированному дереву рендеринга, перекомпоновка (
Layout), вычислить геометрическую информацию (положение, размер) узла - Покраска (перерисовка): По геометрической информации, полученной из дерева рендеринга и перекомпоновки, получаются абсолютные пиксели узла
- Дисплей: отправлять пиксели в
GPU, и, наконец, нарисуйте узел на странице в соответствии с вычисленной информацией.
Перекомпоновать
когда
渲染树(Render Tree)Процесс, посредством которого браузер повторно отображает часть или весь документ при изменении размера, структуры (положения) или определенных атрибутов некоторых или всех элементов в документе, называетсяпереплавкаТакже называется перегруппировкой. См. шаг 3 процесса визуализации 🍊.
Этот процесс можно понимать как заполнение всей веб-страницы и повторный рендеринг содержимого один раз. Просто просмотр браузерной перекомпоновки с сенсорной скоростью человеческого глаза ничего не изменит.Если она достаточно медленная, то вы обнаружите, что каждая перекомпоновка будет очищать страницу, а затем начинать с первого пикселя в верхнем левом углу слева направо. Рендеринг по крупицам сверху вниз до последнего пикселя в правом нижнем углу. Каждый рефлоу представляет процесс, просто он его не чувствует.
Действия, вызывающие перекомпоновку:
- первый рендер страницы
- Размер окна браузера изменяется (поскольку перекомпоновка вычисляет положение и размер элементов на основе размера окна просмотра)
- Размер элемента (включая изменения свойств, таких как поля, отступы, толщина границ, ширина, высота и т. д.) или изменения положения
- Меняется содержимое элемента (вводится текст во вводе, меняется количество текста или размер изображения и т.д.)
- Изменение размера шрифта элемента
- добавить или удалитьвидимыйиз
DOMэлемент - активация
CSSпсевдоклассы (например::hover) - запрашивать определенные свойства или вызывать определенные методы
Некоторые общие свойства и методы, которые могут вызвать перекомпоновку:
-
clientWidth,clientHeight,clientTop,clientLeft -
offsetWidth,offsetHeight,offsetTop,offsetLeft -
scrollWidth,scrollHeight,scrollTop,scrollLeft -
scrollIntoView(),scrollIntoViewIfNeeded() -
getComputedStyle()(currentStyle in IE) getBoundingClientRect()scrollTo()
Из-за вычислительной стоимости каждого COLLOWH большинство браузеров оптимизируют процесс отравляющей, путем модификаций очередей и выполняя их в партии.
Тем не менее, вы можете (часто неосознанно) заставляйте промывку очереди и требуют запланированных задач для немедленного выполнения.
Используйте эти свойства, перечисленные выше, или звонитеgetComputedStyle, в ИЕcurrentStyleчтобы получить информацию о макете, чтобы получить последнюю информацию о макете, браузер должен выполнить «ожидающие изменения» в очереди рендеринга и запустить перекомпоновку для расчета и возврата правильного значения на лету.
🚨 И чего многие не знают, так это того, что перерисовка и перекомпоновка на самом деле такие же, какEventloopСвязанный.
- когда
EventloopзаконченныйMicrotasksпотом будет судитьdocumentНужно ли его обновлять, потому что браузер60Hzчастота обновления на16.6msбудет обновлен только один раз. - а затем определить, является ли
resizeилиscrollсобытие, если оно есть, оно вызовет событие, поэтомуresizeа такжеscrollСобытие также по крайней мере16msОн срабатывает только один раз и имеет собственную функцию дросселирования. - Определите, срабатывает ли он
media query - Обновить анимацию и отправить событие
- Определить, есть ли событие полноэкранного режима
- выполнять
requestAnimationFrameПерезвоните - выполнять
IntersectionObserverОбратный вызов, этот метод используется для оценки того, виден элемент или нет.Его можно использовать для ленивой загрузки, но совместимость плохая.Обновить интерфейс - Это то, что можно сделать в одном кадре. Если в кадре есть свободное время, он выполнит
requestIdleCallbackПерезвоните
Перекрасить
Когда внешний вид элемента меняется (например: цвет, фоновый цвет, видимость, контур и т. д.), но макет не меняется (ширина, высота, размер, положение и т. д. остаются неизменными), браузер присваивает новый стиль к элементу и перекрасить его, придает элементу новый вид (вот почемуRedRaw не обязательно вызывает отражение), этот процесс называетсяперерисовать. См. шаг 7 процесса рендеринга 🍊
ЗачемReflow должен вызывать перерисовкуШерстяная ткань? Положение всего узла изменилось, и его свойства внешнего вида должны быть перерисованы!
Общие свойства, вызывающие перерисовку (которые изменяют внешний вид узлов):
-
color,visibility -
border-style,border-radius,text-decoration,outline-color,outline,outline-style,outline-width,box-shadow -
background,background-color,background-image,background-position,background-repeat,background-size
Сравнение влияния на производительность
Доля стоимости флегмы окрашена выше.
Можно сказать, что рефлюкс «запускает целое», иногда даже если рефлюкс одного элемента, его родительский элемент и любые последующие его элементы будут создавать рефлюкс, что потребует огромного количества вычислений.
Современные браузеры оптимизированы для частых перекомпоновок или перерисовок:
Браузер будет поддерживать очередь и помещать в нее все операции, вызывающие перекомпоновку и перерисовку.Если количество задач в очереди или временной интервал достигает порогового значения, браузер очистит очередь и выполнит пакетный процесс, который может превратить несколько перекомпоновок и перерисовок в одну. Браузер немедленно очищает очередь при доступе к следующим свойствам или методам:
-
clientWidth,clientHeight,clientTop,clientLeft -
offsetWidth,offsetHeight,offsetTop,offsetLeft -
scrollWidth,scrollHeight,scrollTop,scrollLeft -
width,height getComputedStyle()getBoundingClientRect()
Поскольку в очереди могут быть операции, которые влияют на возвращаемое значение этих свойств или методов, даже если информация, которую вы хотите получить, не имеет ничего общего с изменениями, вызванными операциями в очереди, браузер принудительно очистит очередь для убедитесь, что полученное значение является наиболее точным.
как избежать
CSS
- избегать использования
tableрасположение, небольшое изменение может привести к тому, что всеtableоплавление (релейаут) - как можно больше
DOMКонец дерева измененийclass. - Избегайте установки нескольких слоев встроенных стилей.
- Применение анимационных эффектов к
positionсобственностьabsoluteилиfixedна элементе. - избегать использования
CSSвыражения (например:calc()). - использовать
visibilityзаменятьdisplay: none, потому что первое приведет только к перерисовке, второе вызовет перекомпоновку (изменение макета) - использовать
transformзаменятьtop:topявляется геометрическим свойством, операцияtopизменит положение узла и вызовет перекомпоновку, используйтеtransform:translate3d(x,0,0)заменятьtopЭто приведет только к перерисовке слоя, но и косвенному запускуGPUускорить - использовать
requestAnimationFrameВ качестве кадра анимации: чем быстрее скорость анимации, тем больше время перекомпоновки.Вышеупомянутая частота обновления браузера60Hz, то есть каждый16.6msобновить один раз, покаrequestAnimationFrame()это с16.6msСкорость обновляется один раз. так доступноrequestAnimationFrame()заменятьsetInterval(). - Избегайте слишком большого количества уровней правил: когда синтаксический анализатор CSS браузера анализирует файлы CSS, он ищет правила CSS справа налево. Слишком большое количество уровней стиля повлияет на эффективность перекомпоновки и перерисовки. Рекомендуется сохранять правила CSS в
3层о. - Установите узел, который часто перерисовывается или перекомпоновывается, как слой: слой может препятствовать тому, чтобы поведение рендеринга этого узла влияло на другие узлы. Например для
videoтег, браузер автоматически превратит узел в слой. Есть много способов установить узлы как слои, мы можем перейтиwill-change,video 标签,iframe标签для создания нового слоя
🚨 Поскольку в браузере используется гибкий макет,Render TreeВычисление обычно нужно пройти только один раз, ноtableза исключением их внутренних элементов, которые могут потребовать нескольких вычислений, обычно занимающих в 3 раза больше времени, чем эквивалентные элементы, поэтому вам следует избегать использованияtableОдна из причин макета
🚨 подписывайтесьtransformТакой же,opacity,filtersЭти свойства также будут использоватьсяcss3硬件加速(GPU加速), чтобы эти анимации не вызывали перерисовки перерисовки
Яма аппаратного ускорения css3:
- Если вы используете аппаратное ускорение CSS3 для слишком большого количества элементов, это приведет к большому объему памяти и проблемам с производительностью.
- Рендеринг шрифтов на графическом процессоре сделает сглаживание неэффективным. Это связано с тем, что алгоритмы GPU и CPU различаются. Поэтому, если вы не отключите аппаратное ускорение в конце анимации, произойдет размытие шрифта.
JavaScript
- Избегайте частых манипуляций со стилями, лучше всего переписать их все сразу
styleсвойства, вы можете использоватьcssText,classListили непосредственно изменитьclassName
const container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.padding = '5px'
использоватьcssText:
container.style.cssText = 'width: 100px; height: 200px; padding: 5px;';
использоватьclassName:
<style>
.basic_style {
width: 100px;
height: 200px;
padding: 5px;
}
</style>
<script>
container.className = 'basic_style';
</script>
использоватьclassList:
<script>
container.classList.add('basic_style')
</script>
Первый запускает изменение дерева рендеринга каждый раз, когда он работает в одиночку, что приводит к соответствующему процессу перекомпоновки и перерисовки.
После слияния мы отправили сразу все изменения и решили это запросом стиля.
- Вы также можете сначала установить элемент
display: none, и отображать его после завершения операции. Потому чтоdisplayсобственностьnoneвыполняется на элементахDOMОперация не вызовет перекомпоновку и перерисовку, но создаст две перерисовки при отображении и скрытии узлов.
function appendDataToElement(appendToElement, data) {
let li;
for (let i = 0; i < data.length; i++) {
li = document.createElement('li');
li.textContent = 'text';
appendToElement.appendChild(li);
}
}
const ul = document.getElementById('list');
appendDataToElement(ul, data);
Если мы сделаем это напрямую, это приведет к тому, что браузер один раз перестроится, потому что каждый раз в цикле вставляется новый узел.
Оптимизировано:
function appendDataToElement(appendToElement, data) {
let li;
for (let i = 0; i < data.length; i++) {
li = document.createElement('li');
li.textContent = 'text';
appendToElement.appendChild(li);
}
}
const ul = document.getElementById('list');
ul.style.display = 'none';
appendDataToElement(ul, data);
ul.style.display = 'block';
- Избегайте частых операций
DOM,СоздаватьdocumentFragment, на него распространяются всеDOMоперацию и, наконец, добавьте ее в документ.
Приведенный выше код оптимизирован:
const ul = document.getElementById('list');
const fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
ul.appendChild(fragment);
- Используйте абсолютное позиционирование для элементов со сложной анимацией, чтобы они не попадали в поток документа, иначе родительский элемент и последующие элементы будут следовать за движением во время движения анимации и вызывать частые перекомпоновки.
- Избегайте частого чтения свойств, которые вызовут перекомпоновку/перерисовку, и если вам действительно нужно использовать их несколько раз, кэшируйте их в переменной.
for(let i = 0; i < 1000; i++) {
// 每次循环获取 offsetTop 会导致回流,因为需要去获取正确的值
console.log(document.querySelector('.test').style.offsetTop)
}
Вы должны использовать переменную вне цикла, чтобы хранить что-то, что не меняетсяDOMЗначения карты:
const offsetTop = document.querySelector('.test').style.offsetTop;
for(let i = 0; i < 1000; i++) {
console.log(offsetTop);
}
резюме
- Если положение элемента изменится, то он перекомпонуется, например, изменится размер окна, размер шрифта или положение элемента, что приведет к тому, что окружающие элементы изменят свое прежнее положение, а перерисовка приведет не к изменению положения, а изменить только фон на предыдущей позиции, цвет и т.д.;
- Перекомпоновка неизбежно вызовет перерисовку, а перерисовка не обязательно приведет к перерисовке.
- Переплавка дороже, чем перекраска.
Дроссельная защита от сотрясений
Функция подавления сотрясений состоит в том, чтобы предотвратить частые вызовы метода.
<div>没有防抖的input: <input id="unDebounce" /></div>
<script>
//模拟一段ajax请求
function ajax(content) {
console.log('ajax request ' + content)
}
let inputa = document.getElementById('unDebounce')
inputa.addEventListener('keyup', function (e) {
ajax(e.target.value)
})
</script>
Как видите, пока мы нажимаем на клавиатуру, этот запрос ajax будет запущен. Это не только пустая трата ресурсов с точки зрения ресурсов, но и в практических приложениях пользователи будут запрашивать только после вывода полных символов.
Функция debounce (дебаунс)
Обратный вызов выполняется через n секунд после запуска события, и если он снова запускается в течение этих n секунд, таймер переустанавливается.
Идеи ✨:
Перед выполнением функции setTimeout очистите таймер с помощью clearTimeout, отмените блок кода задержки и убедитесь, что он выполняется только один раз.
После добавления стабилизатора в приведенном выше примере давайте посмотрим на эффект:
<div>防抖后的input: <input id="debounce" /></div>
<script>
//模拟一段ajax请求
function ajax(content) {
console.log('ajax request ' + content)
}
function debounce(fun, delay) {
return function (args) {
let that = this
let _args = args
clearTimeout(fun.id)
fun.id = setTimeout(function () {
fun.call(that, _args)
}, delay)
}
}
let inputb = document.getElementById('debounce')
let debounceAjax = debounce(ajax, 500)
inputb.addEventListener('keyup', function (e) {
debounceAjax(e.target.value)
})
</script>
Видно, что после того, как мы добавили антишейк, при частом вводе запрос не будет отправляться, а функция будет выполняться только тогда, когда у вас нет ввода в течение заданного интервала. Если вы перестанете печатать, а затем снова введете в течение указанного интервала времени, время будет запущено заново.
функция дроссельной заслонки
Предусмотрено, что функция может срабатывать только один раз в единицу времени. Если функция запускается несколько раз в течение этого времени, только один из них вступит в силу.
Идеи ✨:
Основная идея состоит в том, чтобы использовать оценку временной метки, а разница во времени между каждой оценкой вызова и последним вызовом определяет, нужен ли вызов.
<div>节流后的input: <input id="throttle" /></div>
<script>
function throttle(fun, delay) {
let last, deferTimer
return function (args) {
let that = this
let _args = arguments
let now = +new Date()
if (last && now < last + delay) {
clearTimeout(deferTimer)
deferTimer = setTimeout(function () {
last = now
fun.apply(that, _args)
}, delay)
}else {
last = now
fun.apply(that,_args)
}
}
}
let throttleAjax = throttle(ajax, 1000)
let inputc = document.getElementById('throttle')
inputc.addEventListener('keyup', function(e) {
throttleAjax(e.target.value)
})
</script>
Видно, что когда мы продолжаем вводить, ajax будет выполняться каждую 1 секунду в соответствии с установленным нами временем.
просто понять
- Дросселирование функции - это скорость стрельбы в игре fps.Даже если вы продолжаете нажимать мышь, чтобы стрелять, она будет стрелять только пулями в пределах указанной скорости стрельбы.
- Функция антивстряска - это когда герой возвращается в город, (если он не вернулся в город) снова нажимаем кнопку возврата, и время возврата будет пересчитано
Сценарии применения
Отказаться
- Поиск Поиск Lenovo, когда пользователи постоянно вводят значения, использует защиту от сотрясений для экономии ресурсов запросов. (Пользователь всегда будет вводить новый триггер, и триггер будет задержан, когда он остановится)
- Когда окно вызывает изменение размера, постоянное изменение размера окна браузера будет постоянно запускать это событие, а использование защиты от сотрясений заставит его запускаться только один раз.
- Частые лайки и дизлайки, поэтому результат последней операции нужно получить и отправить на сервер
дроссель
- Мышь непрерывно нажимается для запуска, mousedown (фиксируется только один раз в единицу времени)
- Слушайте события прокрутки, например, нужно ли скользить вниз, чтобы автоматически загрузить больше, использовать дроссель, чтобы судить
наконец
Если резюме неверно, добро пожаловать на исправление обсуждения!
Справочная статья 📜
❤️Разберитесь в сценариях дросселирования, защиты от встряхивания и использования JS за 7 минут.
❤️10 минут, чтобы понять принципы BFC
❤️Тщательно понимать контекст стека CSS, уровень стека, порядок стека, z-индекс
❤️Важные концепции каскадирования в CSS
❤️Браузерная перекомпоновка и перерисовка