Статья подготовлена для студентов курса «Разработчик JavaScript» в образовательном проекте OTUS.
Во frontend-разработке неизбежное зло – это вёрстка. Насколько бы навороченными не были фреймворки для построения UI, рано или поздно возникнет необходимость в вёрстке. Да и жизнь осложняется тем, что в CSS нет полифиллов, как таковых.
В этой заметке разберём один популярный вопрос на собеседовании. Встретить в сети полный перечень всех способов с учётом современных возможностей непросто. Тем не менее они так или иначе присутствуют на просторах.
Для всех нетривиальных способов даны ссылки, которые помогут в изучении той или иной технологии. Поэтому данный материал будет полезен не только новичкам, но и тем, кто хочет пополнить собственную коллекцию приёмов.
Вопрос в студию
Есть два div-а:
Назовите все способы выровнять внутренний .child по центру по горизонтали относительно .parent. Вот так:
Ссылка на эту картинку в CodePen. Число способов, которые предоставит соискатель, неплохо коррелирует с опытом в вёрстке. Все приведённые приёмы доступны и здесь.
Вариант #01 – margin
Первое, что приходит в голову (в пикселях):
Ссылка на CodePen.
Плюсы и минусы:
– это просто;
– здесь необходимо, чтобы были заданы размеры div-ов;
– соответственно, необходимо заранее вычислить размеры div-ов и margin;
– и, конечно, это никак не responsive.
То же самое в процентах:
Ссылка на CodePen.
Плюсы и минусы:
– по сути, то же самое что и первое;
– но уже лучше – вычислять абсолютные размеры .child div-а и margin мы заставляем браузер;
– ну, хоть какое-то responsive.
Вариант #02 – padding и box-sizing
Ссылка на CodePen.
С padding-ами не так просто – именно теми пикселями можно задать, только зная об одной особенности.
По умолчанию, у .parent стоит box-sizing: content-box, и это означает, что width задаёт размер контента без учёта padding. Т.е. размер .parent будет в данном случае 500px. Подробнее про box-sizing и CSS Box Model.
Плюсы и минусы:
– в принципе, все предыдущие плюсы и минусы имеют место;
– да, и box-sizing это CSS3
Вариант #03 – padding-и
Конечно, зная об этом, можно достаточно просто написать вот это:
Ссылка на CodePen.
Плюсы и минусы:
– в принципе, все предыдущие комментарии имеют здесь место;
– а вот полный размер контейнера уже не так тривиально определить/задать.
Вариант #04 – transparent border
Ссылка на CodePen.
Стоит отметить, что для правильного варианта обязательно задавать border-style (solid – один из вариантов, главное, что не дефолтный none), ну и, конечно, прозрачный цвет transparent.
Плюсы и минусы:
– оригинально;
– но сложно для чтения и понимания.
Вариант #05 – margin auto
А вот это, первое придёт на ум чуть более опытному верстальщику.
Ссылка на CodePen.
Да, это так аккуратно записали margin: 0 auto. Просто мы ничего не знаем о верхней границе, и не задаём 0.
Плюсы и минусы:
– это очень просто и популярно;
– margin считает сам браузер;
– нужно задавать явно размер div-а явно. Если этого не сделать, то auto будет равно 0.
Вариант #06 – с помощью CSS-препроцессоров
Если имеются CSS-препроцессоры (скажем, Less), то вычисления соответствующих границ можно переложить на них. Не забудем про эту возможность:
Ссылка на CodePen.
Это Less, а ещё есть SASS, SCSS, PostCSS и другие.
Плюсы и минусы:
- в итоговой CSS это будут всё те же пиксели.
Вариант #07 – CSS-переменные и calc
Мало кто знает, но и в CSS есть экспериментальные переменные, а ещё и оператор calc:
Ссылка на CodePen.
Про CSS-переменные можно прочитать здесь, а про calc - здесь.
Ну и, конечно, стоит ознакомиться с поддержкой – здесь и здесь, соответственно.
Вариант #08 – position: relative
Ссылка на CodePen Здесь, в принципе, всё понятно. Для тех, кто впервые видит position.
Вариант #09 – position: absolute
А вот про это стоит спросить отдельно.
Ссылка на CodePen Этот вариант достаточно хорошо коррелирует с опытом вёрстки. Предлагаем читателям самостоятельно разобраться, почему необходимо указать position: relative у parent-а.
Плюсы и минусы:
- да, здесь не задаётся ширина у .child.
Вариант #10 – translateX(-50%)
Ссылка на CodePen Подробнее с возможностями transform можно ознакомиться здесь.
Плюсы и минусы:
– не самый очевидный трюк;
– хотя довольно встречается на просторах сети.
Вариант #11 – эклектика
На просторах сети можно встретить и такого монстра:
Ссылка на CodePen. Предлагаем читателям самостоятельно разобраться, что здесь происходит, и почему это не самый лучший пример. Да, здесь 100px = ширина .child / 2
Вариант #12 – inline-block + text-align
Вот этот вариант коррелирует со знаниями о блочных и inline-элементах:
Ссылка на CodePen.
В этом примере блочный элемент div мы сделали строчным, а дальше он выравнивается, как обычный текст.
Подробнее о блочных и строчных элементах.
Вариант #13 – display: table
Любители верстать всё в таблицах могут применить свои навыки и для div-ов:
Ссылка на CodePen. Оставим читателям удовольствие разобраться самостоятельно с этим примером.
Вариант #14 – extra div + float
Если допустить появление дополнительного тега, т. е.:
То можно расположить элементы с помощью float:
Ссылка на CodePen. Подробнее о float можно прочитать, есть прекрасная статья.
Плюсы и минусы:
– это нечестно, добавить один элемент;
– да и разметку следует держать чистой;
– но это очень просто.
Вариант #15 – псевдоэлементы + float
Как ни странно, но «дополнительные» теги уже есть. Называются они псевдоэлементами. Их можно использовать с тем же успехом:
Ссылка на CodePen.
У каждого элемента есть условные два внутренних – :before- и :after-псевдоэлементы. Это очень мощный инструмент в вёрстке, позволяющий держать разметку чистой.
По сути дела, разметка теперь выглядит такой:
Чтобы этот элемент отобразился, необходимо задать ему content. Подробнее про псевдоэлементы.
Плюсы и минусы:
– экономия разметки! – но это float. Сейчас уже почти полностью вытеснено flexbox-ами.
Вариант #16 – псевдоэлементы + text-align
С учётом всего перечисленного этот вариант очевиден:
Ссылка на CodePen. И предлагаем читателям самостоятельно разобраться, почему здесь присутствует font-size: 0.
Вариант #17 – flexbox
Ссылка на CodePen Этот вариант предлагают опытные верстальщики.
Про flexbox-ы написано масса статей. Для начинающих предлагаем ознакомиться вот с этим. Вариант с display: -webkit-box можно считать эквивалентным.
Плюсы и минусы:
– ничего не нужно задавать у внутреннего элемента;
– ну и если есть другие элементы –одно удовольствие их выравнивать flex-ом;
– конечно, сейчас это менее актуально, но помним про поддержку.
Вариант #18 – flex-direction: column
Как дополнение к предыдущему, раскрывает ваши возможности с flexbox-ами:
Ссылка на CodePen.
Плюсы и минусы:
– нужен, собственно, когда у Вас flex-direction: column.
Вариант #19 – flex + space-between
C flex-ами можно творить чудеса, например, очень ровно выровнять набор элементов.
Ссылка на CodePen. Можно считать, что варианты с space-around, margin: auto эквивалентны данному.
Вариант #20 – CSS Grid
CSS grid – это современный и самый мощный, в то же время простой и гибкий инструмент для организации сеток и выравнивания.
Ссылка на CodePen Здесь организуется сетка из трёх колонок (с автоматическим разбиением первой и последней). Сам .child располагается между 2-ой и третьей линий сетки (т. е. во второй колонке).
Это далеко не единственный способ выровнять внутренний див по центру с помощью CSS Grid.
Рекомендуем читателям ознакомиться.
Плюсы и минусы:
– современно;
– со временем станет менее актуально, но всё же.
Вариант #21 – JS
С помощью JS можно сделать то же самое. Это, безусловно считается моветоном, но знать про это нужно:
Ссылка на CodePen.
Да, обратите внимание на последнюю строчку. Вычислить один раз размер div недостаточно. Некоторая категория пользователей (к которым и относится автор) изменяет размер окна после открытия. Поэтому обновление размеров – тоже немаловажная часть.
Плюсы и минусы:
– делать с помощью JS то, что можно сделать с помощью CSS – это моветон;
– может быть полезно в совсем сложных случаях.
В принципе и всё. Надеюсь, подобный перечень способов натолкнёт на более подробное изучение некоторых возможностей CSS.
Если есть какие-то добавления – ждём ваших комментариев!
Приглашаем 13 июня на открытый урок «Особенности работы с WebAssembly».
Знакомимся с WebAssembly: разбираем архитектуру JavaScript-движка на примере V8, чтобы лучше понять, какое место занимает в нём WebAssembly. И изучаем примеры.
ЗАПИСАТЬСЯ