Анимирование Flexbox с CSS

 

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

Случилось так потому, что HTML и CSS развивались эволюционно. В начале веб-страницы были похожи на однопоточные текстовые документы, чуть позже разбиение страницы на блоки делали таблицами, затем стало модным верстать float-ами, а после официальной смерти IE6 добавились еще и приемы с inline-block. В итоге мы получили в наследство гремучую смесь всех этих приемов, используемую для построения лейаутов 99,9% всех существующих веб-страниц.

Спецификация CSS Flexible Box Layout Module (в народе Flexbox) призвана координально изменить ситуацию в лучшую сторону при решении огромного количества задач. Flexbox позволяет контролировать размер, порядок и выравнивание элементов по нескольким осям, распределение свободного места между элементами и многое другое.

Все уже знают про Flexbox. Кто-то уже использует его, кто-то только изучает, а кто-то недоумевает, чем он лучше таблиц. Пока вы занимаетесь этим, поделюсь с вами приятной новостью: flexible-контейнеры неплохо анимируются с помощью CSS transition.

Расскажу, как это использовать и что с этим можно делать.

Под анимацией я имею в виду изменение размеров контейнеров. Казалось бы, ничего удивительного, ведь есть transition: width 0.3s ease. Однако анимация flexible-элементов подразумевает, что размеры нескольких контейнеров изменяются одновременно. Это дает безграничные просторы для анимирования изменения размеров лэйаута. Например, сейчас очень популярно меню, которое схлопывается, оставляя видимыми только иконки.

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

[css]
.menu {
flex: 0.0001 1 180px;
transition: flex 0.3s ease;
}
.collapsed .menu {
flex: 0.0001 1 48px;
}
[/css]

Код для анимирования изменения размеров умещается в одну строку. В качестве CSS-свойства, которое будет анимировано, передаем «flex».
Немного странно здесь выглядит значение flex-grow. Это фактор расширяемости, который указывает, насколько хорошо будет растягиваться контейнер относительно других контейнеров, если родительский элемент имеет свободное место после расчета базовых размеров вложенных элементов. Чем меньше это значение относительно других, тем меньше контейнер будет расширяться. Если использовать значение 0, то ширина (или высота) элемента будет фиксированной. Если же ширина будет фиксированной, то возникает проблема с анимацией: более старая версия Google Chrome напрочь отказалась анимировать изменение размеров при значении flex-grow равным нулю. Есть вероятность, что в некоторых версиях браузеров такая проблема все еще существует.

Фотогалерея

css_1
При наведении курсора будем показывать выбранную фотографию в увеличенном формате

Для расположения фотографий будем использовать Flexbox, а изображения вставим через background-image:

[html]
<div class="items-row">
<div class="item img1"></div>
<div class="item img2"></div>
<div class="item img3"></div>
<div class="item img4"></div>
<div class="item img5"></div>
</div>
[/html]

[css]
.items-row {
display: flex;
flex-flow: row nowrap;
}
.item {
flex: 1 1 20%;
}
.img1 {
background-image: url(‘http://bzdnul.ru/?1′);
background-repeat: no-repeat;
}
[/css]

Элементы flex-контейнера занимают изначально по 20% от ширины и расширяются/сжимаются. Чтобы активный элемент увеличивался при наведении курсора, добавим правило, которое устанавливает фиксированную ширину 400 пикселей и уменьшает расширяемость/сжимаемость элемента почти до нуля:

[css]
.item:hover {
flex: 0.000000001 0.00000001 400px;
}
[/css]

При наведении курсора все неактивные элементы сожмутся, потому что имеют значение flow-shrink: 1, а активный элемент останется шириной 400 пикселей, потому что он почти несжимаем.

Добавление анимации:

[css]
.item {
transition: flex 0.4s ease;
}
[/css]

Если пойти еще дальше, то можно сделать несколько рядов фотографий и при наведении курсора увеличивать не только ширину, но и высоту. Для этого надо повторить то же самое, но с flex-flow: column nowrap;.

css_2

Производительность

Редкое обсуждение анимации обходится без разговоров о FPS. Поэтому на компе я измерял FPS для последней демки. И вот что я получил: FPS 44.5(на слабом компе).

Да, выглядит неплохо. Да и вообще я как-то замерял скорость отрисовки интерфейса сделанного с помощью Flexbox и аналогичного, сделанного на float’ах. Интерфейсы включали в себя по 1500 элементов. Разница в рендеринге составляла около 10 мс на десктопе и около 15-20 мс на мобильном устройстве. Поэтому, если производительность для вас решающий фактор, то вы проиграете немного.

Поддержка браузерами

Это не кроссбраузерная радость. Поскольку Flexbox работает в IE10+, соответственно, и его анимация будет работать не менее, чем с 10-й версии. Как правильно заметил мой друг, приведенный код не будет работать в IE вообще. Остается надеяться, что Microsoft последует примеру других и со временем начнет поддерживать эту анимацию. С другой стороны, для приведенного примера нетрудно сделать фоллбэк, который будет более-менее прилично отображать фотографии в маленьком размере и увеличивать их с помощью какого-нибудь расширения.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *