Скажем, у вас есть такой фрагмент HTML:
<p>Это параграф текста, в котором есть несколько слов.</p>
Затем вы пишете для него этот CSS:
p {
width: 100px;
height: 50px;
padding: 20px;
border: 1px solid;
}
Контент выйдет за пределы вашего элемента и будет шириной в 142 пикселя, а не 100 пикселей. Почему? Блочная модель — это основа основ CSS, и понимание того, как она работает, как на нее влияют другие аспекты CSS, а главное, как ей управлять, поможет вам написать более предсказуемый CSS.
При написании CSS, да и вообще работе в сети, очень важно помнить, что все, что отображается в CSS, представляет собой блок. Будь то блок, в котором используется border-radius
для имитации круга, или просто какой-нибудь текст, важно помнить, что все это — блоки.
Содержание и размеры
Поведение блоков отличается в зависимости от значения их свойства display
, установленных размеров и содержимого, которое в них находится. Этим содержимым могут быть другие блоки, созданные дочерними элементами, или простой текст. В любом случае это содержимое по умолчанию влияет на размер блока.
Это можно контролировать, используя указание внешних размеров (extrinsic sizing), или же можно позволить браузеру принимать решения за вас на основе размера контента, используя внутреннее определение размера (intrinsic sizing).
Давайте вкратце рассмотрим разницу на следующем примере.
В примере есть слова «CSS is awesome» в блоке с фиксированными размерами и толстой рамкой. У блока задана ширина, так что его размеры определены внешне. Он управляет размером своего дочернего содержимого. Проблема заключается в том, что слово «awesome» слишком велико для блока, поэтому оно выходит за пределы блока границ родительского блока (подробнее об этом позже в уроке). Один из способов предотвратить такой выход за границы состоит в том, чтобы разрешить блоку определять размеры внутренне, либо сбросив ширину, либо, в данном случае, установив width
как min-content
. Ключевое слово min-content
указывает, что ширина блока должна соответствовать внутренней минимальной ширине его содержимого (слово «awesome»). Это позволяет фразе «CSS is awesome» идеально вписаться в блок.
Чтобы увидеть влияние различных размеров на реальный контент, рассмотрим что-нибудь посложнее:
Включите и выключите внутренний размер, чтобы посмотреть, как точнее управлять элементом с помощью внешнего размера или отдать управление контенту при помощи внутреннего определения размера. Чтобы увидеть эффект внутреннего и внешнего определения размеров, добавьте на карточку несколько предложений. Когда элемент использует указание внешнего размера, существует предел того, сколько контента получится добавить, прежде чем он выйдет за границы элемента. Если включено внутреннее определение размера, такого предела нет.
По умолчанию для этого элемента заданы значения width
и height
— 400px
в обоих случаях. Эти размеры задают строгие границы всему внутри элемента, которые будут соблюдаться, пока содержимое не превышает размеры блока — в этом случае произойдет очевидный выход за его границы. Как это выглядит, можно посмотреть, изменив содержимое подписи под изображением цветка так, чтобы оно превышало высоту рамки, то есть добавив несколько строк.
Когда вы переключаетесь на внутреннее определение размеров, вы позволяете браузеру принимать решения за вас в зависимости от размера содержимого блока. При внутреннем определении размеров переполнить блок намного сложнее, поскольку размер нашего блока будет изменяться вместе с его содержимым, а не пытаться изменить размеры контента. Важно помнить, что таково гибкое поведение браузера по умолчанию. Хотя на первый взгляд указание внешних размеров дает больший контроль, в большинстве случаев внутреннее определение размера обеспечивает лучшую гибкость.
Области блочной модели
Блоки состоят из отдельных областей блочной модели, каждая из которых выполняет определенную работу.
Начнем с блока контента, который представляет собой область, в которой находится контент. Как вы уже знаете, ее содержимое может управлять размером своего родителя, поэтому, как правило, размер этой области изменяется чаще всего.
Блок заполнения окружает блок контента и является пространством, созданным свойством padding
. Поскольку отступ находится внутри блока, фон блока будет виден в создаваемом им пространстве. Если для нашего блока заданы правила переполнения, такие как overflow: auto
или overflow: scroll
, это пространство также займут полосы прокрутки.
Блок границ окружает блок заполнения, а его пространство занято значением border
. Блок границ — это рамка вашего блока, а края границы (border edge) — это предел того, что вы видите. Свойство border
используется для визуального обрамления элемента.
Последняя область, блок отступа, — это пространство вокруг вашего блока, определяемое правилом margin
. Такие свойства, как outline
и box-shadow
, также занимают это пространство, поскольку они отрисовываются поверх и поэтому не влияют на размер нашего блока. У нашего блока значение outline-width
может быть 200px
, и все внутри него, включая рамку, будет точно такого же размера.
Полезная аналогия
Разобраться в блочной модели нелегко, поэтому давайте подведем итог тому, чему вы научились, с помощью аналогии.
На этой схеме три фоторамки, прикрепленные к стене рядом друг с другом. На схеме есть метки, которые связывают элементы рамы с блочной моделью.
Разберем эту аналогию:
- Блок контента — это графическая составляющая.
- Блок заполнения — белая матовая поверхность между рамкой и иллюстрацией.
- Блок границ — это рамка, в прямом смысле обеспечивающая границу изображения.
- Блок отступа — это пространство между рамками.
- Тень занимает то же пространство, что и блок отступа.
Отладка блочной модели
Браузерные DevTools обеспечивают визуализацию вычислений блочной модели выбранного блока, что может помочь вам понять, как работает блочная модель, и, что немаловажно, как она влияет на веб-сайт, над которым вы работаете.
Попробуйте это в своем браузере:
- Откройте DevTools
- Выберите элемент
- Включите отладчик блочной модели
Управление блочной моделью
Чтобы понять, как управлять блочной моделью, вам сначала нужно понять, что происходит в вашем браузере.
Каждый браузер применяет таблицу стилей пользовательского агента к HTML-документам. Используемый CSS варьируется в зависимости от браузера, но значения по умолчанию подобраны продуманно, чтобы облегчить чтение контента. Если CSS не определен, то, как элементы должны выглядеть и вести себя, определяется браузером. Это прописано в стилях пользовательского агента, где также установлено значение display
по умолчанию для блока. Например, при нормальном ходе работы значение display
по умолчанию для элемента <div>
равно block
, для <li>
значение display
по умолчанию — list-item
, а для <span>
значение display
по умолчанию равно inline
.
У inline
-элемента есть блочный отступ, но другие элементы его игнорируют. Используйте inline-block
, и эти элементы будут учитывать отступ, при этом элемент будет поддерживать большинство тех же действий, что и inline
-элемент. block
по умолчанию заполняет доступное встроенное пространство (inline space), тогда как размер элементов inline
и inline-block
будет соответствовать их содержимому.
Наряду с пониманием того, как стили пользовательского агента влияют на каждый блок, также необходимо понимать правило box-sizing
, которое сообщает нашему блоку, как рассчитать его размер. По умолчанию у всех элементов стиль пользовательского агента следующий: box-sizing: content-box;
.
Наличие content-box
в качестве значения box-sizing
означает, что когда вы устанавливаете размеры, такие как width
и height
, они будут применены к блоку контента. Если затем задать padding
и border
, эти значения будут добавлены к размеру блока контента.
Check your understanding
Test your knowledge of box model size impacting properties
.my-box { width: 200px; border: 10px solid; padding: 20px; }
How wide do you think .my-box
will be?
200px
would be correct if the
box had box-sizing: border-box
.
Фактическая ширина этого блока будет равна 260 пикселям. Поскольку CSS использует box-sizing: content-box
по умолчанию, применяемая ширина — это ширина контента плюс padding
и border
с обеих сторон. Таким образом, 200 пикселей для содержимого + 40 пикселей заполнения + 20 пикселей границы в сумме дают видимую ширину 260 пикселей.
Однако этим можно контролировать, реализовав следующую модификацию для использования альтернативной блочной модели, border-box
:
.my-box {
box-sizing: border-box;
width: 200px;
border: 10px solid;
padding: 20px;
}
Такая альтернативная блочная модель сообщает CSS применить значение width
к блоку границ, а не к блоку контента. Это означает, что наши параметры border
и padding
будут вписаны внутрь, и в результате, когда вы установите .my-box
шириной в 200px
, блок на самом деле будет отрисован шириной 200px
.
Посмотрите, как это работает, в следующем интерактивном примере. Обратите внимание, что при переключении значения box-sizing
на синем фоне показывается, какой CSS применяется внутри нашего блока.
*,
*::before,
*::after {
box-sizing: border-box;
}
Это правило CSS выбирает каждый элемент в документе, а также каждый псевдоэлемент ::before
и ::after
, и применяет box-sizing: border-box
. Это означает, что теперь у каждого элемента будет эта альтернативная блочная модель.
Поскольку альтернативная блочная модель может быть более предсказуемой, разработчики часто добавляют это правило к сбросам и нормализаторам, таким как этот.