УРОК Nº 5.
Просто и понятно про рамки и отступы (padding, borders, margins)
На предыдущем уроке были представлены основные свойства CSS для форматирования текста, но это был лишь один из аспектов стилизации страниц. Определение разметки веб-страницы - это совершенно другое дело. Именно этому и посвящен данный урок.
"Блоковая модель CSS" это набор правил, определяющих отображение в Интернете любой веб-страницы. CSS рассматривает каждый элемент HTML-документа как "блок" [или "бокс"] с кучей различных свойств, определяющих его местоположение на странице. До сих пор все наши веб-страницы были просто набором элементов. Блоковая модель - это набор инструментов для настройки стандартной схемы расположения элементов.
Значительная часть работы веб-разработчика - это превращения дизайнерского эскиза в веб-страницу посредством блоковой модели CSS. Возникнает вопрос - а зачем изучать все эти правила вместо того, чтобы просто загрузить одно большое статичное изображение веб-страницы? Загрузил эскиз-картинку на веб-сервер и все. Разве этого недостаточно?
Да, это значительно упростило бы жизнь. Однако, если не разделять контент на HTML, поисковики не смогут определить структуру наших веб-страниц, не будет возможности сделать наш сайт адаптивным и добавить шикарную анимацию или интерактивность с помощью JavaScript. Цена этого компромисса слишком высока, чтобы игнорировать использование CSS.
Ниже мы рассмотрим основные компоненты блоковой модели: paddings, margins, рамки, inline- и блоковые блоки. Можно считать, что это "микро" CSS-макеты, ибо эта модель определяет специфику поведения блоков. На следующих уроках вы больше узнаете о том, как структура HTML и блоковая модель объединяются для создания сложных CSS-версток.
Для начала создайте новую папку css-box-model. Поместите туда новую веб-страницу boxes.html. Напишите следующий код:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<title>Boxes Are Easy!</title>
<link rel='stylesheet' href='box-styles.css'/>
</head>
<body>
<h1>Headings Are Block Elements</h1>
<p>Paragraphs are blocks, too. <em>However</em>, <em> and <strong>
elements are not. They are <strong>inline</strong> elements.</p>
<p>Block elements define the flow of the HTML document, while inline elements
do not.</p>
</body>
</html>
Вы помните из урока Hello, CSS как HTML-файл ссылается на таблицу стилей CSS? В данном случае это файл будет box-styles.css. Создайте и этот файл для данного урока (пока что его можно оставить пустым).
Надеемся, что вы уже освоились с особенностями работы в редакторе Atom для создания файлов и папок. Если нет, то обязательно просмотрите инструкцию по использованию редактора Atom на вводном уроке этого учебника.
В разделе Что нужно знать о веб-страницах мы вкратце рассказали, как CSS использует "блоки" для разметки веб-страницы. Каждый отображаемый элемент HTML это блок. Они бывают двух видов: "блоковые*" и "строчные (inline)".
* - "блоковый блок" (block box) звучит немного неуклюже. И все же я сознательно не употребляю другой перевод слова box - "бокс". Потому что на ресурсе, на который ссылается Oliver James, автор данного учебника - Mozilla Developers Network (MDN), box переводится как "блок".
Все элементы HTML, с которыми мы работали, по умолчанию имеют определенный тип блока. Например, <h1> и <p> - это элементы блокового уровня, а <em> и <strong> - inline-элементы. Давайте улучшим внешний вид наших блоков, добавив в box-styles.css следующий код:
h1, p {
background-color: #DDE0E3; /* светло-серый */
}
em, strong {
background-color: #B2D6FF; /* светло-голубой */
}
Свойство background-color заполняет только фон выбранного блока. Это даст нам четкое представление о структуре нашей страницы-примера. Наши заголовки и абзацы должны иметь светло-серый фон, а акцентирующие [italic] и сильные [strong] элементы - голубой.
Это демонстрирует нам несколько очень важных особенностей поведения, присущего блоковым и строчным блокам:
Мы можем переопределить установленный по умолчанию тип box элементов HTML с помощью CSS-свойства display. К примеру, вам вдруг захотелось строчные элементы <em> и <strong> превратить в блоковые. Для этого необходимо обновить наше правило в box-styles.css таким образом:
em, strong {
background-color: #B2D6FF;
display: block;
}
Теперь эти элементы действуют как наши заголовки и абзацы: они начинаются с отдельной строки и заполняют всю ширину браузера. Это очень удобно, когда мы хотим сделать элементы <a> кнопками или отформатировать элементы <img/> (оба эти элемента по умолчанию inline-блоки).
Однако делать <em> и <strong> блоковыми элементами - плохая идея. Поэтому давайте превратим их обратно в inline-блоки. Для этого поменяем их свойство display на inline, как показано ниже:
em, strong {
background-color: #B2D6FF;
display: inline;
/* em и strong строчные (inline) по умолчанию */
}
Блоковая модель CSS - это набор правил, определяющих размеры каждого элемента веб-страницы. Для каждого блока (как inline-, так и блокового), данная модель предусматривает четыре свойства:
Все это необходимо браузеру для отображения блока какого-либо элемента. Контент есть "содержимое" HTML-документа. Из этих четырех свойств только контент несет cемантическую ценность (именно поэтому контент находится в HTML). Остальные три свойства отвечают за внешний вид, то есть за презентацию контента. Поэтому все три определяются правилами CSS.
* - понятия внешнего и внутреннего отступов из-за схожести легко может привести к путанице. Поэтому я решил оставить исходные англ. названия: padding и margin. По этой же причине, для лучшей наглядности, "содержимое" зачастую заменяется словом "контент".
Давайте начнем изнутри. Мы уже рассматривали контент, теперь на очереди padding. Свойство padding... вы уже наверно догадались... определяет отступ для выбранного элемента:
h1 {
padding: 50px;
}
Это добавляет по 50 пикселей с каждой стороны заголовка <h1>. Обратите внимание (скриншот ниже), как расширяется цвет фона, заполняя это пространство. Так всегда происходит с padding, поскольку он находится внутри рамки, а все, что находится внутри рамки, имеет фон.
Иногда требуется стилизовать только одну сторону элемента. Для этого в CSS предусмотрены следующие свойства:
p {
padding-top: 20px;
padding-bottom: 20px;
padding-left: 10px;
padding-right: 10px;
}
Для изменения padding можно использовать любые единицы измерения (не только пиксели!). Помните единицы em? Они особенно удобны тем, что делают margin ваших элементов изменяющимся вместе с изменением размера основного шрифта.
Вводить все эти свойства может быть утомительно, поэтому CSS предусматривает альтернативную "сокращенную" форму свойства padding. Вы сможете задать верхний/нижний и левый/правый padding всего одной строкой CSS. Когда вы указываете два значения свойства padding, они интерпретируются как значения вертикального и горизонтального padding соответственно.
Это означает, что наше предыдущее правило может быть переписано так:
h1 {
padding: 20px 10px;
/* вертикально горизонтально */
}
Альтернативный вариант: четыре значения устанавливают padding для каждой стороны элемента по отдельности. Значения идут по часовой стрелке, начиная с верхнего:
Давайте попробуем удалить 10px правого padding из предыдущего правила. Получится по 20 пикселей сверху и снизу каждого абзаца, 10 пикселей слева и ни одного справа:
h1 {
padding: 20px 0 20px 10px;
/* сверху,справа, снизу и слева */
}
Использовать сокращенные форматы или нет - в значительной степени вопрос личных предпочтений и стандартов работы в будущей команде. Некоторым разработчикам импонирует лаконичность сокращенного формата. А другие считают, что длинную форму легче понять с первого взгляда (и следовательно, легче обслуживать). В какой-то момент своей карьеры веб-разработчика вы столкнетесь со всеми этими форматами.
Продолжая наше путешествие от центра блоковой модели CSS, мы видим рамку: линию, проведенную вокруг контента и padding элемента. Свойство рамки требует нового синтаксиса, который нам еще не знаком. Сначала мы определим ширину обводки рамки, затем ее стиль, а затем ее цвет.
Попробуйте добавить рамку вокруг нашего заголовка <h1>, изменив правило в файле box-styles.css:
h1 {
padding: 50px;
border: 1px solid #5D6063;
}
Это команда браузеру нарисовать тонкую серую линию вокруг нашего заголовка. Посмотрите как рамка вплотную примыкает к padding, не оставляя никакого зазора. А если уменьшить размеры браузера так, что заголовок будет разделен на две строки, то padding и рамка все равно останутся на своих местах.
Если нарисовать рамку вокруг всего заголовка, то он будет выглядеть как вебсайт из 1990-х. Так что мы ограничимся только нижней частью заголовка. Как и для свойства padding, так и для border существуют четыре свойства: -top, -bottom, -left и -right.
border-bottom: 1px solid #5D6063;
Рамки являются обычными элементами дизайна, но они также неоценимы для отладки. Когда Вы не уверены в том, как отображается блок, задайте следуещее правило: border: 1px solid red; Это отчетливо покажет padding, margin и общие размеры блока с помощью всего одной строки CSS. После того, как Вы выяснили причину сбоя, просто удалите это правило.
Дополнительную информацию о стилях оформления рамок вы найдете на сайте Mozilla Developer Network.
Margins определяют пространство за рамкой элемента. Или, точнее, пространство между блоком и окружающими его блоками. Давайте добавим немного свободного пространства к нижней части каждого элемента <p>:
p {
padding: 20px 0 20px 10px;
margin-bottom: 50px; /* добавьте это */
}
Это демонстрирует специфический для боковых сторон вариант свойства margin, и это свойство допускает те же сокращенные форматы, что и padding.
Свойства margin и padding могут выполнять одну и ту же задачу во многих ситуациях, что затрудняет определение того, какой из них является "правильным" выбором. Наиболее характерными причины для выбора:
Если ни один из этих пунктов не помог вам принять решение в пользу padding или margin, то не заморачивайтесь по этому поводу - просто выберите один из них. В CSS обычно существует несколько способов решения проблемы.
Одним из самых заметных отличий между блоковыми и inline-элементами - их поведение по отношению к margin. Inline-блоки полностью игнорируют верхний и нижний margin элемента. Для примера добавим достаточно большой margin к нашему элементу <strong>. Посмотрите, что произойдет.
strong {
margin: 50px;
}
Горизонтальные margin-отступы отображаются так, как ожидалось, но при этом вертикальное пространство вокруг нашего <strong> ничуть не изменилось.
Если мы изменим margin на padding, то обнаружим совсем другое поведение у padding в блоке. Пространство вокруг блока расширилось, однако вертикальное отображение окружающих блоков не изменилось.
Дело в том, что inline-блоки форматируют фрагменты текста внутри блока и, таким образом, оказывают ограниченное влияние на отображение страницы. Если хотите поэкспериментировать с вертикальным пространством страницы, вам следует использовать элементы блокового уровня (к счастью, мы уже знаем, как изменить тип блока элемента).
Итак, прежде чем биться головой о стену, пытаясь понять, почему не работает верхний или нижний margin, вспомните о проверке свойства display. Поверьте, рано или поздно это произойдет.
Еще одной странностью блоковой модели CSS является "вертикальное схлопывание margin". Когда два блока с вертикальными margin расположенны друг над другом, они схлопываются. Казалось бы оба margin должны добавляться друг к другу. Однако отображается только самый большой из них.
Давайте для наглядности добавим к нашему элементу <p> верхний margin в 25 пикселей.
p {
padding: 20px 0 20px 10px;
margin-top: 25px;
margin-bottom: 50px;
}
Каждый абзац получит по 50 пикселей снизу и 25 сверху. Вместе получается 75 пикселей между нашими элементами <p>, верно? Неверно! Между ними по-прежнему будет только 50px, потому что меньшее верхнее поле схлопывается в большее нижнее.
Такое поведение очень полезно при работе с множеством различных типов элементов когда вы хотите определить их минимальное пространство между другими элементами.
Эффект схлопывания полей может быть и очень досадным. Все таки иногда хотелось бы не допускать этого. Все, что нужно сделать, это поместить между ними еще один невидимый элемент:
<p>Paragraphs are blocks, too. <em>However</em>, <em> and <strong>
elements are not. They are <strong>inline</strong> elements.</p>
<div style='padding-top: 1px'><div> /* добавьте это */
<p>Block elements define the flow of the HTML document, while inline elements
do not.</p>
Подробнее о <div> поговорим в следующей секции. Самое важное здесь то, что только следующие друг за другом элементы могут схлопываться друг в дружку. Помещение элемента с ненулевой высотой (padding-top) между абзацами заставляет их отображать оба поля - и верхнее в 25px, и нижнее в 50px.
Помните, что padding никогда не схлопывается. Поэтому в виде альтернативы можно использовать padding вместо margin. Однако это срабатывает только, если не использовать padding ни для чего другого (а в данный момент мы используем, поэтому остановимся на варианте с <div>).
Третий вариант избежать схлопывания - соблюдение правила для margin "только снизу или только сверху*". Например, если все наши элементы определяют только bottom-margin, они не будут схлопываться.
И наконец, в схеме компоновки flexbox margin не схлопывается, так что для современных сайтов это вообще не проблема.
* - bottom-only or top-only margin convention.
До сих пор все рассмотренные HTML-элементы придавали дополнительный смысл их контенту. В этом и заключается смысл HTML, но все же иногда нужен некий универсальный блок только для стилизации веб-страницы. Для этого и предназначены <div> и <span>.
И <div>, и <span> являются "контейнерными" элементами, не оказывающими никакого влияния на семантическую структуру HTML-документа. Однако они позволяют добавлять CSS-стили к любым местам веб-страницы. Например, иногда нужно предотвратить добавить margin-схлопывание невидимой рамкой или сгруппировать первые абзацы статьи в краткий обзор с иным форматированием.
На протяжении всего курса мы будем часто использовать <div>. А пока давайте создадим простую кнопку, добавив в нижнюю часть нашего файла boxes.html следующее:
<div>Button</div>
А в файл box-styles.css добавьте стили для нашей кнопочки. Большинство из них должны быть знакомы по предыдущей главе, за исключением нового свойства border-radius:
div {
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;
}
В результате мы получим большую синюю кнопку, занимающую всю ширину браузера:
Эти стили применяются и к невидимому <div>, которым мы отменили margin-схлопывание (см. выше). Очевидно, что для практической пользы от отдельных <div> необходимо их как-то выделить. Для этого и нужны селекторы классов (см. следующ. урок). А пока что просто удалим или закомментируем этот невидимый <div>.
Единственная реальная разница между <div> и <span> заключается в том, что <div> предназначен для блоков, а <span> - для строк.
До сих пор мы позволяли нашим HTML-элементам определять свои размеры автоматически. Paddings, margins, рамки, с которыми мы экспериментировали, обхватывают все внутри блока элемента. Если добавить в наш <em> больше текста, то все будет расширяться, чтобы вместить его:
Но иногда в макете требуется явно выраженный размер, например, боковая панель шириной ровно 250 пикселей. Для этого в CSS предусмотрены свойства width и height. Они имеют приоритет над размером содержимого блока по умолчанию.
Давайте придадим нашей кнопке фиксированную ширину, добавив в box-styles.css следующее свойство:
div {
/* уже заданные декларации */
width: 200px;
}
Вместо ширины во все окно браузера, ширина кнопки стала 200px и она прилегает к левой стороне страницы:
Также заметьте, что сделав заголовок кнопки длиннее, он автоматически перейдет на следующую строку, а элемент увеличится по вертикали, чтобы вместить этот новый контент. Это стандартное поведение можно изменить свойствами white-space и overflow.
Свойства width и height в блоке определяют только размер контента. Padding и рамка добавляются поверх заданных вами размеров. Это объясняет, почему на скриншоте нашей кнопки вы получите изображение шириной 244 пикселя, несмотря на то, что заявленная ширина width: 200px.
Само собой разумеется, это может быть несколько противоречивым, когда вы пытаетесь разметить страницу. Представьте, что вы пытаетесь заполнить контейнер размером 600px тремя блоками шириной: 200px, но они не помещаются, поскольку все они имеют рамку в 1px (что делает их фактическую ширину 202px).
К счастью, CSS позволяет изменить способ расчета ширины блока с помощью свойства box-sizing. По умолчанию оно имеет значение content-box, что приводит к описанному выше поведению. Посмотрим, что произойдет, если мы изменим его значение на border-box:
div {
color: #FFF;
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
border: 2px solid #5D6063;
border-radius: 5px;
width: 200px;
box-sizing: border-box;
/* добавьте это */
}
В результате фактическая ширина блока будет равна 200px - с учетом padding и рамки. Разумеется, ширина контента теперь определяется автоматически:
Это гораздо более интуитивно понятно, поэтому border-box для всех блоков веб-разработчики сегодня считают оптимальным решением.
Выравнивание блоков по горизонтали - распространенная задача для веб-разработчиков, и блоковая модель предлагает множество способов ее решения. Мы уже рассмотрели свойство text-align, которое выравнивает контент и строчные блоки внутри элемента блокового уровня. Выравнивание блоковых блоков - это совсем другая история.
Попробуйте добавить в нашу таблицу стилей следующее правило. Оно будет выравнивать только контент внутри блоковых блоков, но не сами блоки. Наша кнопка <div> все равно будет выровнена по левому краю, независимо от выравнивания текста в <body>:
body {
text-align: center;
}
Существует три метода горизонтального выравнивания элементов на уровне блоков: центрирование auto-margins, floats для выравнивания по левому/правому краю и flexbox для полного контроля над выравниванием. Да, к сожалению, выравнивание на уровне блоков совершенно не связано со свойством text-align.
Floats и flexbox - это сложные темы, которым мы посвятили отдельные главы-уроки. Зато сейчас у нас есть все необходимые знания для работы с auto-margins. Устанавливая для левого и правого полей элемента блокового уровня значение auto, мы получаем центрирование блока в его родительском элементе.
Например, мы можем отцентрировать нашу кнопку следующим образом:
div {
color: #FFF;
background-color: #5995DA;
font-weight: bold;
padding: 20px;
text-align: center;
width: 200px;
box-sizing: border-box;
margin: 20px auto;
/* вертикально горизонтально */
}
Обратите внимание, что это работает только с блоками, для которых явно задана ширина. Уберите строку width: 200px, и наша кнопка будет занимать всю ширину браузера, что сделает "центрирование" бессмысленным.
Заметили белую каемку вокруг нашей страницы (см. скриншот ниже)? Это marging, padding и поля, добавленные браузером по умолчанию. Различные браузеры имеют разные стандартные стили для всех HTML-элементов, что затрудняет создание одинаковых таблиц стилей.
В большинстве случаев полезно переопределить стили по умолчанию на предсказуемое значение с помощью "универсального" CSS-селектора (*). Попробуйте добавить его в верхнюю часть нашего файла box-styles.css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
Этот селектор соответствует каждому элементу HTML, эффективно сбрасывая свойства margin и padding на нашей веб-странице. Все наши блоки также были преобразованы в border-box, что, опять же, является налучшей практикой.
Подобный сброс можно найти в верхней части почти каждой таблицы стилей CSS в Интернете. Все может оказаться гораздо сложнее, но три простых декларации, показанные выше, позволяют нам уверенно настраивать блоковую модель CSS для своих целей, не опасаясь непредвиденных взаимодействий со стилями браузера по умолчанию.
Более подробно о практическом использовании блоковой модели CSS мы узнаем по мере углубления в создание сложных веб-страниц. Пока же воспринимайте ее как новый инструмент в вашем арсенале CSS. Ознакомившись с несколькими ключевыми понятиями из этой главы, вы ощутите себя гораздо более подготовленным к преобразованию дизайнерского эскиза в реальную веб-страницу:
Как и на прошлом уроке, только что рассмотренные CSS-свойства могут показаться простыми - так оно и есть. Но стоит взглянуть на посещаемые сайты через призму блоковой модели, - и вы увидите эти свойства буквально повсюду.
Наше изучение универсальных блоков (<div> и <span>) было несколько ограниченным, поскольку у нас не было возможности извлечь отдельный HTML-элемент из нашей веб-страницы. Мы исправим это на следующем уроке, где более подробно рассмотрим селекторы CSS.