January 18, 2019

Flexbox трюки

1. Липкий футер

HTML

<body>
  <header></header>
  <main></main>
  <footer></footer>
</body>

CSS

body {
 margin: 0;
 display: flex;
 flex-direction: column;
 min-height: 100vh;
}

header, footer {
 height: 50px; // or another
}
main {
 flex: 1 0 0;
}

2. min-width имеет значение

Возможно, ты думаешь, что несложно заставить все flex-элементы внутри flex-контейнера сжиматься, для того чтобы уместить контент. Наверняка, если ты укажешь flex-shrink: 1 на элементах, они так и будут себя вести, правда?

Может, пример.

Скажем, у тебя есть часть DOM, которая отображает книгу на продажу и кнопку чтобы ее купить.

Ты разместил все с помощью flexbox и все хорошо.

.book {
  display: flex;
}
.book .description {
  font-size: 30px;
}
.book .buy {
  margin-left: auto;
  width: 80px;
  text-align: center;
  align-self: center;
}

(Поскольку ты хочешь кнопку «Купить» справа — даже для очень коротких названий — ты, будучи умным, указал margin-left: auto)

Название книги довольно длинное, поэтому оно использует столько пространства сколько может и затем переходит на следующую строку. Ты счастлив, жизнь прекрасна. Ты блаженно отправляешь свой код в продакшн, с уверенностью, что он выдержит все.

И потом получаешь неприятный сюрприз. Совсем не хорошего рода.

Некий дурень, много о себе возомнивший, написал книгу с длинным словом в названии.

Все сломано!

Если красная граница обозначает ширину смартфона, и ты скрываешь переполнение (overflow: hidden), ты только что потерял свою кнопку «Купить». Твой коэффициент конверсии — как и эго бедного автора — будет страдать.

(Примечание: к счастью, там где я работаю, есть хорошая QA команда, которая наполнила нашу базу данных разнородным текстом, наподобие такого. В частности, именно эта проблема побудила меня прочитать спецификацию.)

Оказывается, такое поведение происходит из-за того, что min-width элемента описания изначально установлена в auto, что в данном случае равняется ширине слова Electroencephalographically(электроэнцефалографически). Flex-элементу буквально не разрешается быть уже чем это слово.

Решение? Переопределить эту проблемную минимальную ширину min-width: auto установив min-width: 0, указывая flexbox'у, что этот элемент может быть уже, чем содержимое внутри него.

Теперь за управление текстом внутри элемента отвечаешь ты. Я предлагаю перенести слово. Таким образом, твой CSS будет выглядеть так:

.book {
  display: flex;
}
.book .description {
  font-size: 30px;
  min-width: 0;
  word-wrap: break-word;
}
.book .buy {
  margin-left: auto;
  width: 80px;
  text-align: center;
  align-self: center;
}

Результат будет таким:

3. Не используй margin или padding в %

Это не просто уровня «лучшая практика», это уровня «совет-от-бабушки», так что просто делай что говорят и не задавай вопросов.

«Авторам следует полностью избегать использования процентов в padding'ах или margin'ах на flex-элементах» — с любовью, спецификация flexbox.

4. Свойство Flex

  • Если я хочу, чтобы элемент немного сжимался, когда места недостаточно, но не тянулся шире чем ему надо: flex: 0 1 auto или flex: initial
  • Если мой flex-элемент должен тянуться для заполнения всего доступного пространства, и немного сжиматься если места не хватает: flex: 1 1 auto или flex: auto
  • Если мой элемент не должен менять размеры совсем: flex: 0 0 auto или flex: none