Разработка и ведение стартапов, изготовление сайтов, дизайн печатной и сувенирной продукции, продвижение.

Центрирование в CSS: полное руководство

    Центрирование элементов — самая популярная причина для жалоб на CSS. «Ну почему нельзя было сделать всё попроще?» — возмущаются все кому не лень. Думаю, проблема не в том, что это сложно сделать, а в том, что способов центрирования элементов такое множество, что бывает трудно выбрать подходящий.
     

    Давайте построим древовидную схему для принятия решения и будем надеяться, что это всё немного упростит.

     

    Центрирование по горизонтали
     

    Строчные элементы (тексты, ссылки) с типом отображения inline, inline-block, inline-table, inline-flex, внутри родительского блочного можно центрировать так:
     

    .center-children {
      text-align: center;
    }
    


     

    Блочный элемент можно центрировать, указав для margin-left и margin-right значение auto (а также прописав для него конкретный width, иначе он займёт всю ширину родительского контейнера и не будет нуждаться в центрировании). Для этого часто используют сокращённую запись:
     

    .center-me {
      margin: 0 auto;
    }
    

     
     

    Способ работает независимо от ширины центрируемого блочного элемента и его родителя. Обратите внимание, что заставить элемент плавать по центру с помощью float нельзя.
     

    Несколько блочных элементов, размещённые в ряд, которые нужно центрировать по горизонтали. Возможно, вам потребуется изменить тип display. Необходимо  указать для них тип отображения inline-block или применить flexbox:
     

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

     

    Центрирование по вертикали
     

    С вертикальным центрированием в CSS все немного сложнее:
     

    Элемент строчного типа помещающийся в одну строку:

     

    Иногда строчные/текстовые элементы могут выглядеть отцентрированными по вертикали только потому, что у них одинаковые верхнее и нижнее поля (padding).
     

    .link {
      padding-top: 30px;
      padding-bottom: 30px;
    }
    
    

    Если использование полей по какой-либо причине невозможно, а вы хотите отцентрировать текст, который точно не будет переноситься в следующую строку, можно использовать хитрость с установкой line-height равной высоте элемента, это отцентрирует текст:
     

    .center-text-trick {
      height: 100px;
      line-height: 100px;
      white-space: nowrap;
    }
    


     

    Центрирование нескольких строчек текста можно сделать с помощью установки одинаковых верхнего и нижнего полей, однако, если этот вариант не подходит, можно сделать элемент, в который помещён текст, ячейкой таблицы — буквально или же просто её имитацией на CSS. За центрирование в этом случае отвечает свойство vertical-align, несмотря на то, что обычно он просто выравниванивает по горизонтали элементы в ряду.
     

    Если происходит имитация таблицы, стоит использовать flexbox. Один дочерний flex-элемент можно довольно легко отцентрировать во flex-родителе.
     

    .flex-center-vertically {
      display: flex;
      justify-content: center;
      flex-direction: column;
      height: 400px;
    }
    

     

    Помните, что этот способ подходит только если у родительского контейнера указана конкретная ширина (px, % и т.д.), поэтому здесь у контейнера есть высота.
     

    Если оба этих способа не подходят, можно использовать приём «элемент-призрак», при котором в контейнер помещается псевдоэлемент с максимальной высотой, и текст выравнивается по горизонтали по этому элементу:
     

    .ghost-center {
      position: relative;
    }
    .ghost-center::before {
      content: " ";
      display: inline-block;
      height: 100%;
      width: 1%;
      vertical-align: middle;
    }
    .ghost-center p {
      display: inline-block;
      vertical-align: middle;
    }
    


     

    Блочный элемент с фиксированной высотой
     

    Обычно когда речь идёт о веб-странице, высота может быть неизвестна по многим причинам: если изменяется ширина элементы, перераспределение текста может изменить высоту. Вариации в стилизации текста могут изменить высоту. Изменение количества текста может изменить высоту элемента. Элементы с фиксированным соотношением сторон, например, изображения, могут изменить высоту при масштабировании, и так далее.
     

    Но, если вам известна высота, вертикальное центрирование можно сделать так:
     

    .parent {
      position: relative;
    }
    .child {
      position: absolute;
      top: 50%;
      height: 100px;
      margin-top: -50px; /* учитывайте поля и границы, если не используете box-sizing: border-box; */
    }
    


     

    Блочный элемент с не фиксированной высотой


    Можно центрировать, подняв вверх на половину его высоты после того, как сдвинули его наполовину вниз:
     

    .parent {
      position: relative;
    }
    .child {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
    }
    

     

    Всё это можно сделать значительно проще с помощью flexbox.
     

    .parent {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    
    

     

     

    И по горизонтали, и по вертикали
     

    Описанные выше приёмы можно комбинировать как угодно, чтобы получить идеально отцентрированные элементы. Но, по моему опыту, обычно всё сводится к трём вариантам:


    Элемент с фиксированной высотой и шириной.
     

    Использование отступов с отрицательными значениями, равными половине высоты и ширины элемента после того, как для него было прописано абсолютное позиционирование в точке 50%/50%, отцентрирует элемент внутри родителя. Кроме того, способ хорошо поддерживается браузерами:
     

    .parent {
      position: relative;
    }
    
    .child {
      width: 300px;
      height: 100px;
      padding: 20px;
    
      position: absolute;
      top: 50%;
      left: 50%;
    
      margin: -70px 0 0 -170px;
    }
    

     

    Элемент с нефикированной высотой и шириной.
     

    Если вам не известны ширина или высота, для центрирования можно использовать свойство transform и отрицательное значение translate по 50% в обеих направлениях (оно вычисляется от текущей ширины/высоты элемента):
     

    .parent {
      position: relative;
    }
    .child {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    


     

    Flexbox
     

    Чтобы выполнить центрирование в обеих направлениях с помощью flexbox, нужно использовать два центрирующих свойства:
     

    .parent {
      display: flex;
      justify-content: center;
      align-items: center;
    }