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

298

Від автора: 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();
});