css
Основы

Блочная модель

CSS
Основы

Обновлено

06.08.2023

Просмотров

396

Время прочтения

30 мин.

Сложность

Видеоурок

Этот урок также доступен в видеоформате

Смотреть

Блочная модель CSS является основой всех основ в Вебе. Это та самая черепаха из древних представлений о мироздании, на которой находится планета, только в нашем случае на блочной модели лежит вся фронтенд разработка. Суть этой модели, если сформулировать это вкратце, — все элементы веб сайтов являются прямоугольниками и состоят из четырёх компонентов — внутреннего содержимого (content), внутреннего отступа (css свойство padding), границы/рамки (css свойство border), внешнего отступа (css свойство margin). Не стоит заблуждаться на этот счёт, даже если кто-то намеренно станет вводить вас в заблуждение: 99% всего, что вы видите на веб-сайте, является прямоугольниками, даже если внешне это один или несколько текстовых символов, если это круг (даже если это фигура <circle> в SVG), неравнесторонний треугольник, шестиугольник и даже если это текст, свёрнутый в круг…

Все четыре компонента — содержимое, отступ внешний и внутренний, граница -, из которых состоят эти прямоугольники, обязательны для всех элементов, исключений здесь нет. Вместе с тем любой из этих компонентов может быть равен нулю (и по умолчанию все эти величины равны нулю, хотя браузеры в своих табицах стилей могут добавлять различные отступы), например элемент может не иметь содержимого, но может иметь внутренний отступ, и т.д. Это всё же не отменяет того, что все четыре компонента будут присутствовать у элемента. Именно от размеров этих отступов, рамки, внутреннего содержимого зависит итоговый размер и внешний вид элемента на странице.

Как видите, в браузере присутствует визуализация блочной модели, и это действительно очень удобно для разработчика. Мы всегда можем выбрать любой элемент на странице и посмотреть все его величины. Синим цветом выделена контентная часть, зелёным — внутренний отступ, жёлтым — граница, оранжевым — внешний отступ. Такими же цветами элемент будет подсвечиваться и на странице, если вы наведёте на него курсор мыши в панели разработчика. Стоит сказать, что, хотя все эти величины в CSS могут указываться в любых единицах измерения(px, %, vw, vh, pt), в визуальном представлении в панели разработчика эти величины будут обозначены в пикселях.

При указании значения в % учитывается ширина родительского элемента, то есть margin-left: 50% будет определять отступ, равный половине ширины родительского элемента.

Вы могли обратить внимание на то, что в визуализации блочной модели все величины имеют четыре стороны — верхнюю, нижнюю, левую и правую, и это вполне логично. Эти величины могут различаться с разных сторон, например верхний отступ может быть 100px, а нижний 20px, верхней границы/рамки у элемента может не быть, но может быть указана нижняя граница, и т.д. В связи с этим мы можем указывать эти величины как общим свойством для всех сторон (CSS свойства margin, padding), так и отдельными свойствами для различных сторон (CSS свойства margin-left, margin-right, padding-left, padding-right). Но об этом немного позже. Сперва поговорим о внешних отступах.

MARGIN

Определяет внешний отступ элемента. Хотя такой отступ по блочной модели относится к компонентам элемента, внешний отступ не является самим элементом и не входит в его ширину (CSS свойство width). Так, если мы укажем width: 500px для элемента, а также margin-top: 200px, то размер элемента не станет 700px. Также, если мы при помощи JavaScript укажем обработчик события клика мыши для элемента, клик по margin элемента не будет вызывать это событие.

Внешний отступ может указываться одновременно для всех четырёх сторон элемента, а может и по отдельности для каждой из сторон. В последнем случае применяются CSS свойства margin-left, margin-right, margin-top, margin-bottom. В случае, если мы указываем величину всех сторон элемента одним свойством margin, мы можем указывать одно или несколько значений и в зависимости от этого они будут применяться ко всем сторонам, к верхней и нижней и пр. Понятнее станет из примера CSS кода:

                
/* при указании одного значения оно применяется ко всем сторонам элемента */ .box1{ margin: 100px; } /* при указании двух значений первое применяется к верхнему и нижнему отступу (по 100px), а второе к левому и правому (по 60px) */ .box2{ margin: 100px 60px; } /* при указании трёх значений первое применяется к верхнему отступу (100px), второе к левому и правому (по 60px), а третье - к нижнему (80px) */ .box3{ margin: 100px 60px 80px; } /* при указании четырёх значений они применяются ко всем сторонам по часовой стрелке: первое к верхней, второе к правой, третье к нижней, четвёртое к левой */ .box4{ margin: 100px 60px 80px 20px; } /* значения не обязательно указывать в одинаковых единицах измерения. Вы можете указать все значения в разных единицах, а для right и left вообще применить auto */ .example-box{ margin: 100px auto 20%; }

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

Справедливо заметить, что подобный способ указания отступов подходит и для свойства padding и действует аналогично: исходя из количества указанных значений, они применяются к различным сторонам элемента.

Значения в случае margin, padding могут быть не только целыми числами, а также дробными (float), например margin-top: 20.5%. Как видите, в таком случае десятичная часть отделяется точкой. При указании дробных значений стоит знать и помнить, что браузеры по-разному обрабатывают десятичные доли пикселей, например 1.2px, 2.5px и пр. Некоторые браузеры будут округлять такие значения в большую, некоторые в меньшую стороны, некоторые способны отрисовывать такие величины как есть. При работе с пикселями(px), поинтами(pt), миллиметрами(mm), сантиметрами(cm), пиками(pc), то есть со всеми небольшими значениями, в CSS лучше не указывать дробные значения. Подробнее о единицах измерения будет рассказано в соответствующем уроке.

Говоря о вертикальной марже, мы должны обязательно упомянуть о схлопывании вертикальных отступов. Это поведение блочных элементов, следующих друг за другом, при котором их вертикальная маржа не суммируется, а берётся большее значение.

                
<style> .box{ width: 80px; height: 80px; background-color: red; } .top{ margin-bottom: 100px; } .bottom{ margin-top: 60px; } </style> <div class="box top"></div> <div class="box bottom"></div>

Как видите, отступ между двумя блоками не стал 160px, а «схлопнулся» и остался 100px, т.е. наибольшего значения из указанных. Про такое поведение вертикальной маржи вы обязательно должны помнить.

Схлопывание относится только к вертикальной марже (но не горизонтальной!), к элементам, находящимся в нормальном потоке документа, то есть расположенным статично (position: static). Также схлопывание не относится к строчно-блочным элементам (css свойства display: inline-block и display: inline-flex), к плавающим блокам (css свойство float). Об этих свойствах пойдёт речь в следующих уроках, однако запомнить эти исключения можно уже сейчас.

Маржа может быть не только нулевой или положительной, но также отрицательной. В таком случае блок просто «съедет» в указанную сторону на эту величину. При работе с вертикальной маржей схлопывание маржи учитывается.

                
<style> .box{ width: 80px; height: 80px; background-color: red; } .top{ margin-bottom: 100px; } .bottom{ margin-top: -60px; } </style> <div class="box top"></div> <div class="box bottom"></div>

Для нижнего блока указана верхняя маржа -60px, и она схлопнулась с верхним блоком, у которого нижняя маржа 100px. Итоговая маржа между этими двумя блоками всего 40px.

В случае, если нижний блок получит слишком большую отрицательную маржу, он «наедет» на вышестоящий блок, или даже на несколько блоков:

Отрицательная маржа является очень удобным способом визуально «надвинуть» один блок на другой, или даже целую секцию сайта «надвинуть» на другую секцию. Запомните этот приём, он вам обязательно пригодится в работе!

Помимо числовых значений, а также «глобальных» значений initial, inherit, отступы могут принимать значение auto. Для плавающих (float) элементов, строчных, блочно-строчных это значение вычисляется как 0. То же самое происходит и для блочных элементов при указании margin-top, margin-bottom. При указании для блочных элементов margin-left: auto или margin-right: auto данные отступы принимают максимально возможное значение, что приводит к ориентации элемента слева\справа в родительском контейнере. При указании одновременно margin-left: auto и margin-right: auto отступы распределяются равномерно, что приводит к выравниванию элемента по центру родительского контейнера.

                
<style> .box{ width: 80px; height: 80px; background-color: red; } .centered{ margin-left: auto; margin-right: auto; } .right-align{ margin-left: auto; } </style> <div class="box centered"></div> <div class="box right-align"></div>

Поведение блоков отображено на скриншоте (размер body уменьшен до 500px для удобства демонстрации):

Пожалуйста, запомните про эти особенности поведения БЛОЧНЫХ элементов при указании значения auto. Это самый простой способ выровнять блок по центру родителя, или справа. Запомните также, что с вертикальной маржей подобные «трюки» не работают, а значит выровнять блок по вертикали таким образом не получится.

margin
Значение в px, pt, %, em, rem и др. величинах определяет величину отступа с указанной стороны. При указании % значение рассчитывается относительно ширины родительского элемента. Может принимать отрицательное значение. Значение по умолчанию 0
auto Для строчных, блочно-строчных, плавающих (float) элементов вычисляется как 0. Для блочных свойства margin-right, margin-left вычисляются в максимально возможные значения, располагая тем самым блок слева, справа или по центру при указании обоих свойств как auto
initial устанавливает значение свойства по умолчанию
inherit значение свойства наследуется от родителя

Значения initial, inherit являются «глобальными» и могут применяться ко многим свойствам. Они позволяют «сбрасывать» указанное прежде значение, а также исключают необходимость дублировать код, наследуя значение от родителя.

PADDING

Внутренние отступы имеют много общего с внешними, однако во многом и отличаются от них. Самое важное в padding, пожалуй, то, что он является частью элемента. Поэтому, если вы укажете обработчик события клика на элементе и кликните на внутренний отступ, это событие будет обработано. Также при некоторых условиях в CSS внутренний отступ будет учитываться свойством width, однако об этом позже.

Как уже было сказано, внутренний отступ подсвечивается в панели разработчика и в браузере зелёным цветом. Правила описания свойства аналогичны margin: мы можем указывать для свойства padding одно или несколько значений, можем указывать размер отступов для отдельных сторон (padding-left, padding-top и т.д.). Исключением здесь будет являться значение auto, оно не может быть указано для padding.

У padding нет вертикального схлопывания, как у margin, поскольку внутренний отступ является частью элемента. Также вы не можете указывать отрицательные значения для padding. Правила с такими значениями не будут обработаны браузером.

padding
Значение в px, pt, %, em, rem и др. величинах определяет величину отступа с указанной стороны. При указании % значение рассчитывается относительно ширины родительского элемента. Отрицательные значения не допускаются. Значение по умолчанию 0
initial устанавливает значение свойства по умолчанию
inherit значение свойства наследуется от родителя

Теперь мы должны рассмотреть пару примеров использования padding, а также немного коснуться непосредственно содержимого элемента (content) и модели вычислений (CSS свойство box-sizing). Мы говорили, что элементы состоят из 4-х компонентов. О двух уже было сказано, о рамке речь пойдёт в отдельном уроке, а вот четвёртый компонент это то, чего как-бы и нет. Точнее, нет определённого свойства, определяющего ширину и высоту контента, хотя сам контент имеет и ширину, и высоту. На скриншоте выше была показана блочная модель в браузере, и контент элемента выделен на ней синим цветом, также он будет отображаться и на веб странице, если вы наведёте курсор мыши на элемент в панели разработчика. Впрочем, контента может и не быть, а элемент может иметь только padding, border и margin. Всё содержимое тега является контентом и обыкновенно определяет ширину и высоту этой контент-части. Если вы поместите в тег текст и изображение, они потребуют достаточно места, чтобы поместиться.

На скриншоте размер body уменьшен для удобства демонстрации. Вы можете наблюдать указанные свойства margin и padding для элемента, а также его контент. По умолчанию тег <p> является блочным, и он растягивается на всю ширину родителя, а значит всё, что не является его отступами и границей, может быть местом для его контента. Так и происходит — текст занимает всю возможную для него ширину. Если мы увеличим отступы, места для контента станет меньше, он уменьшится в ширине. Текст будет переноситься на следующую строку дальше и дальше, до тех пор, пока не поместится в теге.

В случае, если места для содержимого будет совсем мало, то, опять же, текст будет сжиматься максимально (одно слово на строке), а изображения, если таковые у нас будут, «переполнят» контент, т.е. просто отобразятся за его пределами.

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

Мы можем захотеть указать ширину для элемента, чтобы получить точно такой результат, какой требует от нас дизайн-макет сайта. Для этого мы можем воспользоваться CSS свойством width. Подробно мы поговорим о нём в следующем уроке, а пока что просто рассмотрим его применение. Мы указываем для параграфа с текстом ширину в 200 пикселей, а отступы по 20.

Мы получили вполне ожидаемый результат: ширина контента стала 200, отступы по 20. Итого элемент имеет ширину 200px (width) + 40px (padding с обеих сторон). Текстовый контент и изображение будут по-прежнему занимать столько места, сколько возможно, ну а при недостатке его будут вести себя вышеописанным образом. Обратите внимание на жёлтое поле справа — это маржа, которая у блочных элементов автоматически увеличивается вправо до максимума.

Из того, что мы увидели на последнем скриншоте, можно заключить, что свойство width определяет ширину контент-части элемента. То есть если мы укажем width: 400px, то и получим контент шириной 400. Это всё верно, но здесь есть одна важная особенность. Такая модель (она называется content-box) вычислений действует во многих браузерах по умолчанию — когда свойство width определяет ширину контент-части элемента -, но эта модель не является единственной и не является популярной в веб-разработке. В основном разработчики используют другую модель, признанную более удобной — border-box. За определение модели для элемента отвечает CSS свойство box-sizing, и оно может принимать только два этих значения. Модель box-sizing:border-box определяет, что свойство width (а также свойство height, о нём поговорим в следующих уроках) указывает размер не только контент-части, а также внутреннего отступа и рамки\границы. Понятнее будет после просмотра примера:

Теперь, при указании box-sizing:border-box наше свойство width учитывает размеры границы и padding, так что вычисление происходит следующим образом: размер всего элемента с границей и padding должен быть 200px. Поскольку padding у нас слева и справа определён по 20px, на контентную часть остаётся 160px. Разница налицо.

Как уже было сказано, border-box применяется разработчиками в подавляющем большинстве случаев, потому что эта модель на практике оказалась удобнее. Нам нужно только задать размеры элемента, а контент уже будет подстраиваться под них и будет учитывать border, padding. Только в некоторых случаях вам может понадобиться content-box. Когда вы столкнётесь с такими случаями, скорее всего вы уже будете довольно хорошо знать вёрстку и без труда разберётсь в этом.

Для переопределения калькуляции блочной модели разработчики часто пользуются следующим кодом, помещая его в сбросы стилей:

                
*{ box-sizing: border-box }

Это определит для всех ваших тегов калькуляцию размеров border-box, которая будет удобна в работе.

box-sizing
content-box значение в большинстве браузеров по умолчанию. Свойство width отвечает только за ширину контента и не включает в себя padding, border. При указании width:100px; padding:20px; финальная ширина элемента будет 140px!
border-box свойство width включает в себя ширину контента, padding, border. При указании width:100px; padding:20px; финальная ширина элемента будет 100px, ширина внутренних отступов в сумме 40px, а ширина контента 60px

Поля padding очень удобно использовать, создавая свободное пространство\рамку вокруг контента, например в карточке продукта, в форме заявки или в любом другом блоке. Таким образом вы выравниваете контент по левому\правому краю, не позволяя ему выходить за пределы обозначенного для него пространства.

Установка внутренних полей вовсе не означает, что мы не сможем ничего сделать с контентом. Мы в случае необходимости сможем визуально сдвинуть какое-либо содержимое блока за пределы контент-части. При этом, конечно же, для всех остальных элементов внутренний отступ будет действовать по-прежнему как ограничитель, и это для нас очень удобно:

Необходимо очков: