Модель отображения

Часть 1

Кристина Ильенко

Всё есть прямоугольники

Are You Serious?

Как видит человек:

Как видит браузер:

Каждый прямоугольник содержит внутри себя еще несколько прямоугольников

5 важных свойств элемента

  • width – ширина
  • height – высота
  • padding – внутренний отступ
  • border – граница
  • margin – внешний отступ

Давайте поймем, что все 5 свойств прямоугольника

  • width – ширина
  • height – высота
  • padding – внутренний отступ
  • border – граница
  • margin – внешний отступ

можно разделить на 3 зоны. И найдем аналогии

3 разные зоны:

Зона 1: высота (height) и ширина (width) фактического элемента

Зона 1 – дом

3 разные зоны:

Зона 2: внутренняя область вокруг элемента (padding) и граница (border)

Зона 2 – двор и забор

3 разные зоны:

Зона 3: пустое пространство, отделяющее элемент от соседних (margin)

Зона 3 – деревья между соседними дворами

Боксовая модель CSS

margin border padding content

Content-box

content

Padding-box

padding content

Border-box

border padding content

Margin-box

margin border padding content
margin content
margin content

Модель визуального форматирования

Это алгоритм, который обрабатывает документ и отображает его на экране устройства.

Модель визуального форматирования задаёт трансформацию каждого элемента в документе и создаёт ноль, один или несколько боксов, согласно боксовой модели CSS

MDN Web Docs

На положение боксов на странице влияет
размер бокса
:

  • точно задан
  • вычисляется

На положение боксов на странице влияет
тип бокса
:

  • block (блочный)
  • inline (строчный)

На положение боксов на странице влияет
схема позиционирования

Это алгоритм, используемый движком CSS для расположения блоков на макете

На положение боксов на странице влияет
схема позиционирования

    Виды:
  • Нормальный поток
  • Схема float
  • Схема абсолютного позиционирования

На положение боксов на странице влияют
отношения между элементами DOM:
дочерними и соседними

На положение боксов на странице влияют
размеры и расположение окна просмотра (viewport)

Viewport - это видимая пользователю область веб-страницы, то, что может увидеть пользователь, не прибегая к прокрутке.

На положение боксов на странице влияют
внутренние размеры содержащихся изображений

Типы боксов

Боксы блочного уровня

Особенности

Каждый элемент блочного уровня генерирует один главный бокс блочного уровня, который

  • содержит все дочерние блоки
  • участвует в позиционировании элемента

Боксы блочного уровня

Особенности

Но некоторые элементы кроме главного бокса генерируют дополнительные, например

            
I will display as a list item
.fake-list { display: list-item; list-style-position: inside; }
I will display as a list item

Боксы блочного уровня

Блочные элементы по умолчанию:

p div pre ol ul dl
h1 h2 h3 h4 h5 h6
address blockquote fieldset form hr table

Боксы блочного уровня

Необходимое CSS-свойство

            
Говорят, что элемент является боксом блочного уровня, когда:
display: block; /* а так же list-item, table, flex, ... */
            
        

Почему значение flex,
а элемент блочный?

Свойство display

Согласно спецификации CSS Display 3,
свойство display отвечает за:
  • Внешнее поведение элемента — т.е. в каком контексте форматирования он сам участвует;
  • Внутреннее поведение элемента— т.е. какой контекст форматирования действует в нем самом

Почему значение flex, а элемент блочный?

Элемент с display: flex
участвует в блочном контексте форматирования, а для своих дочерних элементов он сам создает
гибкий (flex) контекст форматирования,
о котором расскажут в следующих лекциях

Боксы блочного уровня

Занимают всю доступную ширину и выстраиваются сверху вниз

Боксы блочного уровня

Участвуют в блочном контексте форматирования

Блочный контекст форматирования

Это часть визуального CSS-рендеринга веб-страницы

В нем действуют правила, изложенные в блочной модели CSS, которая определяет, как поля, границы и отступы элемента взаимодействуют с другими блоками в том же контексте.

MDN Web Docs

Боксы блочного уровня

Могут создавать вокруг себя анонимные блочные боксы

Анонимные блочные боксы

Что это?

В случае смешанного контента алгоритм визуального форматирования добавляет
дополнительную обёртку
для текстового содержимого — анонимный бокс.

Анонимные блочные боксы

Пример

            
Какой-то текст

с параграфом внутри

и текстом в конце.
Какой-то текст

с параграфом внутри

и текстом в конце.

Анонимные блочные боксы

Особенности

  • Анонимный блок не связан ни с одним элементом
  • Анонимный блок не имеет названия, поэтому к нему нельзя применить CSS-стили для оформления
  • Анонимные боксы наследуют свойства окружающего блока, а не наследуемые свойства принимают первоначальное значение.

Содержащий блок

Почему это важно?

На размеры и положение элемента часто влияет его содержащий блок

Определение содержащего блока элемента

полностью зависит от значения свойства position

В этой лекции мы рассматриваем случай,
когда position не задан (используется
его дефолтное значение),
и под содержащим блоком понимаем
родительский блок элемента

Математика блочных элементов

Ширина и высота

                    
div {
    width: 200px;
    height: 200px;
}
                    
                
                    
div {
    width: 20%;
    height: 10%;
}
                    
                
                    
div {
    width: 5em;
    height: 5em;
}
                    
                

Ширина и высота

                
Yeah, you can be the greatest,
you can be the best
.wrapper { width: 400px; height: 100px; }
Yeah, you can be the greatest,
you can be the best

Ширина и высота

                    
You can be the King Kong bangin'
on your chest
.wrapper { width: 400px; height: 100px; } .inner { margin: 0 20px; }
You can be the King Kong bangin' on your chest

Ширина и высота

                    
You can beat the world, you can win the war
You can talk to God, go bangin' on his door
You can throw your hands up, you can beat the clock
.wrapper { width: 400px; height: 100px; } .inner { margin: 0 20px; }
You can beat the world, you can win the war
You can talk to God, go bangin' on his door
You can throw your hands up, you can beat the clock

Ширина и высота

                    
You can move a mountain, you can break rocks
Some will call that practice, some will call that luck
But either way your going to the history books
.wrapper { width: 400px; height: 100px; } .inner { height: 100px; margin: 0 20px; }
You can move a mountain, you can break rocks
Some will call that practice, some will call that luck
But either way your going to the history books

Ширина и высота

                
Standing in the Hall of Fame
And the world's gonna know your name
'Cause you burn with the brightest flame
.wrapper { width: 500px; height: 100px; } .inner { width: 600px; height: 100px; margin: 0 20px; }
Standing in the Hall of Fame
And the world's gonna know your name
'Cause you burn with the brightest flame

При заданных фиксированных размерах элемент не будет менять свои размеры,
но при этом вложенные элементы могут из него выпадать

margin и padding

margin: 20px 10px 5px 34px;
margin-top: 20px;
margin-right: 10px;
margin-bottom: 5px;
margin-left: 34px;

Аналогично для 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  */;
        

Аналогично для padding

Процентные значения

Ширина, заданная в процентах, считается относительно ширины содержащего блока

            
.wrapper {
    width: 816px;
    background: #3af4d5;
}
.inner {
    width: 50%;
}
            
        
You can go the distance, you can run a mile
You can walk straight through hell with a smile

Высота, заданная в процентах, считается относительно высоты содержащего блока, но только если высота содержащего блока задана явно

                
.wrapper {
    width: 470px;
    height: 400px;
}
.inner {
    height: 50%;
    width: 60%;
}
                
            
You can be a hero, you can get the gold
Breaking all the records they thought
would never be broke

Высота, заданная в процентах, считается относительно высоты содержащего блока, но только если высота содержащего блока задана явно

                
.wrapper {
    width: 457px;
}
.inner {
    height: 50%;
    width: 70%;
}
                
            
Yeah, do it for your people,
do it for your pride
How are you ever gonna
know if you never even try?
  • margin-left/right и padding-left/right, заданные в процентах, считаются относительно ширины содержащего блока
  • margin-top/bottom и padding-top/bottom, заданные в процентах, считаются относительно ширины содержащего блока

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;
}

        
Do it for your country, do it for your name

border


div {
    border: 20px dashed blue;
}

        
'Cause there's gonna be a day, when you're

border


div {
    border: 20px solid blue;
}

        
Standing in the Hall of Fame

border


div {
    border-width: 20px;
    border-style: solid;
    border-color: blue red;
}

        
And the world's gonna know your name

border


div {
    border-width: 30px 20px;
    border-style: solid dotted;
    border-color: blue red;
}

        
'Cause you burn with the brightest flame

Перерыв

Пример #1

                
.parent {
    width: 500px;
    height: 500px;
    border:  10px solid #3af4d5;
}

.child {
    width: 100%;
    height: 100px;
    margin: 2em auto;
    background-color: #f70044;
}
                
            

Parent

Child

Пример #2

                
.parent {
    width: 500px;
    height: 500px;
    border: 10px solid #3af4d5;
}

.child {
    width: 100%;
    height: 100px;
    margin: 2em auto;
    background-color: #f70044;
    /* добавим границу */
    border: 10px solid #5b6dcd;
    /* и внутренний отступ: */
    padding: 5px;
}
                
            

Parent

Child

Что происходит?

По умолчанию в блочной модели CSS выставленная ширина и высота применяются только к content-box элемента

Если элементу дополнительно заданы border или padding, то их значения добавятся к ширине и высоте

Если размер содержащего элемента явно заданы,
а сумма размеров border, padding и размеров элемента превышают их, элемент не поместится в содержащем

MDN Web Docs

Как быть?

Правильно использовать свойство
box-sizing

Какие варианты использования?

  • content-box (по умолчанию)
  • border-box

box-sizing: content-box

Ширина и высота, которую устанавливаем элементу, применяется к его content-box

Если задаем элементу дополнительно border или padding с ненулевыми размерами, то эти значения будут добавлены к заданным выше

Поэтому размеры элемента при рендеринге станут больше, чем указанные первоначально

box-sizing: border-box

При рендеринге браузер будет учитывать заданные значения border или padding так, чтобы не выходить за указанные значения высоты и ширины

Пример #3

                
.parent {
    width: 500px;
    height: 500px;
    border: 10px solid #3af4d5;
}

.child {
    width: 100%;
    height: 100px;
    margin: 2em auto;
    background-color: #f70044;
    /* content-box -> border-box */
    box-sizing: border-box;
    border: 10px solid #5b6dcd;
    padding: 5px;
}
                
            

Parent

Child

Нетривиальная математика
блочных элементов

Пример


.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}


.inner {
    width: 400px;
    margin: 0 auto;
    background: #00bbf0;
}

        
And you’ll be on the walls of the Hall of Fame

Что сделал браузер?

Браузер самостоятельно посчитал отступы

Нетривиальная математика блочных элементов

  • Пусть box-sizing: content-box
  • margin + border + padding + width = width содержащего блока
  • margin + width = width содержащего блока - border - padding

При этом border/padding: либо заданы, либо auto, т.е.

Значит значения в правой части формулы известны

Браузеру остается вычислить margin-left, margin-right и ширину блока

Пример #1

Не задано 1 значение – margin-left

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    width: 300px;
    margin-right: 300px;
}
            
        
margin-left = 0, margin-right вычисляется
margin-left + margin-right + width = width с.б. - border - padding
0 + [366px] + 300px = 666px

Пример #2

Не задано 1 значение – margin-right:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-left: 100px;
    width: 300px;
}
            
        
margin-right вычисляется
margin-left + margin-right + width = width с.б. - border - padding
100px + [266px] + 300px = 666px

Пример #3

Не задано 1 значение – width:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-left: 100px;
    margin-right: 200px;
}
            
        
width вычисляется
margin-left + margin-right + width = width с.б. - border - padding
100px + 200px + [366px] = 666px

Пример #4

Не задано 2 значения – margin-left и margin-right:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    width: 300px;
}
            
        
margin-left равен 0, margin-right вычисляется
margin-left + margin-right + width = width с.б. - border - padding
0 + [366px] + 300px = 666px

Пример #5

Не задано 2 значения – margin-left и width:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-right: 200px;
}
            
        
margin-left равен 0, width вычисляется
margin-left + margin-right + width = width с.б. - border - padding
0 + 200px + [466px]= 666px

Пример #6

Не задано 2 значения – margin-right и width:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-left: 100px;
}
            
        
margin-right равен 0, width вычисляется
margin-left + margin-right + width = width с.б. - border - padding
100px + 0 + [566px] = 666px

Пример #7

Заданы margin-left: auto и width:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-left: auto;
    width: 300px;
}
            
        
margin-right равен 0, margin-left вычисляется
margin-left + margin-right + width = width с.б. - border - padding
[366px] + 0 + 300px = 666px

Пример #8

Заданы margin-right: auto и width:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-right: auto;
    width: 300px;
}
            
        
margin-left равен 0, margin-right вычисляется
margin-left + margin-right + width = width с.б. - border - padding
0 + [366px] + 300px = 666px

Пример #9

Заданы margin-right: auto, margin-left: auto и width:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin: 0 auto;
    width: 300px;
}
            
        
расчетное пространство распределяется равномерно
margin-left + margin-right + width = width с.б. - border - padding
[183px] + [183px] + 300px = 666px

Пример #10

Задан любой из margin в auto, width не задана:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-left: auto;
}
            
        
оба margin = 0, width вычисляется
margin-left + margin-right + width = width с.б. - border - padding
0 + 0 + [666px] = 666px

Пример #11

Заданы все 3 значения:

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
    margin-left: 100px;
    margin-right: 300px;
    width: 300px;
}
            
        
пересчитываем margin-right
margin-left + margin-right + width = width с.б. - border - padding
100px + [266px] + 300px = 666px

Пример #12

Не задано ни одно из всех 3 значений

            
.wrapper {
    width: 666px;
    background: #3af4d5;
    padding: 10px 0;
}
            
            
.inner {
    height: 50px;
    background: #00bbf0;
}
            
        
margin-left = margin-right = 0, width вычисляется
margin-left + margin-right + width = width с.б. - border - padding
0 + 0 + [666px] = 666px

Пример #13 (Самостоятельный)

Заданы margin-left: auto и width:

            
.wrapper {
    width: 666px;
    padding: 10px 0;
}
            
            
.inner {
    width: 500px;
    margin-left: auto;
}
            
        
margin-left + margin-right + width = width с.б. - border - padding
margin-right равен 0, margin-left вычисляется
[166px] + 0 + 500px = 666px

Как браузер это делает?

margin-left + margin-right + width = width содержащего блока - border - padding

  • Если не задано 1 значение:
    1) Если не задан margin-left, он равен 0, margin-right вычисляется
    2) Если не задан margin-right, он вычисляется
    3) Если не задана width, она вычисляется
  • Если не задано 2 значения:
    1) Если не заданы margin-left и margin-right, то margin-left равен 0, margin-right вычисляется
    2) Если не заданы margin-left и width, то margin-left равен 0, width вычисляется
    3) Если не заданы margin-right и width, то margin-right равен 0, width вычисляется

Как браузер это делает?

margin + width = width содержащего блока - border - padding

  • Если задано что-то в значении auto и width:
    1) Если margin-left: auto, то margin-right = 0, margin-left вычисляется
    2) Если margin-right: auto, то margin-left = 0, margin-right вычисляется
    3) Если оба margin заданы в auto, то расчетное пространство распределяется равномерно
  • Если задано что-то в значении auto и не задана width:
    Если любой из margin в auto, то оба margin 0, width вычисляется
  • Если заданы все 3 значения:
    Пересчитываем margin-right
  • Если не заданы все 3 значения:
    margin-left = margin-right = 0, width вычисляется

Схлопывание отступов

MDN Web Docs

Пример


.first { margin-bottom: 30px; }


.second { margin-top: 60px; }

        

Блоки

Be students, be teachers
Be politicians, be preachers

Ожидание

Be students, be teachers
Be politicians, be preachers

Реальность

Be students, be teachers
Be politicians, be preachers
Произошло схлопывание
внешних "пересекающихся" отступов
элементов-братьев

Высчитывание результирующего margin'а

Если у двух блочных элементов пересекаются margin'ы, то
  1. Берутся максимальный и минимальный среди всех margin'ов
  2. Если максимальный < 0, то максимум — 0
  3. Если минимальный > 0, то минимум — 0.
  4. Результирующий margin = max + min
Если у двух блочных элементов пересекаются margin'ы, то
если максимальный < 0, то max = 0, а в нашем случае max = 100px
если минимальный > 0, то min = 0, тогда в нашем случае min = 0
total margin = max + min, в нашем случае 100px + 0 = 100px

.first { margin-bottom: 60px; }
.second { margin-top: 100px; }

        
Be believers, be leaders,
Be astronauts, be champions,
Be believers, be leaders,
Be astronauts, be champions,
Если у двух блочных элементов пересекаются margin'ы, то
если максимальный < 0, то max = 0, а в нашем случае max = 60px
если минимальный > 0, то min = 0, а в нашем случае min = -60px
total margin = max + min, в нашем случае 60px + (-60px) = 0

.first { margin-bottom: 60px; }
.second { margin-top: -60px; }

        
Be truth seekers.
Standing in the hall of fame,
Be truth seekers.
Standing in the hall of fame,
Если у двух блочных элементов пересекаются margin'ы, то
если максимальный < 0, то max = 0, а в нашем случае max = 60px
если минимальный > 0, то min = 0, а в нашем случае min = -80px
total margin = max + min, в нашем случае 60px + (-80px) = -20px

.first { margin-bottom: 60px; }
.second { margin-top: -80px; }

        
And the world's gonna know your name,
Cause you burn with the brightest flame
And the world's gonna know your name,
Cause you burn with the brightest flame

Боксы строчного уровня (inline)

Боксы строчного уровня

Строчные элементы генерируют
бокс(ы) строчного уровня

Боксы строчного уровня

Строчные элементы по умолчанию:

b big i small textarea abbr
acronym cite code strong img q
span button sub sup input label

Боксы строчного уровня

Необходимое CSS-свойство

            
Говорят, что элемент является боксом строчного уровня, когда:
display: inline; /* а так же inline-block, inline-table,
                 inline-flex, ... */
            
        

Боксы строчного уровня

Особенности

Выглядят как строки

Боксы строчного уровня

Особенности

Выстраиваются слева направо, сверху вниз

Боксы строчного уровня

Особенности

Участвуют в строчном контексте форматирования

Боксы строчного уровня

Особенности

Могут создать вокруг себя анонимные строчные боксы


Some inline text followed by a span followed by more inline text.
Some inline text followed by a span followed by more inline text.

Математика inline элементов

Инлайновые блоки не реагируют на задание ширины и высоты

То есть сколько текста положим внутрь инлайн блока,
такая ширина этого блока и будет

Математика inline элементов

Не реагируют на вертикальные margin'ы

Реагируют на горизонтальные margin'ы

Математика inline элементов

Инлайновые padding'и не затрагивают высоту строки

Но при этом сами padding'и можно сделать видимыми

Поверстаем!

Хотим получить:
Помощь
?

Попытка #1

                
Помощь ?
.button { width: 63px; height: 63px; background: #ff0; text-align: center; cursor: pointer; }
Помощь ?

Попытка #2

                
Помощь
?
.button { width: 63px; height: 63px; background: #ff0; text-align: center; cursor: pointer; }
Помощь
?

Что делать?

Использовать
display: inline-block!

FINISH HIM!

                
Помощь
?
.button { display: inline-block; width: 63px; height: 63px; background: #ff0; text-align: center; cursor: pointer; }
Помощь
?

inline-block элементы

Особенности

Реагируют на ширину и высоту

inline-block элементы

Особенности

Реагируют на вертикальные margin'ы

inline-block элементы

Особенности

Padding'и влияют на высоту строки

inline-block элементы

Особенности

Внешнее поведение как у inline элементов, а внутри создают блочный контекст форматирования

Итоги

  • Элементы на странице отображаются в виде боксов, каждый из которых имеет контентную часть (content), отступы (padding и margin) и границу (border)
  • Боксы бывают двух видов – блочного уровня и строчного уровня, задать можно с помощью CSS-свойства display
  • Для блочных боксов размеры и отступы можно задать либо явно, либо оставить вычисляемыми
  • Строчные боксы не будут реагировать на заданные ширину, высоту и вертикальные отступы
  • inline-block элементы – элементы, участвующие в строчном контексте форматирования, внутри которых действует блочный контекст форматирования

Спасибо!