Вещи, связанные с центрированием в CSS, это, пожалуй, олицетворение того, на что чаще всего жалуются пользователи. Это на самом деле должно быть так сложно? — иронично интересуются они.
Я думаю, что проблема заключается не в том, что центрирование трудно осуществить, а в том, что, в зависимости от ситуации, существует так много различных способов сделать это, что их трудно охватить все.
Поэтому давайте создадим дерево решений и, надеюсь, теперь этот вопрос станет для вас проще. Мне нужно отцентрировать элементы…
Горизонтально
Это элементы inline или inline-* (например, текст или ссылки)?
Вы можете отцентрировать элементы inline горизонтально, в родительском элементе block-level с помощью:
.center-children {
text-align: center;
HTML:
<header>
Этот текст отцентрирован.
</header>
<nav role='navigation'>
<a href="#0">Один</a>
<a href="#0">Два</a>
<a href="#0">Три</a>
<a href="#0">Четыре</a>
</nav>
CSS:
body {
background: #f06d06;
}
header, nav {
text-align: center;
background: white;
margin: 20px 0;
padding: 10px;
}
nav a {
text-decoration: none;
background: #333;
border-radius: 5px;
color: white;
padding: 3px 8px;
}
Это будет работать для inline, inline-block, inline-table, inline-flex и т.д.
Это элемент уровня блока?
Вы можете отцентрировать элемент block-level, придав ему margin-left и margin-right или auto (при этом также нужно задатьwidth, в противном случае это будет полная ширина, и центрирование не потребуется). Это часто делается в подобных сокращениях:
.center-me {
margin: 0 auto;
}
HTML:
<main>
<div class="center">
Я элемент block-level и я отцентрирован.
</div>
</main>
CSS:
body {
background: #f06d06;
}
main {
background: white;
margin: 20px 0;
padding: 10px;
}
.center {
margin: 0 auto;
width: 200px;
background: black;
padding: 20px;
color: white;
}
Это будет работать независимо от ширины элемента block-level или родительского элемента. Обратите внимание, что вы не можете использовать привязку к центру float.
У вас есть более чем один элемент block-level?
Если у вас есть два или более элемента block-level, которые должны быть отцентрированы горизонтально в ряд, скорее всего вам лучше применить для них разные типы display. Вот примеры, как сделать из них inline-block и flexbox:
HTML:
<main class="inline-block-center">
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд.
</div>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд. Я содержу больше контента, чем другие элементы моего уровня.
</div>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд.
</div>
</main>
<main class="flex-center">
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд.
</div>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд. Я содержу больше контента, чем другие элементы моего уровня.
</div>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд.
</div>
</main>
CSS:
body {
background: #f06d06;
font-size: 80%;
}
main {
background: white;
margin: 20px 0;
padding: 10px;
}
main div {
background: black;
color: white;
padding: 15px;
max-width: 125px;
margin: 5px;
}
.inline-block-center {
text-align: center;
}
.inline-block-center div {
display: inline-block;
text-align: left;
}
.flex-center {
display: flex;
justify-content: center;
}
Если только вы не хотите расположить несколько элементов block-level друг над другом. В этом случае по-прежнему прекрасно работает техника автоматического отступа:
HTML:
<main>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд.
</div>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд. Я содержу больше контента, чем другие элементы моего уровня.
</div>
<div>
Я элемент блочного типа, у меня есть другие элементы того же уровня, и все мы отцентрированы в ряд.
</div>
</main>
CSS:
body {
background: #f06d06;
font-size: 80%;
}
main {
background: white;
margin: 20px 0;
padding: 10px;
}
main div {
background: black;
margin: 0 auto;
color: white;
padding: 15px;
margin: 5px auto;
}
main div:nth-child(1) {
width: 200px;
}
main div:nth-child(2) {
width: 400px;
}
main div:nth-child(3) {
width: 125px;
}
Вертикально
Вертикальное центрирование в CSS немного сложнее
Это элементы inline или inline-* (например, текст или ссылки)?
Это одиночная строка?
Иногда линейные / текстовые элементы могут центрироваться по вертикали, просто потому, что отступ снизу и сверху равны:
body {
background: #f06d06;
font-size: 80%;
}
main {
background: white;
margin: 20px 0;
padding: 50px;
}
main a {
background: black;
color: white;
padding: 40px 30px;
text-decoration: none;
}
Если отступ по некоторым причинам для вас это не вариант, и вы хотите отцентрировать текст, который не будет оборачивать, существует прием, аналогичный тому, что мы делали с line-height:
<main>
<div>
Я отцентрированная строка.
</div>
</main>
CSS
body {
background: #f06d06;
font-size: 80%;
}
main {
background: white;
margin: 20px 0;
padding: 40px;
}
main div {
background: black;
color: white;
height: 100px;
line-height: 100px;
padding: 20px;
width: 50%;
white-space: nowrap;
}
Это несколько строк?
Аналогично отступ сверху и снизу может задать эффект центрирования для нескольких строк текста. Но иногда это не будет работать, если элемент текста представляет собой ячейку таблицы или для него с помощью CSS задано такое поведение. В этом случае применяется свойство vertical-align, в отличие от общих случаев выравнивания элементов:
HTML:
<table>
<tr>
<td>
Мы - отцентрированные по вертикали несколько строк текст в ячейке таблицы.
</td>
</tr>
</table>
<div class="center-table">
<p> Мы - отцентрированные по вертикали несколько строк текста в созданной через CSS структуре таблицы.</p>
</div>
Если выравнивание в формате таблицы неприменимо для вас, возможно, вы могли бы использовать flexbox? Один дочерний элемент flex может легко быть отцентрирован внутри родительского элемента flex:
Имейте в виду, что это актуально только для тех случаев, когда контейнер имеет фиксированную высоту (в пикселях, процентах и т.д.), поэтому для контейнера здесь задана высота.
Если оба этих метода неприменимы, вы могли бы использовать технику “призрачного элемента”, в которой внутри контейнера по всей высоте размещается псевдо-элемент и текст вертикально выравнивается с помощью этого элемента:
<div class="ghost-center">
<p>Мы - отцентрированные по вертикали несколько строк текста в контейнере. Центрирование выполнено внутри псевдо элемента.</p>
</div>
Довольно часто вы можете не знать высоту в макете веб-страницы по многим причинам: если ширина изменяется, текст адаптивный и может изменять высоту. Высота текста может меняться в зависимости от различных применяемых к нему стилей.
Элементы с фиксированным соотношением сторон, например, изображения, могут изменять свою высоту при изменении ширины. И т.д.
Но если вы знаете высоту, вы можете выровнять элемент по центру следующим образом:
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px; /* при вычислении отступа и границы не используется box-sizing: border-box; */
}
HTML:
<main>
<div>
Я элемент block-level с фиксированной высотой, отцентрированный вертикально внутри родительского элемента.
</div>
</main>
Вы можете комбинировать методы, приведенные выше, любым способом, чтобы получить полное центрирование элементов. Но я, как правило, выделяю три основных частных случая.
Это элементы с фиксированной шириной и высотой?
Использование отрицательных полей, равных половине ширины и высоты элемента, после того, как вы абсолютно позиционировали их на 50% / 50% от размеров родительского элемента, будет поддерживаться большинством браузеров:
Если вы не знаете, ширину или высоту элемента, вы можете использовать свойство преобразования и отрицательный перевод на 50% в обеих плоскостях (этот метод основан на текущей ширине / высоте элемента) в центр: