Наш ассоциированный член www.Bikinika.com.ua

Битва за базову лінію

  1. inline-table
  2. П робу флексбокси
  3. А якщо інакше?
  4. Всі разом
  5. П оследніе штрихи
  6. І того

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

  1. Для багаторядкових інлайн-блоків базової лінією є базова лінія останнього сатиричного боксу в звичайному потоці.

  2. Якщо всередині інлайн-блоку немає боксів звичайного потоку, або ж у інлайн-блоку варто overflow відмінний від visible, то базовою лінією стає нижня межа блоку.

Через ці проблем вийде вирівняти по базовій лінії тільки однорядкові блоки без заданого overflow, тоді як в будь-яких більш складних випадках вийде зовсім не те, що може бути потрібно.

Ось приклад: все три блоку мають display: inline-block. Перший - звичайний однорядковий і з великим паддінгом, другий - багаторядковий, але з меншим розміром шрифту, третій - однорядковий, але з overflow: auto.

I'm an inline-block

I'm an inline-block
With a second line

I'm an inline-block with an overflow auto

I'm an inline-block with an overflow auto

На цьому прикладі добре видно , Де у якого блоку знаходиться базова лінія.

inline-table

В CSS було одне місце, де вертикальне вирівнювання працювало * правильно * - display: inline-table. Замінюємо інлайн-блоки на нього і отримуємо, здавалося б, то, що потрібно:

I'm an inline-table

I'm an inline-table
With a second line

I'm an inline-table with an overflow auto

Але тут відразу видно: не працює overflow: auto. До того ж такого блоку потрібно задавати table-layout: fixed. Виходить ідеально, якщо не потрібен overflow: auto.

П робу флексбокси

Чи можна зробити блок з скроллбар, який буде правильно вирівнюватися? Тут на допомогу поспішають флексбокси, точніше, display: inline-flex. В теорії вони також мають правильне положення базової лінії, але що ми отримуємо на практиці?

I'm an inline-flex

I'm an inline-flex
With a second line

I'm an inline-flex with an overflow auto

Якщо ви подивіться на цей приклад в будь-якому браузері крім Firefox (так, навіть в IE 10 і 12-й Опері), то ви бачите ідельно вирівняні блоки.

Але в Fx блок з overflow: auto, раптово, працює аналогічно інлайн-блоку: втрачає базову лінію. Смуток, печаль, розчарування, чекаємо виправлення свежезарепорченного бага .

А якщо інакше?

Дуже здорово, що inline-flex сам по собі правильно вирівнюється щодо інших блоків, і, якби не баг Fx, все було б зовсім чудово. Але що якщо ми спробуємо вирівнювати не різні inline-flex відносно один одного, а елементи всередині флексбокса?

I'm an inline-flex

I'm an inline-flex
With a second line

I'm an inline-flex with an overflow auto

Оп! Все працює! Ось тільки ... Якщо окремі блоки з inline-flex самі по собі переносяться на новий рядок, то для елементів всередині флексбокса нам треба було б застосовувати flex-wrap. Але Firefox його не підтримував до версії 28.0.

Всі разом

Так! Але ж якщо inline-flex прокидає свою базову лінію нагору, а внутрішній блок з overflow: auto також має правильне вирівнювання навіть в Firefox, то можна ж поєднати! Додамо в кожен блок по додатковому елементу, нехай буде він ставити паддінгі і overflow вже на них:

I'm an inline-flex
With a second line

I'm an inline-flex with an overflow auto

I'm an inline-flex with an overflow auto

У нормальних браузерах нічого не змінилося, тепер подивимося на Firefox ... Так, блок вже вирівнюється не по нижній межі, але і не по базовій лінії. Хоча, виміряємо різницю: 10 пікселів. Це ж наш паддінг! Прибираємо паддінгі по черзі - все вирівнюється правильно, коли верхній паддінг стає дорівнює нулю. Ага, значить Fx в цьому випадку все робить майже вірно, ось тільки сплив новий баг. Поки ми чекаємо його виправлення , Позбудемося-ка від паддінга, замінивши його на псевдо-елемент:

I'm an inline-flex
With a second line

I'm an inline-flex with an overflow auto

I'm an inline-flex with an overflow auto

Ідеально!

П оследніе штрихи

Ну ладно, не ідеально. Залишається пара дрібниць, які можуть проявитися в десятому IE і в дванадцятій Опері.

В IE при заданій ширині флексбокса текст всередині нього не буде врапаться, навіть якщо не буде стояти white-space: nowrap. Досить дивний баг, обходиться або додаванням внутрішнього блоку явною ширини в 100%, або, що правильніше, -ms-flex-negative: 1.

В Опері дуже схожий баг - внутрішній блок не реагує на задану ширину, через що в блоці немає переносів. Єдиний спосіб це виправити, який я знайшов: додати батькові flex-direction: column - так як у нас завжди тільки один внутрішній елемент, це ні на що не вплине.

тепер ідеально . Ось останній приклад з різними варіантами, які переносяться з рядка на рядок:

Just some inline text

I'm an inline-flex
With a second line

I'm an inline-flex with an overflow auto

I'm an inline-flex with the text wrapped on the next lines

I'm just another inline-flex block with a lot of content and overflow: auto.

I'm just another inline-flex block with a lot of content and overflow: auto

Код виходить таким:

.flex {display: -ms-inline-flexbox; display: -webkit-inline-flex; display: inline-flex; / * Fixing Opera issue * / flex-direction: column; vertical-align: baseline; } .Flex-content {padding: 0 10px 10px; border: 1px solid lime; / * Fixing IE issue * / -ms-flex-negative: 1; } / * Fixing Fx issue * / .flex-content: before {content: ""; display: block; padding-top: 10px; }

І того

Ох вже цей Firefox! Якби не його баги (і один баг десятого IE), то ми могли б обійтися одним елементом для кожного інлайнового блоку, який ми хочемо вирівняти по базовій лінії. А якщо вам не потрібен overflow відмінний від visible, і ви не боїтеся таблиць, то можна спробувати використовувати display: inline-table.

Так, чи інакше, ми перемогли. Тепер можна вирівнювати блоки по їх базових ліній незалежно від їх складності, ура! Якщо ви хочете застосовувати цю техніку без зайвих блоків, настійно раджу піти і проголосувати за виправлення відповідних багів в багзілле.

А якщо інакше?
Але що якщо ми спробуємо вирівнювати не різні inline-flex відносно один одного, а елементи всередині флексбокса?

Новости