Балансування тексту і зображень з допомогою Flexbox

61

Від автора: в кінці семестру студенти здають мені свої роботи. У цих демо часто можна зустріти дуже довгий текст збоку або під зображеннями, або ж навпаки, занадто великі зображення з невеликим уривком тексту. В роботу дизайнера входить балансування тексту і зображень, щоб все виглядало гармонійно: щось одне не повинна заглушати сторінку за рахунок іншого. Це вкрай важливо у виносках невеликі уривки тексту з зображенням), які повинні бути рідкими і вміти адаптуватися до зміни розміру екрану і непередбачуваного зміни кількості контенту. Після недовгих експериментів я знайшов ідеальне рішення, що задовольняє обом умовам. Для цього нам знадобиться flexbox і фонові зображення.

Створення модулів

У базову розмітку входить тег figure з двома тегами div всередині. Наприклад, в демо вище ці теги знаходяться всередині елемента з класом column. Один з модулів показаний нижче:

Aloe polyphylla Schönland ex Pillans

Endangered native of the Maluti Mountains…

Стилі тега figure:

.flex {
margin: 0;
display: flex;
border: 5px solid #333;
margin-bottom: 2rem;
}

Перший div у модулі спочатку порожній, ми заповнимо» його фоновим зображенням:

.flex div:first-child {
flex: 1;
background-size: cover;
background-position: center;
}

Перший div має візуальний вагу, рівний 1. Другий div має значення 2, він буде в два рази ширше першого за замовчуванням:

.flex div:last-child {
margin: 2rem;
flex: 2;
}

Стилі тексту всередині тега figure:

.flex h3 {
font-size: 1.5 rem;
margin-top: 0;
font-weight: 400;
}
.flex p {
font-size: 1rem;
line-height: 1.4;
font-weight: 400;
}

В останнього параграфа div прибраний margin-bottom, щоб він не входив у висоту блоку:

.flex p:last-of-type {
margin-bottom: 0;
}

Фонові зображення в модулях задаються через псевдокласи :first-of-type або nth-of-type:

.flex:first-of-type div:first-child {
background-image: url(«aloe-polyphylla.jpg»);
}

Ефект

Стилі вище роблять так, щоб фотографії завжди заповнювали ліву частину модуля зверху донизу, стискаючись і розширюючись в залежності від зміни ширини адаптивного контейнера і кількості контенту. Можете поекспериментувати, додайте або видаліть текст у модулі в CodePen демо.

Також можна перевернути макет кожного модуля наступним чином:

.flex:nth-child(odd) {
flex-direction: row-reverse;
}

Обмеження

Якщо сильно стиснути вікно браузера, зображення стануть дуже високими. У такому випадку крім змін на стандартних брейкпоинтах (зменшення margin, line-height, font-size, padding тощо) є ще два варіанти:

1. Змінити баланс зображень і тексту, прирівнявши візуальний вага обох дочірніх елементів у модулі:

@all media and (max-width: 600px) {
.flex div { flex: 1 !important; }
}

2. Перебудувати модулі в вертикальний макет:

@all media and (max-width: 400px) {
.flex { flex-direction: column; }
.flex div:first-child { min-height: 200px; }
}

Занадто великий, занадто маленький

Даний підхід передбачає, що в кожному блоці виноски буде хоча б трохи тексту, але і не занадто багато. По-справжньому продумана система буде перевіряти обидва випадки: можна було б використовувати JS (або в майбутньому запити елементів) для перевірки співвідношення сторін кожного блоку, перемикаючи flex-direction, якщо висота блоку набагато більше його ширини.

В принципі, властивість object-fit має працювати точно так само зі звичайними зображеннями, розташованими поряд з текстом, проте в моїх експериментах з цим виникли проблеми. Також буде корисно почитати специфікацію CSS Grid. У подальших експериментах я буду використовувати обидва підходи.