Центрирование элементов
Мы уже изучили достаточно материла, который поможет нам реализовать наш проект. Сейчас, я хочу поделиться с тобой несколькими практическими приемами, которые встречаются в практике. Также я помечу некоторые из них меткой "Устарело". Я делаю это по нескольким причинам.
Во-первых, эти решения использовались довольно давно, но они до сих пор работают, но есть более современные. Во-вторых, хоть они являются устаревшими, но их польза заключается в том, что они помогают настроить мышление на нужны лад для работы верстальщиком.
Центрирование блочных элементов по-горизонтали
Начнем мы с горизонтальное центрирование блока, которая является самой частой задачей. Для ее решения используют margin со значением auto, которое рассчитывает браузером автоматически.
Создадим один блок с контентом и попробуем отцентрировать.
<div class="parent">
<div class="block">Дочерний блок</div>
</div>
body{
margin: 0;
}
.parent{
border: 2px solid black;
margin-left: auto;
margin-right: auto;
}
Как ты уже знаешь, блочные элементы по-умолчанию растягиваются на всю ширину своего родителя, и поэтому ширина элемента .parent будет равняться ширине body, и, соответственно, браузер не может рассчитать значения для внешних отступов.
Зададим значение ширины, которое будет меньше чем у body. Например, 400px.
.parent{
border: 2px solid #000;
margin-left: auto;
margin-right: auto;
width: 400px;
}
Браузер добавил 253,333px слева и справа, и давай попробуем понять, как он рассчитал эти значения.
Для этого нам пригодиться блочная модель. Я еще раз напишу ее.
Ш.Б = width + padding-right + padding-left + border-right + border-left + margin-right + margin-left
Но мы можем использовать ее не только для расчета размера бокса, но и для свойств width, padding, border и margin. Например, для margin формула изменится следующим образом:
margin = (Ш.Б - width - padding-right - padding-left - border-right - border-left) / 2
Из-за того, что мы используем значение auto, то margin-left и margin-right равны друг друге, и поэтому я делаю на два. Также из-за того, что у блока нет padding мы можем упростить формулу.
margin = (Ш.Б - width - border-right - border-left) / 2
Из всех значений мы не знаем ширину бокса, в которой находится элемент. Хм, как же быть? Тьфу, да все просто! Так как элемент .parent находится в body, то он и будет является боксом. Соответственно, мне нужно было посмотреть ширину body. Когда я делал скриншот экрана она равнялась 910,667px
margin = (910,667 - 400 - 0 - 0 - 2 - 2) / 2 = 253,333
Получилось точно такое же значение, как и в веб-инспекторе, и теперь мы точно знаем как же браузер обрабатывает значение auto для свойства margin.
Центрирование блока с position: absolute и position: fixed по горизонтали
Для изучения приема создадим следующий пример:
<div class="parent">
<div class="block">Дочерний блок</div>
</div>
.parent{
width: 500px;
height: 200px;
border: 2px solid #000;
margin-left: auto;
margin-right: auto;
position: relative;
}
.block{
width: 100px;
height: 100px;
background-color: tomato;
position: absolute;
top: 0;
left: 50%;
}
Из-за того, что координата элемента рассчитывается относительно левой стороны родителя, получается то, что браузер сдвигает на 50% левую сторону самого элемента, и поэтому блок находится чуть правее. Но нас это не устраивает!
Для исправления нужно сдвинуть элемент .block влево на половину его ширины. Например, мы можем сделать при помощи margin-left с отрицательным значением.
.block{
width: 100px;
height: 100px;
background-color: tomato;
position: absolute;
top: 0;
left: 50%;
margin-left: -50px;
}
Но в этом способе существует одно ограничение. Нам обязательно нужно знать ширину блока, но чаще всего ширина изменяется динамически, и мы не можем повлиять на это. Но, к счастью, существует решение!
Мы будем использовать свойство transform. Пока, что мы не будем подробно разбирать принцип работы свойства. Скажу только то, что мы будем использовать функцию translate, с помощью которой можно двигает элемент по осям X и Y.
Зададим в качестве первого аргумента значение -50%, а вторым — 0.
.block{
width: 100px;
height: 100px;
background-color: tomato;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 0);
}
Значением 50% рассчитывается от ширины элемента. Это то, что нужно!
Мы рассмотрели основные способы центрирования абсолютного блока, но что же с фиксированным позиционированием? Да, все хорошо! Все рассмотренные приемы отличное работают для элементов, которые позиционируются с помощью fixed.
Центрирование блока с position: absolute и position: fixed по вертикали
В предыдущем способе мы использовали функцию transform со значениями -50% и 0, но я не рассказал, почему во второй аргумент я передал такое число. Исправлю этот недочет и раскрою заветную тайну!
Да, на самом деле нет никакой тайны. Значение во втором аргументе отвечает за смещение по оси Y, а так как мы прижали блок к верху родителя, то и смещать его не нужно было.
Но, у меня есть один пример, в котором это как раз потребуется. Допустим, что центрирование нужно сделать сразу по осям X и Y, одновременно. Для этого нам нужно изменить в предыдущем примере значение для свойства top и для функции translate.
.block{
width: 100px;
height: 100px;
background-color: tomato;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Вот и все! Мы сверстали элемент так, что при любых его размерах, он всегда будет по центру.
Кроме приема с использованием transform мы также могли использовать отрицательный margin, но как и в случаи с шириной, нам нужно было бы знать высоту блока. А это еще более редкое явление, поэтому данную технику мы рассматривать не будем.
Центрирование строчно-блочных элементов по горизонтали
А теперь перейдем к строчно-блочным элементам. И начнем мы с позиционирования по горизонтали. Для решения мы будем использовать свойство text-align.
<body>
<div class="parent">
<div class="block">Дочерний блок</div>
</div>
</body>
.parent{
width: 1000px;
height: 500px;
border: 2px solid #000;
text-align: center;
}
.block{
display: inline-block;
width: 100px;
height: 100px;
background: tomato;
}
Центрирование строчно-блочных элементов по вертикали
И наконец то мы с тобой дошли до вертикального центрирования. Существует несколько техник решения этой задачи. Рассмотрим каждую по порядку.
С псевдоэлементом :before
Первый метод основывается на свойстве vertical-align.
<body>
<div class="parent">
<div class="block">
Дочерний блок
</div>
</div>
</body>
.parent{
width: 400px;
height: 500px;
border: 2px solid #000;
}
.parent:before{
content: "";
display: inline-block;
vertical-align: middle;
height: 100%;
}
.block{
display: inline-block;
vertical-align: middle;
}
Свойство vertical-align выравнивает элементы по вертикали. Но так, как у нас только один блок, то нам нужно добавить еще один. Для этого мы используем псевдоэлемент :before. Далее мы растягиваем его на всю высоту родителя, и теперь vertical-align: middle сможет отцентрировать соседний элемент по высоте псевдоэлемента, а тем самым и по высоте родительского блока.
Но давай теперь добавим больше текста, чтобы он занял как минимум 2 строки.
<body>
<div class="parent">
<div class="block">
Дочерний блок с длинным очень длинным текстом так, чтобы было очень длинно
</div>
</div>
</body>
Как видишь текст спрыгнул под блок. Ты же помнишь, что между строчно-блочными элементами создается отступ? Вот именно из-за текст и спрыгнул, потому что блоку с ним просто не хватило места.