Как выровнять содержимое с другим разделом, если они размещены в разных обертках
На днях я работал над макетом статьи и наткнулся на интересную задачу. Вот:
Как видите, у нас есть следующее:
- Основной заголовок: логотип и навигация
- Заголовок статьи: заголовок и тизер
- Содержание тела
Основной заголовок обернут элементом фиксированной ширины, центрированным по горизонтали.
<header class="site-header">
<div class="wrapper">
<!-- Header content -->
</div>
</header>
.wrapper {
max-width: 1100px;
margin-left: auto;
margin-right: auto;
padding-left: 1rem;
padding-right: 1rem;
}
Для шапки статьи он ни во что не обёрнут и живёт сам по себе.
<header class="site-header">
<div class="wrapper">
<!-- Header content -->
</div>
</header>
<div class="article-header">
<h1><!-- Title --></h1>
<p>!-- Description --></p>
</div>
Проблема здесь кроется в заголовке статьи. Если вы заметили на рисунке выше, он имеет отступы слева, что делает его совмещенным с началом логотипа. Сначала это кажется выполнимым, но вы передумаете при изменении размера экрана.
На следующем рисунке размер экрана стал больше. Обратите внимание, что заголовок статьи не совпадает с логотипом.
Когда размер экрана меньше, проблема также возникает.
Напомним, что проблема, которую мы здесь пытаемся решить, состоит в том, чтобы значение padding-left
было динамическим в зависимости от расстояния от левого края экрана до начала обертки содержимого.
Рассмотрим следующий рисунок. Основной заголовок и основное содержимое заключены в элемент фиксированной ширины, а заголовок статьи — нет. Чего мы хотим добиться, так это значения динамического заполнения для заголовка статьи.
Чтобы добиться этого, нам нужно немного посчитать. Вот простыми словами:
динамическое заполнение = (ширина области просмотра - ширина оболочки) / 2
Возьмем следующий пример.
Учитывая значения, которые у нас есть, вот значение динамического заполнения:
динамическое заполнение = (1300 - 1100) / 2 = 100
Вам может быть интересно, зачем делить на 2? Ну, поскольку у нас есть динамические области и слева, и справа, нам нужна только одна сторона.
Решение
В CSS мы будем использовать следующее для достижения вышеуказанного:
- Единицы области просмотра
- функция
calc()
- функция сравнения
max()
- CSS-переменные
Мы можем использовать значение 100vw
, чтобы получить полную ширину области просмотра.
.article-header {
padding-left: calc(100vw - calc(1100px / 2));
}
Таким образом, значение padding-left
будет динамическим и сделает содержимое заголовка статьи выровненным с логотипом и навигацией.
Тем не менее, мы не закончили. Нам нужно учитывать горизонтальный отступ .wrapper
.
.article-header {
padding-left: calc(100vw - calc(1100px / 2) - 32px);
}
32px
— это сумма левого и правого отступов.
Обработка отступов на мобильных устройствах
Поскольку мы вычли значение отступа из оболочки, отступ заголовка статьи будет равен нулю на мобильных устройствах.
Чтобы вернуть заполнение обратно, нам нужна помощь функции CSS max()
. Цель состоит в том, чтобы дать ему минимальное значение для заполнения.
.article-header {
padding-left: max(1rem, calc(100vw - calc(1100px / 2) - 32px));
}
Таким образом, горизонтальный отступ будет не менее 1rem и станет динамическим, когда размер окна просмотра станет больше.
Использование переменных CSS
Чтобы сделать вещи еще более абстрактными, мы можем добавить все вышеперечисленное в одну переменную CSS, чтобы мы могли использовать ее в разных местах.
:root {
--wrapper-width: 1100px;
--wrapper-padding: 16px;
--space: max(
1rem,
calc((100vw - calc(var(--wrapper-width) - var(--wrapper-padding) * 2)) / 2)
);
}
.article-header {
padding-left: var(--space);
}
Единственная проблема с 100vw
В Mac OS полосы прокрутки по умолчанию не видны, если пользователь не выбрал это в настройках системы. Если полосы прокрутки видны по умолчанию, 100vw
будет равно 100% ширины окна просмотра минус ширина полосы прокрутки. Это вызовет проблему несоосности.
Поскольку элемент не находится в оболочке, мы можем вместо этого заменить 100vw
на 100%
, и он будет работать, как и ожидалось.
:root {
--wrapper-width: 1100px;
--wrapper-padding: 16px;
--space: max(
1rem,
calc((100% - calc(var(--wrapper-width) - var(--wrapper-padding) * 2)) / 2)
);
}
.article-header {
padding-left: var(--space);
}
Обновление: 15 марта 2022 г.
Дэнни Винтер напомнил мне, что max()
будет выполнять математические операции без использования функции calc()
. Аккуратный!
:root {
--space: max(
1rem,
100% - (var(—wrapper) - ((var(—wrapper-padding) * 2) / 2))
);
}
Вот и все, что касается этого маленького CSS-трюка. Надеюсь, вы узнали что-то новое!