Вертикально вирівняний текст у блоці за допомогою Flexbox

16

Від автора: Flexbox виявляється вкрай корисним інструментом при проектуванні макетів у веб-дизайні. Тим не менш, в деяких випадках він погано підходить для вертикального вирівнювання тексту у блоці. Повернемося до прикладу, який я розбирав минулого тижня. Той метод працює, якщо текст в обох посиланнях однієї довжини. Якщо ж одну посилання обернути в тег, а іншу ні, то вирівнювання вже не працює.

Не найстрашніша проблема, але вона дратує, і я хотів би її вирішити. Для її рішення нам потрібно трохи JavaScript. Але спершу розмітка:


Вертикально вирівняний текст у блоці за допомогою Flexbox


Responsive Image Hinting: Using w


Techniques and Treatments for Background Images Retina


Вертикально вирівняний текст у блоці за допомогою Flexbox

CSS код як і в попередній статті.

JavaScript

Припущу, що такий тип навігації з’являється на сторінці один раз. Якщо це так, то я можу визначити кожен елемент меню окремо за допомогою querySelector:

var leftText = document.querySelector(«#prevnext a span.articlename»),
rightText = document.querySelector(«#prevnext a:last-child span.articlename»);

Всі маніпуляції з текстовими посиланнями відбуваються у функції matchHeight():

function matchHeight() {
var difference = leftText.offsetHeight — rightText.offsetHeight;
if (difference > 0) {
rightText.style.marginTop = «-» + difference+»px»;
}
if (difference < 0) {
leftText.style.marginTop = difference +»px»;
}
if (difference == 0 && (leftText.hasAttribute(«style») || rightText.hasAttribute(«style»))) {
leftText.removeAttribute(«style»);
rightText.removeAttribute(«style»);
}
}

Що робить функція:

Difference вимірює різницю висот між двома текстовими посиланнями. Значення може бути 0 (посилання на одній висоті), позитивним (ліва посилання вище правої) і негативним (тобто права посилання вище лівої).

У першому умови ми піднімаємо праву посилання на значення difference (за допомогою негативного top-margin).

У другому умови піднімається вже ліва посилання на величину різниці висот.

В останньому умови мінлива difference може прийняти значення » 0 » у випадку, якщо обидві посилання були спочатку однієї висоти, або вони вже були налаштовані (одну з них підняли). Також я додав перевірку на вбудовані стилі в посиланнях. Якщо у посиланнях присутній атрибут style, він видаляється, а обидві посилання вертикально вирівнюються.

Функція викликається після завантаження сторінки:

matchHeight();

Скрипт потрібно викликати кожен раз, коли текстова посилання обертається в блок-обгортку (змінюється висота елемента). Було б чудово додати оброблювач події, однак JS ще не вміє визначати зміни у висоті елементів. Можна було б використовувати події за властивістю transition, як це зробив Девід Уолш, але браузери поки що теж не розуміють такий функціонал, принаймні, у flexbox елементах. Замість цього я викликаю функцію при зміні розміру вікна за допомогою requestAnimationFrame:

window.addEventListener. («resize», function() {
window.requestAnimationFrame(matchHeight);
});

Затримка в макеті

У Chrome я зіткнувся з однією цікавою проблемою: браузер вирівнює текст при першому завантаженні сторінки. Якщо ж повторно оновити сторінку, нічого не працює. Браузер показує, що елементи мають однакову висоту, навіть якщо це не так. Я підозрюю, що це пов’язано з помилками макетування в браузері. Як я зрозумів, Chrome задає елементів однакову висоту при першому рендерінгу їх на сторінці після оновлення, а через деякий час трошки виправляє макет.

Рішення виявилося не з простих: setTimeout не спрацював, як я від нього очікував, те ж саме можна сказати і за обробник події для DOMContentLoaded. Спрацювало тільки подія load на JQuery об’єкт window:

$(window).bind(«load», function() {
matchHeight();
});