Модель отображения. Часть 1
М охов Олег
Р азработчик интерфейсов
Всё есть квадраты прямоугольники
Визуальная модель форматирования
Что это такое?
Алгоритм, который используется для обработки документа и отображения его визуального представления. Каждый элемент документа трансформируется 0, 1 или более box'ов в соответствие с боксовой моделью CSS.
Визуальная модель форматирования определяет как страница будет отрендерена.
Положение бокса
размер бокса: определен ли, ограничен или никак не задан
тип бокса: inline, block, и т.п
положение относительно других элементов в дереве: соседей или детей
размер и положение viewport'а
внутренние пропорции (картинки, видео)
схема позиционирования: поток, float или абсолютная
Типы боксов
Блочного уровня (это не только display: block)
Строчного (inline) уровня
Боксы блочного уровня
Элемент рендерится как блок (близкая аналогия – параграф)
Элементы блочного уровня выстраиваются сверху внизу
Элемент блочного уровня участвует в блочном контексте форматирования
Элемент блочного уровня генерирует главный бокс блочного уровня (principal block-level box) и в некоторых случаях дополнительные (например list-item генерирует бокс для буллета)
Участвующий в блочном контексте форматирования элемент может создать вокруг себя анонимный блочный бокс
Анонимные боксы
Некий текст
с параграфом
внутри
и снова текст.
Некий текст с параграфом внутри
и снова текст.
Боксы блочного уровня по-умолчанию
p
div
h1, h2, h3, h4, h5, h6
ol, ul
pre
address
blockquote
dl
fieldset
form
hr
table
display: block, list-item, table, flex...
Математика block элементов
margin-left + /* css */
border-left + /* css */
padding-left + /* css */
content-width + /* ≠ width (css) */
padding-right + /* css */
border-right + /* css */
margin-right /* css */
= width содержащего блока
box-sizing
CSS свойство, которое применяется для изменения алгоритма расчета ширины и высоты элемента.
margin + border + padding + width = width содержащего блока при content-box
margin + border + width = width содержащего блока при padding-box
margin + width = width содержащего блока при border-box
margin + border + padding + height ≠ height содержащего блока
Ширина и высота
div {
width: 200px;
height: 200px;
}
Ширина и высота
div {
width: 400px;
height: 200px;
}
Ширина и высота
div {
width: 400px;
height: 100px;
}
Ширина и высота
div {
width: 400px;
height: 100px;
}
div div {
}
Вместо тепла - зелень стекла Вместо огня - дым
Ширина и высота
div {
width: 400px;
height: 100px;
}
div div {
margin: 0 20px;
}
Из сетки календаря выхвачен день
Ширина и высота
div {
width: 400px;
height: 100px;
}
div div {
margin: 0 20px;
}
Красное солнце сгорает дотла
День догорает с ним,
На пылающий город падает тень.
Ширина и высота
div {
width: 400px;
height: 100px;
}
div div {
height: 100px;
margin: 0 20px;
}
Перемен! - требуют наши сердца.
Перемен! - требуют наши глаза
Ширина и высота
div {
width: 400px;
height: 100px;
}
div div {
height: 100px;
margin: 0 20px;
width: 800px;
}
В нашем смехе и в наших слезах, и в пульсации вен:
«Перемен! Мы ждем перемен!»
Ширина и высота
div {
height: 100px;
}
div div {
height: 100px;
margin: 0 20px;
max-width: 800px;
}
Электрический свет продолжает наш день,
И коробка от спичек пуста,
Но на кухне синим цветком горит газ.
margin/padding
div {
width: 800px;
}
div div {
margin: 20px;
padding: 50px;
}
Сигареты в руках, чай на столе - эта схема проста,
И больше нет ничего, все находится в нас.
margin/padding
margin/padding
top right bottom left
margin: 2px 30px 400px 5000px;
margin: 2px 30px 400px /* 30px */;
margin: 2px 30px /* 2px 30px */;
margin: 2px /* 2px 2px 2px */;
margin/padding
margin: 2px 30px 400px 5000px;
margin-top: 2px;
margin-right: 30px;
margin-bottom: 400px;
margin-left: 5000px;
Процентные значения
ширина, заданная в процентах, считается относительно ширины содержащего блока
высота, заданная в процентах, считается относительно высоты содержащего блока, но только если она задана явно
margin-left/right и padding-left/right, заданная в процентах, считаются относительно ширины содержащего блока
высота содержащего блока (если не задана) = сумма места, занимаемого его детьми
margin-top/bottom и padding-top/bottom, заданная в процентах, считаются относительно ширины содержащего блока
div div {
height: 50%;
width: 50%;
}
Перемен требуют наши сердца
Перемен требуют наши глаза
div {
height: 400px;
}
div div {
height: 50%;
width: 50%;
}
В нашем смехе и в наших слезах
И в пульсации вен
Перемен, мы ждём перемен
div div {
margin: 10%;
padding: 10%;
}
Мы не можем похвастаться мудростью глаз
И умелыми жестами рук
border
border: <размер> <тип> <цвет>;
border-left: <размер> <тип> <цвет>;
border-width: <размер> <размер> <размер> <размер>;
border-type: <тип> <тип> <тип> <тип>;
border-color: <цвет> <цвет> <цвет> <цвет>;
border-left-width: <размер>;
border-left-type: <тип>;
border-left-color: <цвет>;
border
div {
border: 20px dotted blue;
}
Нам не нужно всё это, чтобы друг друга понять
Сигареты в руках, чай на столе
border
div {
border: 20px dashed blue;
}
Так замыкается круг
И вдруг нам становится страшно что-то менят
border
div {
border: 20px solid blue;
}
Перемен требуют наши сердца
Перемен требуют наши глаза
border
div {
border-width: 20px;
border-style: solid;
border-color: blue red;
}
В нашем смехе и в наших слезах
И в пульсации вен
border
div {
border-width: 20px 40px;
border-style: solid dashed dotted;
border-color: blue red;
}
Перемен, мы ждём перемен
Немного о математике блочных элементов
margin + border + padding + width = width содержащего блока
margin + width = width содержащего блока - border - padding
border/padding: либо заданы, либо auto = 0
если margin-left не задан, значит он равен 0, если margin-left задан в auto, то он вычисляется
width либо задан, либо вычисляется
margin-right вычисляется всегда, если заданы width и margin-right
margin + width = width содержащего блока - border - padding
.container { width: 666px; background: red; padding: 10px 0; }
.inner { background: rgba(0, 0, 255, 0.5) }
margin + width = width содержащего блока - border - padding
.container { width: 666px; background: red; padding: 10px 0; }
.inner { background: rgba(0, 0, 255, 0.5) }
Теплое место, но улицы ждут отпечатков наших ног. Звездная пыль - на сапогах.
Мягкое кресло, клетчатый плед,
Не нажатый вовремя курок.
Солнечный день - в ослепительных снах..
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { margin-left: 500px; }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { margin-left: 500px; margin-right: 66px; }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { width: 300px; }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { width: 300px; margin-right: 0; }
если margin-left не задан, значит он равен 0, если margin-left задан в auto, то он вычисляется
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { width: 300px; margin-left: auto }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { width: 300px; margin: 0 auto }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { margin-right: -100px; }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { margin-right: -100px; margin-left: -100px; }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { width: 50%; margin-left: -100px; }
margin + width = width содержащего блока - border - padding
.wrapper { width: 666px; }
.inner { width: 50%; margin-left: auto; margin-right: -100px; }
Схлопывание отступов
.first { margin-bottom: 30px; }
.second { margin-top: 60px; }
Блоки
И есть чем платить, но я не хочу
Ожидание
И есть чем платить, но я не хочу
Реальность
И есть чем платить, но я не хочу
.inner { margin-top: 30px; }
Блоки
Я никому не хочу ставить ногу на грудь.
Ожидание
Я никому не хочу ставить ногу на грудь.
Реальность
Я никому не хочу ставить ногу на грудь.
Высчитывание результирующего margin'а
Если у двух блочных элементов, принадлежащих одному контексту форматирования, пересекаются margin'ы, то
Берутся максимальный и минимальный среди всех margin'ов
Если максимальный < 0, то максимум — 0. То же самое с минимумом
Результирующий margin = max + min
.first { margin-bottom: 60px; }
.second { margin-top: 100px; }
Я хотел бы остаться с тобой,
Просто остаться с тобой,
Но высокая в небе звезда зовет меня в путь.
Я хотел бы остаться с тобой,
Просто остаться с тобой,
Но высокая в небе звезда зовет меня в путь.
.first { margin-bottom: 60px; }
.second { margin-top: -60px; }
Группа крови - на рукаве,
Мой порядковый номер - на рукаве,
Группа крови - на рукаве,
Мой порядковый номер - на рукаве,
.first { margin-bottom: 60px; }
.second { margin-top: -80px; }
Пожелай мне удачи в бою, пожелай мне
Не остаться в этой траве, не остаться в этой траве
Пожелай мне удачи в бою, пожелай мне
Не остаться в этой траве, не остаться в этой траве
Боксы инлайн уровня
Элемент рендерится как строка
Элементы строчного уровня выстраиваются слева направо сверху вниз
Элемент инлайн уровня участвует в инлайн контексте форматирования
Элемент инлайн уровня генерирует бокс(ы) инлайн уровня
Участвующий в инлайн контексте форматирования элемент может создать вокруг себя анонимный инлайн бокс
Some inline
text followed
by a paragraph
followed by
more inline text.
Some inline text followed by a span followed by more inline text.
Математика инлайн элементов
Математика inline элементов
не реагирует на ширину и высоту
не реагирует на вертикальные margin'ы
padding'и не затрагивают высоту строки
.wrapper { width: 666px; }
Мы хотим видеть дальше, чем окна дома напротив, мы хотим жить, мы живучи, как кошки.
Мы хотим видеть дальше, чем окна дома напротив, мы хотим жить, мы живучи, как кошки.
Боксы инлайн уровня по-умолчанию
b, big, i, small, tt
abbr, acronym, cite, code, dfn, em, kbd, strong, samp, var
a, bdo, br, img, map, object, q, script, span, sub, sup
button, input, label, select, textarea
display: inline, inline-block, inline-table
Математика inline-block элементов
реагирует на ширину и высоту
реагирует на вертикальные margin'ы
padding'и затрагивают высоту строки
создаёт внутри себя новый блочный контекст
.wrapper { width: 666px; }
.inner { }
И вот мы пришли заявить о своих правах: "Да!"
Слышишь шелест плащей - это мы... Дальше действовать будем мы!