Боксовая модель
Вопрос
Из чего складывается ширина элемента и почему два соседних margin не суммируются?
Короткий ответ
Классическая модель content-box: width и height задают контент. Padding и border добавляются снаружи, итоговый размер больше заявленной ширины. border-box включает padding и border в width. В современных сбросах часто ставят box-sizing: border-box на все элементы, иначе сетка с паддингом вылезает из колонки.
Margin лежит уже вне border и в ширину по border-box не входит. Вертикальные margin соседей в обычном потоке схлопываются: остаётся больший, а не сумма. Горизонтальные не схлопываются. Схлопывание не происходит у flex- и grid-элементов, у float, и если между блоками есть padding, border или новый блок форматирования.
display: none убирает элемент из потока, места он не занимает. visibility: hidden место сохраняет, элемент невидим и не кликабелен. opacity: 0 место сохраняет, и элемент может ловить клики.
Разбор
Блок форматирования (BFC) создают, среди прочего, overflow, отличный от visible, display: flow-root, flex-контейнер, float. Внутри BFC вертикальные margin не выпадают наружу к родителю. Этим же лечат обтекание float: контейнер с BFC охватывает плавающие дети, иначе высота родителя схлопывается до нуля.
inline не принимает вертикальные margin и width так, как блок. inline-block строит бокс в строке и ширину принимает. Зазор между инлайн-блоками часто даёт пробел в HTML между тегами, не margin.
Процент у padding и margin считается от ширины содержащего блока, даже для вертикальных отступов. Высота в процентах требует явной высоты у родителя, иначе процент не от чего считать.
На что смотрят на senior
min-width: auto у flex-элемента не даёт колонке сжаться меньше контента. Длинное слово или картинка раздувают сетку, хотя у родителя задан max-width. Лечится min-width: 0 на ребёнке, которому разрешено сжиматься, плюс перенос или overflow.
Схлопывание margin у первого ребёнка с родителем двигает весь блок, хотя padding родителю не задавали. На макете это выглядит как «отступ прилип не туда».
Типичные ошибки
- Ждать, что
width: 100%плюс padding влезет в родителя приcontent-box. - Складывать вертикальные margin соседей в уме.
- Путать
display: noneиvisibility: hidden. - Ставить высоту в процентах внуку, у которого родительская высота
auto.
Задача
У блока width: 200px, padding: 20px, border: 2px solid, box-sizing: content-box. Какая полная ширина на экране? Что изменится при border-box?
Показать ответ
При content-box ширина контента 200. По бокам padding 20 + 20 и border 2 + 2. Полная ширина 244px.
При border-box заявленные 200px уже включают padding и border. Контентная область станет уже, наружный размер останется 200px. Margin в обоих случаях снаружи и в width не входит.