От автора: в конце семестра студенты сдают мне свои работы. В этих демо зачастую можно встретить очень длинный текст сбоку или под изображениями, или же наоборот, слишком большие изображения с небольшим отрывком текста. В работу дизайнера входит балансировка текста и изображений, чтобы все смотрелось гармонично: что-то одно не должно заглушать страницу за счет другого. Это крайне важно в выносках (небольшие отрывки текста с изображением), которые должны быть жидкими и уметь адаптироваться к изменению размера экрана и непредсказуемому изменению количества контента. После недолгих экспериментов я нашел идеальное решение, удовлетворяющее обоим условиям. Для этого нам понадобится flexbox и фоновые изображения.
Создание модулей
В базовую разметку входит тег figure с двумя тегами div внутри. Например, в демо выше эти теги находятся внутри элемента с классом column. Один из модулей показан ниже:
1 2 3 4 5 6 7 8 9 10 |
<div class="column"> <figure class="flex"> <div></div> <div> <h3>Aloe polyphylla Schönland ex Pillans</h3> <p>Endangered native of the Maluti Mountains…</p> </div> </figure> </div> |
Стили тега figure:
1 2 3 4 5 6 |
.flex { margin: 0; display: flex; border: 5px solid #333; margin-bottom: 2rem; } |
Первый div в модуле изначально пустой, мы «заполним» его фоновым изображением:
1 2 3 4 5 |
.flex div:first-child { flex: 1; background-size: cover; background-position: center; } |
Первый div имеет визуальный вес, равный 1. Второй div имеет значение 2, он будет в два раза шире первого по умолчанию:
1 2 3 4 |
.flex div:last-child { margin: 2rem; flex: 2; } |
Стили текста внутри тега figure:
1 2 3 4 5 6 7 8 9 10 |
.flex h3 { font-size: 1.5rem; margin-top: 0; font-weight: 400; } .flex p { font-size: 1rem; line-height: 1.4; font-weight: 400; } |
У последнего параграфа в div убран margin-bottom, чтобы он не входил в высоту блока:
1 2 3 |
.flex p:last-of-type { margin-bottom: 0; } |
Фоновые изображения в модулях задаются через псевдоклассы :first-of-type или nth-of-type:
1 2 3 |
.flex:first-of-type div:first-child { background-image: url("aloe-polyphylla.jpg"); } |
Эффект
Стили выше делают так, чтобы фотографии всегда заполняли левую часть модуля сверху донизу, сжимаясь и расширяясь в зависимости от изменения ширины адаптивного контейнера и количества контента. Можете поэкспериментировать, добавьте или удалите текст в модуле в CodePen демо.
Также можно перевернуть макет каждого модуля следующим образом:
1 2 3 |
.flex:nth-child(odd) { flex-direction: row-reverse; } |
Ограничения
Если сильно сжать окно браузера, изображения станут слишком высокими. В таком случае помимо изменений на стандартных брейкпоинтах (уменьшение margin, line-height, font-size, padding и т.д.) есть еще два варианта:
1. Изменить баланс изображений и текста, приравняв визуальный вес обоих дочерних элементов в модуле:
1 2 3 |
@media all and (max-width: 600px) { .flex div { flex: 1 !important; } } |
2. Перестроить модули в вертикальный макет:
1 2 3 4 |
@media all and (max-width: 400px) { .flex { flex-direction: column; } .flex div:first-child { min-height: 200px; } } |
Слишком большой, слишком маленький
Данный подход предполагает, что в каждом блоке выноски будет хотя бы чуть-чуть текста, но и не слишком много. По-настоящему продуманная система будет проверять оба случая: можно было бы использовать JS (или в будущем запросы элементов) для проверки соотношения сторон каждого блока, переключая flex-direction, если высота блока намного больше его ширины.
В принципе, свойство object-fit должно работать точно так же с обычными изображениями, расположенными рядом с текстом, однако в моих экспериментах с этим возникли проблемы. Также будет полезно почитать спецификацию CSS Grid. В дальнейших экспериментах я буду использовать оба подхода.
Источник: //thenewcode.com/
Редакция: Команда webformyself.