Изучаем flexbox и как его применять. CSS Grid и Flexbox: сравнение на практике

Модуль Flexbox Layout (Flexible Box) направлен на то чтобы предоставить более эффективный способ расположения, выравнивания и распределения свободного пространства между элементами в контейнере, даже когда их размер заранее неизвестен и/или динамичен (поэтому слово "flex").

Основная идея гибкой (flex) разметки заключается в том, чтобы предоставить контейнеру возможность изменять ширину/высоту (и порядок) своих элементов, для того чтобы наилучшим образом заполнить доступное пространство (в основном для размещения на всех типах и размерах экранов). Flexbox контейнер расширяет элементы чтобы заполнить свободное пространство или сжимает их чтобы избежать переполнения.

Самое главное, что Flexbox это направленный агностик в отличии от обычных раскладок (блоков основанных на вертикальном позиционировании и строковых элементов основанных на горизонтальном позиционировании). Не смотря на то что они достаточно хорошо работают, им не хватает гибкости для поддержки больших или сложных приложений (особенно когда речь идёт об изменении ориентации, изменении размеров, растягивании, сжатии и т. д.).

Примечание. Flexbox больше подходит для компонентов приложения и небольших макетов, тогда как CSS Grid предназначен для более масштабных макетов.

Основы и терминология

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

Если обычная система компоновки основана на блочных и строковых направлениях, то Flexbox основан на "flex-flow направлениях". Пожалуйста взгляните на этот рисунок из спецификации, объясняющий основную идею Flexbox.

В основном элементы будут располагаться вдоль основной оси (от main-start к main-end) или попереченой оси (от cross-start к cross-end).

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

CSS Flexible Box Layout Module

Chrome for Android

Браузер Blackberry начиная с 10 версии поддерживает новый синтаксис.

Свойства для контейнера

Свойства для элементов

Свойства для родительского элемента (Flex-контейнера)

display

Определяет flex-контейнер; строковый или блочный зависит от переданного значения. Включает flex-контекст для всех своих прямых, дочерних элементов.

Container { display: flex; /* или inline-flex */ }

Обратите внимание, что CSS колонки не влияют на flex-контейнер.

flex-direction


Устанавливает основную ось, таким образом определяет направление элементов расположенных в контейнере. Flexbox (помимо опциональной обёртки) представляет собой концепцию однонаправленного макета. Думайте о flex-элементах, прежде всего как горизонтальных строках или вертикальных колонках.

Container { flex-direction: row | row-reverse | column | column-reverse; }

  • row (по умолчанию) - слева направо в ltr ; справа налево в rtl ;
  • row-reverse - справа налево в ltr ; слева направо в rtl ;
  • column - тоже самое что row , только сверху вниз;
  • column-reverse - тоже самое что row-reverse , только снизу вверх;

flex-wrap


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

Container{ flex-wrap: nowrap | wrap | wrap-reverse; }

  • nowrap (по умолчанию) - все flex-элементы будут расположены на одной строке;
  • wrap - flex-элементы будут расположены на нескольких строках, сверху вниз;
  • wrap-reverse - flex-элементы будут расположены на нескольких строках, снизу вверх;

justify-content


Определяет выравнивание вдоль основной оси. Это помогает распределить свободное пространство, оставшееся после того как все фиксированные и не фиксированные по ширине flex-элементы достигли максимального размера. Оно также помогает осуществлять некоторый контроль над выравниванием элементов, когда они переполняют строку.

Container { justify-content: flex-start | flex-end | center | space-between | space-around; }

  • flex-start (по умолчанию) - элементы прижимаются к началу строки;
  • flex-end - элементы прижимаются к концу строки;
  • center - элементы располагаются по центру вдоль строки;
  • space-between - элементы размещаются равномерно на линии; первый элемент находится в начале строки, последний элемент находится в конце строки;
  • space-around - элементы размещаются равномерно на линии с одинаковым пространством возле них. Обратите внимание, что визуально пространство не одинаковое, так как у всех элементов одинаковое пространство с обеих сторон. У первого элемента будет одна единица пространства со стороны контейнера, но две единицы между ним и следующим элементом, потому что у следующего элемента также по одной единице с двух сторон.

align-items


Это свойство определяет поведение flex-элементов вдоль поперечной оси на текущей строке. Думайте о нём как о , только для поперечной оси (перпендикулярной основной оси).

Container { align-items: flex-start | flex-end | center | baseline | stretch; }

  • flex-start - элементы размещаются в начале поперечной оси;
  • flex-end - элементы размещаются в конце поперечной оси;
  • center - элементы располагаются по центру поперечной оси;
  • baseline - элементы выравниваются по базовой линии;
  • stretch (по умолчанию) - растягиваются чтобы заполнить весь контейнер (по-прежнему соблюдают min-width / max-width);

align-content


Примечание. Это свойство не действует, когда есть только одна строка flex-элементов.

Container { align-content: flex-start | flex-end | center | space-between | space-around | stretch; }

  • flex-start - строки располагаются в начале контейнера;
  • flex-end - строки располагаются в конце контейнера;
  • center - строки размещаются по центру контейнера;
  • space-between - строки распределяются равномерно, первая строка располагается в начале контейнера, а последняя строка в конце;
  • space-around - строки распределяются равномерно, с одинаковым расстоянием между ними;
  • stretch (по умолчанию) - строки растягиваются по всей ширине, чтобы занять оставшееся пространство;

Свойства для дочерних элементов (Flex элементов)

order


По умолчанию, все элементы располагаются в исходном для них порядке. Однако, свойство order управляет порядком, в котором располагаются элементы внутри контейнера.

Item { order: ; }

flex-grow


Свойство определяет возможность элемента увеличиваться в размере, при необходимости. Оно принимает безразмерное значение в качестве пропорции, которое определяет какое количество свободного пространства внутри контейнера должен занимать элемент.

Если у всех элементов свойство flex-grow установлено в 1 , то свободное пространство внутри контейнера будет равномерно распределено между всеми элементами. Если у одного из элементов значение установлено в 2 , то элемент будет занимать в два раза больше пространства, чем остальные (по крайней мере, попытается).

Item { flex-grow: ; /* по умолчанию 0 */ }

Нельзя указывать отрицательные числа.

flex-basis

Определяет размер элемента по умолчанию, до распределения оставшегося пространства. Это может быть длина (20%, 5rem и т.д.) или ключевое слово. Ключевое слово auto означает "выглядеть как моё свойство width или height ". Ключевое слово content означает что "размер основан на содержимом элемента" - это ключевое слово пока не очень хорошо поддерживается, поэтому его трудно проверить, а ещё труднее узнать что делают его братья min-content , max-content и fit-content .

Item { flex-basis: | auto; /* по умолчанию auto */ }

Если установить значение 0 , то дополнительное пространство вокруг содержимого не будет учитываться. Если установить auto , дополнительное пространство будет распределяться на основе значения .

flex

Это сокращение для , и . Второй и третий параметры (flex-shrink и flex-basis) не обязательны. Значение по умолчанию установлено в 0 1 auto .

Item { flex: none | [ <"flex-grow"> <"flex-shrink">? || <"flex-basis"> ] }

align-self


Это свойство позволяет переопределить выравнивание по умолчанию (или заданное с помощью свойства ) для отдельных flex-элементов.

Пожалуйста посмотрите на объяснение свойства , чтобы понимать доступные значения.

Item { align-self: auto | flex-start | flex-end | center | baseline | stretch; } .item { align-self: auto | flex-start | flex-end | center | baseline | stretch; }

Обратите внимание, что float , clear и vertical-align не оказывают никакого влияния на flex-элемент.

Примеры

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

Parent { display: flex; height: 300px; } .child { width: 100px; height: 100px; margin: auto; }

Это зависит от того, что margin , установленный в auto у flex-контейнера, поглощает дополнительное пространство. Таким образом, установка вертикального margin в auto у элемента, сделает элемент идеально центрированным по обеим осям.

Теперь давайте используем ещё несколько свойств. Рассмотрим список из 6 элементов, все с фиксированным размером в эстетическом отношении, но они могут быть автоматическими. Мы хотим, чтобы они были равномерно распределены вдоль горизонтальной оси и чтобы при изменении размера браузера всё было в порядке (без медиа-запросов!).

Flex-container { display: flex; flex-flow: row wrap; justify-content: space-around; }

Готово! Всё остальное, это лишь некоторые проблемы дизайна. Ниже приведён пример на CodePen, обязательно зайдите туда и попробуйте изменить размер окон, чтобы посмотреть что произойдёт.

Давайте попробуем что-нибудь ещё. Представьте, что у нас есть навигация расположенная по правому краю в самой верхней части экрана, но мы хотим чтобы она располагалась по центру на экранах среднего размера и была в одну колонку на маленьких экранах. Проще простого.

Navigation { display: flex; flex-flow: row wrap; justify-content: flex-end; } @media all and (max-width: 800px) { .navigation { justify-content: space-around; } } @media all and (max-width: 500px) { .navigation { flex-direction: column; } }

Давайте попробуем сделать что-нибудь ещё лучше, играясь с гибкостью наших flex-элементов! Как насчёт трёхколоночного mobile-first макета с шапкой и футером на всю ширину экрана, и чтобы не было зависимости от исходного порядка элементов.

Wrapper { display: flex; flex-flow: row wrap; } .header, .main, .nav, .aside, .footer { flex: 1 100%; } @media all and (min-width: 600px) { .aside { flex: 1 auto; } } @media all and (min-width: 800px) { .main { flex: 2 0px; } .aside-1 { order: 1; } .main { order: 2; } .aside-2 { order: 3; } .footer { order: 4; } }

Связанные свойства

Ошибки

Безусловно Flexbox не без ошибок. Лучшая коллекция, которую я видел представлена Philip Walton и Greg Whitworth"s Flexbugs . Это Open Source место для отслеживания всех ошибок, поэтому я думаю, что лучше всего просто оставить ссылку.

Модуль разметки Flexbox (от английского Flexible Box – гибкий блок ), находящийся на данный момент на этапе «Возможная рекомендация » стандартизации W3C (W3C Candidate Recommendation ) нацелен на обеспечение более эффективного способа разметки, выравнивания и распределения места между элементами в контейнере, даже если их размер неизвестен и/или определяется динамически (вот почему его назвали «гибкий» ).

Основная идея, стоящая за гибкой разметкой – это наделить контейнер способностью изменять высоту/ширину (и порядок ) его элементов для оптимального заполнения доступного пространства (в основном для поддержки всех видов и размеров экранов ).

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

Что наиболее важно, разметка Flexbox не зависит от направления, в противоположность обычным разметкам (блокам, которые ориентированы вертикально и строчным элементам, располагающимся горизонтально ).

И хотя элементы обычной разметки хорошо работают для страниц, им не хватает гибкости (и это не игра слов ) для поддержки больших и сложных приложений (особенно если речь заходит об изменении ориентации, размеров, растяжении, сжатии и так далее ).

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

Основные понятия и термины

Так как Flexbox это целый модуль, а не отдельное свойство, он включает в себя много элементов, в том числе и целый набор свойств. Некоторые из них предназначены для применения к контейнеру (родительскому элементу, известному как flex-контейнер ), в то время как другие должны быть применены к дочерним элементам (назовем их flex-элементы ).

Если обычная разметка основывается на направлениях блоков и строчных элементов, то flex -разметка базируется на направлениях flex -потока. Пожалуйста, обратите внимание на приведенную ниже схему из спецификации, объясняющую основную идею, стоящую за flex -разметкой:


В основном, элементы будут размещены либо вдоль главной оси (от точки main-start до main-end ), либо вдоль поперечной оси (от точки cross-start до cross-end ):
  • main axis – это главная ось flex -контейнера, вдоль которой размещаются flex -элементы. Будьте осторожны, она не обязательно располагается горизонтально, ее положение зависит от свойства flex-direction (смотрите ниже );
  • main-start | main-end — flex -элементы располагаются внутри контейнера, начиная от точки main-start , и доходят до точки main-end ;
  • main size – это ширина или высота flex -элемента, в зависимости от основной величины. В качестве значения свойства main size может быть установлено значение ширины или высоты;
  • cross axis – поперечная ось, перпендикулярная главной оси. Ее направление зависит от направления главной оси.
  • cross-start | cross-end – flex -строки заполняются элементами и размещаются в контейнере, начиная со стороны cross-start по направлению к стороне cross-end ;
  • cross size – ширина или высота flex -элемента, в зависимости от выбранной размерности. Свойство может иметь значение либо ширины, либо высоты поперечной размерности.

Свойства родительского класса (flex-контейнера)

display

Это свойство определяет flex -контейнер: строчной или блоковый, в зависимости от установленного значения. Также оно разрешает flex -контекст для всех его прямых потомков:

Container { display: flex; /* или inline-flex */ }

Отметим, что CSS -столбцы (columns ) не имеют эффекта во flex -контейнере.

flex-direction

Это свойство задает главную ось, определяющую направление, в котором размещаются flex -элементы во flex -контейнере. Flexbox (за исключением опционального обертывания ) является концептом однонаправленной разметки.

Представьте, что flex -элементы в первую очередь располагаются либо в горизонтальных, либо вертикальных колонках:

Container { flex-direction: row | row-reverse | column | column-reverse; }

  • row (по умолчанию ): слева направо для ltr; справа налево для rtl;
  • row-reverse : справа налево для in ltr; слева направо для rtl;
  • column : так же как row , но сверху вниз;
  • column-reverse : так же как row-reverse , но снизу вверх.

flex-wrap

По умолчанию flex -элементы попытаются втиснуться в одну линию. Вы можете изменить это, и обернуть элементы как нужно с помощью этого свойства. Здесь играет роль и направление, в котором располагаются новые линии:

Container{ flex-wrap: nowrap | wrap | wrap-reverse; }

  • nowrap (по умолчанию ): однострочный / слева направо для ltr; справа налево для rtl ;
  • wrap : многострочный / слева направо для ltr ; справа налево для rtl ;
  • wrap-reverse : многострочный / справа налево для ltr ; слева направо для rtl .

flex-flow (применяется к родительскому элементу flex-контейнера)

Это сокращенная форма свойств flex-direction и flex-wrap , которые вместе определяют главную и поперечную оси flex -контейнера. По умолчанию задается значение row nowrap :

flex-flow: <‘flex-direction’> || <‘flex-wrap’>

justify-content

Данное свойство задает выравнивание вдоль главной оси. Это помогает распределить лишнее свободное пространство, в том случае, если все flex -элементы в строке негибкие, либо гибкие, но достигли своего максимального размера. Также данное свойство позволяет получить контроль над выравниваем элементов, когда они выходят за границы строки:

Container { justify-content: flex-start | flex-end | center | space-between | space-around; }

  • flex-start (по умолчанию): элементы выравниваются к началу строки;
  • flex-end : элементы выравниваются к концу строки;
  • center : элементы выравниваются по центру строки;
  • space-between : элементы распределяются в строке равномерно: первый элемент располагается в начале строки, последний – в конце;
  • space-around : элементы распределяются в строке равномерно с одинаковым расстоянием между собой.

align-items

Это свойство определяет то, как по умолчанию располагаются flex -элементы относительно поперечной оси на текущей строке. Его можно считать версией justify-content для поперечной оси (перпендикулярной главной ):

Container { align-items: flex-start | flex-end | center | baseline | stretch; }

  • flex-start : граница элементов cross-start располагается на линии cross-start ;
  • flex-end : граница элементов cross-start располагается на линии cross-end ;
  • center : элементы располагаются по центру поперечной оси;
  • baseline : выравнивание элементов происходит согласно базовой линии;
  • stretch (по умолчанию ): элементы растягиваются для того, чтобы заполнить контейнер (с учетом значений min-width/max-width ).

align-content

Это свойство позволяет выравнивать строки внутри flex -контейнера, когда есть свободное место на поперечной оси, что схоже с тем, как свойство justify-content выравнивает отдельные элементы относительно главной оси.

Примечание : это свойство не будет работать, если есть только одна строка flex -элементов:

Container { align-content: flex-start | flex-end | center | space-between | space-around | stretch; }

  • flex-start : строки располагаются в начале контейнера;
  • flex-end : строки располагаются в конце контейнера;
  • center : строки располагаются посередине контейнера;
  • space-between : строки распределяются равномерно; первая строка – в начале контейнера, а последняя – в конце;
  • space-around : строки размещены равномерно на одинаковом расстоянии друг от друга;
  • stretch (по умолчанию ): строки растягиваются, чтобы заполнить оставшееся пространство.

Свойства дочерних элементов

(flex-элементы)

Order

По умолчанию, flex -элементы располагаются в порядке, заданном источником. Однако свойство order контролирует порядок, в котором элементы появляются во flex -контейнере:

Item { order: ; }

flex-grow

Это свойство позволяет flex -элементу «разрастаться » в случае необходимости. Оно принимает безразмерное значение, служащее в качестве пропорции. Это значение определяет, какой объем доступного пространства внутри flex -контейнера может занять элемент.

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

Item { flex-grow: ; /* default 0 */ }

flex-shrink

Это свойство определяет для flex -элементов возможность сжиматься в случае необходимости:

Item { flex-shrink: ; /* default 1 */ }

Отрицательные числа недопустимы.

flex-basis

Это свойство определяет размер элементов по умолчанию перед распределением оставшегося пространства:

Item { flex-basis: | auto; /* по умолчанию установлено auto */ }

flex

Это свойство является сокращенной формой для комбинации свойств flex-grow, flex-shrink и flex-basis . Второй и третий параметры (flex-shrink и flex-basis ) задаются опционально. Значения по умолчанию: 0 1 auto :

Item { flex: none | [ <"flex-grow"> <"flex-shrink">? || <"flex-basis"> ] }

align-self

Это свойство позволяет переопределить выравнивание, заданное по умолчанию (или определенное свойством align-items ) для отдельных flex -элементов.

Доступные значения вы можете найти в описании свойства align-items :

Item { align-self: auto | flex-start | flex-end | center | baseline | stretch; }

Обратите внимание, что float , clear и vertical-align не работают с flex -элементами.

Примеры

Давайте начнем с очень простого примера, решив практически ежедневную проблему: идеальное выравнивание по центру. Нет ничего проще, если использовать flexbox:

Parent { display: flex; height: 300px; /* Или что угодно */ } .child { width: 100px; /* Или что угодно */ height: 100px; /* Или что угодно */ margin: auto; /* Магия! */ }

Этот пример основывается на том факте, что свойство margin , установленное в значение auto , поглощает лишнее пространство. Поэтому такое задание отступа выравнивает элемент ровно по центру от обеих осей.

Теперь давайте воспользуемся еще несколькими свойствами. Предположим, что у нас есть список из 6 элементов, все они фиксированного размера (для эстетичности ), но с возможностью автоматического заполнения.

Мы хотим, чтобы они были красиво, равномерно распределены по горизонтальной оси таким образом, чтобы при изменении размера окна браузера, все смотрелось хорошо (без использования медиа запросов ):

Flex-container { /* Сначала создаем контекст flex-разметки */ display: flex; /* Затем определяем направление потока и хотим ли мы, чтобы элементы были обернуты. * Помните, что это то же самое, что и: * flex-direction: row; * flex-wrap: wrap; */ flex-flow: row wrap; /* Теперь мы определяем, как распределять оставшееся пространство */ justify-content: space-around; }

Готово! Все остальное — уже вопросы оформления. Здесь располагается демонстрация этого примера. Перейдите по ссылке и попробуйте изменить размер окна, чтобы посмотреть, что произойдет:

HTML:

CSS:

Flex-container { padding: 0; margin: 0; list-style: none; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; justify-content: space-around; } .flex-item { background: tomato; padding: 5px; width: 200px; height: 150px; margin-top: 10px; line-height: 150px; color: white; font-weight: bold; font-size: 3em; text-align: center; }

Давайте попробуем еще кое-что. Допустим, у нас на самом верху веб-сайта находится меню навигации, выровненное вправо, но мы хотим, чтобы на экранах среднего размера оно располагалось по центру, а для устройств с маленьким экраном – располагалось в один столбец. Все достаточно просто:

CSS:

/* Большие экраны*/ .navigation { display: flex; flex-flow: row wrap; /* Выравнивание элементов к концу строки по главной оси*/ justify-content: flex-end; } /* Средние экраны */ @media all and (max-width: 800px) { .navigation { /* Для экранов среднего размера, мы центрируем элементы, равномерно распределяя свободное пространство между ними */ justify-content: space-around; } } /* Небольшие экраны */ @media all and (max-width: 500px) { .navigation { /* Для небольших экранах мы используем направление не по строкам, а по столбцам */ flex-direction: column; } }

HTML:

CSS:

Navigation { list-style: none; margin: 0; background: deepskyblue; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; justify-content: flex-end; } .navigation a { text-decoration: none; display: block; padding: 1em; color: white; } .navigation a:hover { background: darken(deepskyblue, 2%); } @media all and (max-width: 800px) { .navigation { justify-content: space-around; } } @media all and (max-width: 600px) { .navigation { -webkit-flex-flow: column wrap; flex-flow: column wrap; padding: 0; } .navigation a { text-align: center; padding: 10px; border-top: 1px solid rgba(255,255,255,0.3); border-bottom: 1px solid rgba(0,0,0,0.1); } .navigation li:last-of-type a { border-bottom: none; } }

Давайте попробуем сделать еще лучше, поиграв с «гибкостью » flex -элементов. Как насчет мобильной разметки в три столбца с заголовком и подвалом во всю ширину? И с выводом элементов, независимым от порядка, заданного исходным кодом:

CSS:

Wrapper { display: flex; flex-flow: row wrap; } /* Задаем для всех элементов ширину в 100% */ .header, .main, .nav, .aside, .footer { flex: 1 100%; } /* В этом случае для ориентации на мобильные устройства мы полагаемся на исходный порядок: * 1. заголовок * 2. навигация * 3. основная часть * 4. боковая панель * 5. подвал */ /* Средние экраны*/ @media all and (min-width: 600px) { /* Обе боковые панели располагаются в одной строке */ .aside { flex: 1 auto; } } /* Большие экраны */ @media all and (min-width: 800px) { /* Инвертируем порядок вывода первой боковой панели и основной части, и указываем основному элементу необходимость занимать максимум в два раза больше места, чем две боковые панели */ .main { flex: 2 0px; } .aside-1 { order: 1; } .main { order: 2; } .aside-2 { order: 3; } .footer { order: 4; } }

HTML:

Header

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.

Footer

CSS:

Wrapper { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; flex-flow: row wrap; font-weight: bold; text-align: center; } .wrapper > * { padding: 10px; flex: 1 100%; } .header { background: tomato; } .footer { background: lightgreen; } .main { text-align: left; background: deepskyblue; } .aside-1 { background: gold; } .aside-2 { background: hotpink; } @media all and (min-width: 600px) { .aside { flex: 1 auto; } } @media all and (min-width: 800px) { .main { flex: 2 0px; } .aside-1 { order: 1; } .main { order: 2; } .aside-2 { order: 3; } .footer { order: 4; } }

Использование префиксов для flexbox

Flexbox требует использования вендорных префиксов для возможности поддержки большинством браузеров. Это включает в себя не только использование вендорных префиксов перед свойствами, но и полностью разные названия свойств и значений.

А все потому, что спецификация flexbox менялась с течением времени, создав «old » (старую ), «tweener «(промежуточную), и «new» (новую) версии.

Возможно, наилучший выход в этой ситуации - это писать код, используя новый (и финальный) синтаксис и пропускать CSS через Autoprefixer , который очень хорошо обрабатывает откаты к предыдущим версиям.

В качестве альтернативы, ниже приведен Sass метод @mixin для помощи с некоторыми префиксами, который к тому же раскрывает идею того, какие действия должны быть предприняты:

SCSS:

@mixin flexbox() { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; } @mixin flex($values) { -webkit-box-flex: $values; -moz-box-flex: $values; -webkit-flex: $values; -ms-flex: $values; flex: $values; } @mixin order($val) { -webkit-box-ordinal-group: $val; -moz-box-ordinal-group: $val; -ms-flex-order: $val; -webkit-order: $val; order: $val; } .wrapper { @include flexbox(); } .item { @include flex(1 200px); @include order(2); }

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

Разделена «версиями » flexbox на:

  • (new ) – означает поддержку последнего синтаксиса из спецификации (например, display: flex;

В этой статье познакомимся с технологией CSS Flexbox, предназначенной для создания гибких макетов веб-страниц.

Поддержка браузерами технологии CSS Flexbox

Технология Flexbox поддерживается уже почти всеми используемые на сегодняшний момент браузерами (с использованием префиксов: IE10+, Edge12+, Firefox 2+, Chrome 4+, Safari 3.1+, Opera 12.1+, iOS Safari 3.2, Opera mini, Android 2.1+, Blackberry 7+).

Основы Flexbox (сетка)

В основу Flexbox положена сетка. Она состоит всего из 2 элементов. Первый элемент – это flex-контейнер . Создание flex-контейнера осуществляется посредством добавления к необходимому HTML элементу CSS-свойства display со значением flex или flex-inline .

После этого все непосредственные дочерние элементы flex-контейнера (дети) автоматически становятся flex-элементами (2 элемент flexbox сетки).

HTML разметка:

1
2
3
4

Flex-container { display: flex; /* flex || inline-flex */ } Структура flexbox сетки

Flex-элементы по умолчанию занимают всю высоту flex-контейнера.

Значение flex или flex-inline определяет то, как flex-контейнер будет представлен на странице. Если его необходимо представить как блок , то используйте значение flex . Если элемент необходимо представить как строчный , то используйте значение flex-inline . В этом случае он будет занимать столько места странице, сколько необходимо для отображения его элементов.

Направление выстраивания flex-элементов

Указание направления выстраивания flex-элементов внутри flex-контейнера осуществляется посредством осей .


Во flexbox выделяют 2 оси . Первая ось называется основной или главной (по умолчанию направлена вправо). Вторая - поперечная (по умолчанию направлена вниз).

Элементы во flex-контейнере располагаются в одну линию (по умолчанию) даже тогда, когда им не хватает места. Выстраиваются flex-элементы в flex-контейнере по направлению основной оси.

Расположение элементов в контейнере по умолчанию (flex-элементы, которым не хватает места во flex-контейнере, вылезают за его пределы)

В CSS Flexbox разрешить перенос flex-элементов на новые линии (если им не хватает места в текущей линии) осуществляется с помощью установки flex-контейнеру CSS свойства flex-wrap со значением wrap или wrap-reverse .

Flex-wrap: wrap; /* nowrap (в одну линию - по умолчанию) wrap (разрешить перенос flex-элементов на новые линии) wrap-reverse (осуществлять перенос flex-элементов в обратном порядке) */

Значения wrap и wrap-reverse CSS-свойства flex-wrap определяют направление поперечной оси.

Установка направления главной оси flexbox осуществляется с помощью CSS-свойства flex-direction .

Flex-direction: row; /* row (вправо) - по умолчанию row-reverse (налево) column (вниз) column-reverse (вверх) */

С помощью этого свойства можно сделать так, чтобы flex-элементы располагались не горизонтально (строками), а вертикально (колонками).


Свойства flex-direction и flex-wrap можно указать с помощью универсального CSS свойства flex-flow:

Flex-flow: row nowrap; /* 1 значение - flex-direction, 2 значение - flex-wrap */

Выравнивание flex-элементов

Во Flexbox выравнивание элементов внутри контейнера осуществляется по двум направлениям (осям).

Выравнивание flex-элементов по направлению главной оси

Выравнивание элементов вдоль основной оси осуществляется с помощью CSS свойства justify-content:

Justify-content: flex-start; /* flex-start (flex-элементы выравниваются относительно начала оси) – по умолчанию flex-end (flex-элементы выравниваются относительно конца оси) center (по центру flex-контейнера) space-between (равномерно, т.е. с одинаковым расстоянием между flex-элементами) space-around (равномерно, но с добавлением половины пространства перед первым flex-элементом и после последнего) */ Варианты выравнивания flex-элементов вдоль главной оси

Выравнивание flex-элементов вдоль поперечной оси

Выравнивание flex-элементов во flex-контейнере по направлению поперечной оси осуществляется с помощью CSS-свойства align-items:

Align-items: stretch; /* stretch (растягиваются по всей длине поперечной оси) – по умолчанию flex-start (относительно начала поперечной оси) flex-end (относительно конца поперечной оси) baseline (относительно базовой линии) center (по центру) */ Варианты выравнивания flex-элементов вдоль поперечной оси

Выравнивание линий flex-контейнера

CSS Flexbox позволяет выравнивать не только сами flex-элементы, но и линии на которых они расположены.

Align-content: stretch /* stretch (растягиваются по всей длине поперечной оси) – по умолчанию flex-start (относительно начала поперечной оси) flex-end (относительно конца поперечной оси) center (по центру) space-between (равномерно, т.е. с одинаковым расстоянием между линиями) space-around (равномерно, но с добавлением половины пространства перед первой линией и после последней) */ Варианты выравнивания линий flex-контейнера

Свойство align-content имеет смысл использовать только тогда, когда flex-элементы во flex-контейнере располагаются на нескольких линиях. Чтобы это произошло, необходимо, во-первых, чтобы ширина всех flex-элементов была больше ширины flex-контейнера, а во-вторых flex-контейнер должен иметь в качестве CSS-свойства flex-wrap значение wrap или wrap-reverse .

CSS-свойство align-self

Свойство align-self в отличие от предыдущих (justify-content , align-items и align-content) предназначено для flex-элементов. Оно позволяет изменить выравнивание flex-элемента вдоль направления поперечной оси. Свойство align-self может принимать такие же значения как align-items .

Align-items: stretch; /* auto (по умолчанию) || stretch || flex-start || flex-end || baseline || center */

1
2
3
4

Flex-container { display: flex; width: 300px; height: 150px; align-items: center; padding: 10px; background-color: #efefef; } .flex-container_element-1, .flex-container_element-2, .flex-container_element-3, .flex-container_element-4 { flex-basis: 70px; text-align: center; padding: 15px; font-size: 30px; } .flex-container_element-1 { align-self: flex-start; background: #fe4; } .flex-container_element-2 { align-self: flex-end; background: pink; } .flex-container_element-3 { align-self: stretch; background: lime; } .flex-container_element-4 { align-self: auto; background: cyan; } Как работает CSS свойство align-self

Изменение порядка следования flex-элементов

По умолчанию flex-элементы отображаются во flex-контейнере в том порядке, в котором они расположены в HTML коде. Для изменения порядка следования одних flex-элементов относительно других в CSS Flexbox можно использовать свойство order . Данное CSS свойство выстраивает flex-элементы во flex-контейнере в порядке возрастания их номеров.

Order: 0; /* 0 (по умолчанию) целое положительное или отрицательное число */

Например:

...
...
...
...
CSS: .flex-container { display: flex; } /* переместим 2 flex-элемент в конец */ .flex-container_element-2 { order: 2; } /* передвинем 3 элемент до 2 */ .flex-container_element-3 { order: 1; } /* расположим 4 flex-элемент до 1 */ .flex-container_element-4 { order: -1; } Как работает CSS свойство order

Управление шириной flex-элемента

Во Flexbox есть несколько CSS свойств, определяющих то, какая ширина может быть у flex-элемента.

CSS-свойство flex-basis

Данное свойство предназначено для установления начальной ширины flex-элементу . Задавать значение ширины можно посредством различных единиц измерения, таких как px, %, em и др. По умолчанию данное свойство имеет значение auto (в этом случае ширина элемента будет рассчитываться автоматически на основании его содержимого).

Конечная ширина flex-элемента будет определяться в зависимости от значений CSS-свойств flex-grow и flex-shrink , которые установлены не только для этого элемента, но и для других flex-элементов этого flex-контейнера.

CSS-свойство flex-grow

Это свойство определяет, может ли начальная ширина flex-элемента увеличиваться (расти) . Увеличение ширины flex-элемента осуществляется за счёт свободного пространства линии . В качестве значения CSS-свойства flex-grow указывается целое число . Именно это значение и определяет (если оно больше или равно 1) какую часть свободного пространства flex-элемент заберёт себе.

Например:

...
...
CSS: .flex-container { display: flex; width: 600px; } .flex-container_element-1 { flex-basis: 40%; flex-grow: 1; } .flex-container_element-2 { flex-basis: 40%; flex-grow: 4; } Как работает CSS свойство flex-grow

В этом примере, если flex-элементы расположены на одной линии и в ней есть свободное пространство (600×(1-0,8)=120px):

  • к ширине элемента.flex-container_element-1 добавится 1/5 часть этого пространства (120×1/5=24px);
  • к ширине элемента.flex-container_element-2 добавится 4/5 части этого пространства (120×4/5=96px).

Другими словами, CSS свойство flex-grow позволяет не просто указать, что ширина flex-элемента может вырасти, но и задать, насколько эта величина может вырасти по отношению к другим элементам.

По умолчанию CSS свойство flex-grow имеет значение 0. Это означает, что flex-элемент не может расти (увеличивать свою ширину).

CSS-свойство flex-shrink

Данное свойство определяет, может ли ширина flex-элемента уменьшиться. Уменьшение ширины flex-элемента будет осуществляться только в том случае, если ширины линии будет не достаточно для отображения всех flex-элементов , расположенных в ней. Необходимая ширина рассчитывается на основании начальной ширины , который имеет каждый flex-элемент в ней.

Например:

...
...
CSS: .flex-container { display: flex; width: 500px; } .flex-container_element-1 { flex-basis: 300px; flex-shrink: 1; } .flex-container_element-2 { flex-basis: 300px; flex-shrink: 3; } Как работает CSS свойство flex-shrink

Ширина flex-контейнера 500px. Для отображения flex-элементов необходимо 600px. В итоге не хватает 100px. В этом примере уменьшаться могут 2 flex-элемента (.flex-container_element-1 и.flex-container_element-2). Ширина первого flex-элемента.flex-container_element-1 в данном случае составит 300 – 1/4*100= 275px. Ширина второго flex-элемента.flex-container_element-2 в данном случае составит 300 – 3/4*100= 225px.

Значение по умолчанию:

Flex-shrink: 1;

Если вам необходимо запретить уменьшение ширины flex-элементу , то в качестве значения свойства flex-shrink необходимо указать число 0.

CSS-свойство flex

Для удобной установки flex-grow , flex-shrink и flex-basis можно использовать CSS свойство flex .

Значение по умолчанию:

Flex: 0 1 auto; /* 0 - flex-grow (1 значение) 1 - flex-shrink (2 значение) auto - flex-basis (3 значение) */

Верстка макета страницы на CSS Flexbox

В этом разделе создадим простой адаптивный макет на Flexbox.

Структура макета будет состоять из 3 секций:

  • header (для вывода заголовка и основного меню);
  • main (для отображения основной части);
  • footer (для футера).

Основную часть (main) в свою очередь разделим ещё на 2 раздела (их позиционирование будем осуществлять с помощью CSS Flexbox). На больших экранах (>=992px) эти разделы выстроим горизонтально, а на остальных - вертикально (<992px).

[Шапка страницы...]
[Основная часть...]
[Футер...]
CSS: /* контейнер (устанавливает ширину блока в зависимости от ширины viewport) */ .container { position: relative; margin-left: auto; margin-right: auto; padding-right: 15px; padding-left: 15px; } @media (min-width: 576px) { .container { width: 540px; max-width: 100%; } } @media (min-width: 768px) { .container { width: 720px; max-width: 100%; } } @media (min-width: 992px) { .container { width: 960px; max-width: 100%; } } @media (min-width: 1200px) { .container { width: 1140px; max-width: 100%; } } /* flex-контейнер */ .row-flex { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; } /* CSS настройки flex-элементов */ .col-flex { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } /* ширина блоков article и aside по умолчанию */ .main_article, .main_aside { -webkit-box-flex: 0; -webkit-flex: 0 0 100%; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } /* ширина блоков article и aside для больших экранов */ @media (min-width: 992px) { /* 2/3 от ширины контейнера */ .main_article { -webkit-box-flex: 0; -webkit-flex: 0 0 66.666667%; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } /* 1/3 от ширины контейнера */ .main_aside { -webkit-box-flex: 0; -webkit-flex: 0 0 33.333333%; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } }

Для поддержки макета большинством браузеров добавим в CSS необходимые префиксы и max-width .

Для «превращения» блока во flex-контейнер будем использовать класс row-flex . Установку ширины каждому flex-элементу (main_article и main_aside) внутри flex-контейнера будем осуществлять с помощью CSS-свойства flex .


В качестве примера разметим посредством Flexbox ещё блок «Футер» и секцию раздела main-article «Интересненькое на сайте».

Секцию «Футер» разделим на 4 равные части (минимальная ширина одной части - 200px), а «Интересненькое на сайте» на 3 части (минимальная ширина одной части - 300px).

[Шапка страницы...]
[Основная часть...]
[Ещё 1...]
[Ещё 2...]
[Ещё 3...]

Дополнительный CSS:

Footer_block, .main_other_article { -webkit-flex-basis: 0; -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; }

Я хотел бы рассказать о FlexBox. Модуль Flexbox-верстки (flexible box — «гибкий блок», на данный момент W3C Candidate Recommendation) ставит задачу предложить более эффективный способ верстки, выравнивания и распределения свободного места между элементами в контейнере, даже когда их размер неизвестен и / или динамический (отсюда слово «гибкий»).

Главная задумка flex-верстки в наделении контейнера способностью изменять ширину / высоту (и порядок) своих элементов для лучшего заполнения пространства (в большинстве случаев — для поддержки всех видов дисплеев и размеров экранов). Flex-контейнер растягивает элементы для заполнения свободного места или сжимает их, чтобы предотвратить выход за границы.

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

Т.к. flexbox — это целый модуль, а не просто единичное свойство, он объединяет в себе множество свойств. Некоторые из них должны применяться к контейнеру (родительского элемента, так называемом flex-контейнера), в то время как другие свойства применяются к дочерним элементам, или flex-элементам.

Если обычный макет основывается на направлениях потоков блочных и инлайн-элементов, то flex-макет основывается на «направлениях flex-потока».

Flexbox

В основном элементы будут распределяться или вдоль главной оси (от main-start в main-end), или вдоль поперечной оси (от cross-start в cross-end).

main-axis — главная ось, вдоль которого располагаются flex-элементы. Обратите внимание, она обязательно должна быть горизонтальной, все зависит от качества justify-content.
main-start | main-end — flex-элементы размещаются в контейнере от позиции main-start позиции main-end.
main size — ширина или высота flex-элемента в зависимости от выбранной основной величины. Основная величина может быть либо шириной, или высотой элемента.
cross axis — поперечная ось, перпендикулярная главной. Ее направление зависит о тнаправления главной оси.
cross-start | cross-end — flex-строки заполняются элементами и размещаются в контейнере от позиции cross-start и позиции cross-end.
cross size — ширина или высота flex-элемента в зависимости от выбранной размерности равна этой величине. Это свойство совпадает с width или height элемента в зависимости от выбранной размерности.


Свойства
display: flex | inline-flex;

Определяет flex-контейнер (инлайновий или блочный зависимости от выбранного значения), подключает flex-контекст для всех его непосредственных потомков.

display: other values ​​| flex | inline-flex;

Имейте в виду:

CSS-столбце columns не работают с flex-контейнером float, clear и vertical-align не работают с flex-элементами

flex-direction

Применяется до родительского элемента flex-контейнера.

Устанавливает главную ось main-axis, определяя тем самым направление для flex-элементов, размещаемых в контейнере.

flex-direction: row | row-reverse | column | column-reverse

row (по умолчанию): слева направо для ltr, справа налево для rtl;
row-reverse: справа налево для ltr, слева направо для rtl;
column: аналогично row, сверху вниз;
column-reverse: аналогично row-reverse, снизу вверх.

flex-wrap

Применяется до родительского элемента flex-контейнера.

Определяет, контейнер однострочными или многострочным, а также направление поперечной оси, определяет направление, в котором будут располагаться новые строки.

flex-wrap: nowrap | wrap | wrap-reverse

nowrap (по умолчанию): однострочный / слева направо для ltr, справа налево для rtl;
wrap: многострочный / слева направо для ltr, справа налево для rtl;
wrap-reverse: многострочный / справа налево для ltr, слева направо для rtl.

flex-flow

Применяется до родительского элемента flex-контейнера.

Это сокращение для свойств flex-direction и flex-wrap, вместе определяют главную и поперечную оси. По умолчанию принимает значение row nowrap.

flex-flow < ‘flex-direction’> || < ‘Flex-wrap’>

justify-content

Применяется до родительского элемента flex-контейнера.

Определяет выравнивание относительно главной оси. Помогает распределить свободное место в случае, когда элементы строки не «тянутся», или тянутся, но уже достигли своего максимального размера. Также позволяет в некотором роде управлять выравниванием элементов при выходе за пределы строки.

justify-content: flex-start | flex-end | center | space-between | space-around

flex-start (по умолчанию): элементы сдвигаются к началу строки;
flex-end: элементы сдвигаются до конца строки;
center: элементы выравниваются на середину строки;
space-between: элементы распределяются равномерно (первый элемент в начале строки, последний — в конце)
space-around: элементы распределяются равномерно с равным расстоянием между собой и вне строки.

justify-content
align-items

Применяется до родительского элемента flex-контейнера.

Определяет поведение по умолчанию для того, как flex-элементы располагаются относительно поперечной оси на текущей строке. Считайте это версии justify-content для поперечной оси (перпендикулярной к основной).

align-items: flex-start | flex-end | center | baseline | stretch

flex-start: граница cross-start для элементов расположен позиции cross-start;
flex-end: граница cross-end для элементов расположен позиции cross-end;
center: элементы выравниваются по центру поперечной оси;
baseline: элементы выравниваются по своей базовой линии;
stretch (по умолчанию): элементы растягиваютcя, заполняя контейнер (с учетом min-width / max-width).


align-items
align-content

Применяется до родительского элемента flex-контейнера. Выравнивает строки flex-контейнера при наличии свободного места на поперечной оси аналогично тому, как это делает justify-content на главной оси. Примечание: это свойство не работает с однострочными flexbox.

align-content: flex-start | flex-end | center | space-between | space-around | stretch

flex-start: строки выравниваются относительно начала контейнера;
flex-end: строки выравниваются относительно конца контейнера;
center: строки выравниваются по центру контейнера;
space-between: строки распределяются равномерно (первая строка в начале строки, последняя — в конце)
space-around: строки распределяются равномерно с равным расстоянием между собой;
stretch (по умолчанию): строки растягиваются, заполняя свободное пространство.

align-content
order

По умолчанию flex-элементы располагаются в исходном порядке. Тем не менее, свойство order может управлять порядком их расположения в контейнере.

order 1

flex-grow

Применяется до дочернему элементу / flex-элемента. Определяет для flex-элемента возможность «расти» при необходимости. Принимает безразмерное значение, служит в качестве пропорции. Оно определяет, какую долю свободного места внутри контейнера элемент может занять. Если во всех элементов свойство flex-grow задано как 1, то каждый потомок получит внутри контейнера одинаковый размер. Если вы задали одному из потомков значение 2, то он займет в два раза больше места, чем другие.

flex-grow (по умолчанию 0)

flex-shrink

Применяется до дочернему элементу / flex-элемента.

Определяет для flex-элемента возможность сжиматься при необходимости.

flex-shrink (default 1)

Отрицательные числа не принимаются.
flex-basis

Применяется до дочернему элементу / flex-элемента. Определяет размер по умолчанию для элемента перед распределением пространства в контейнере.

flex-basis | auto (default auto)

flex

Применяется до дочернему элементу / flex-элемента. Это сокращение для flex-grow, flex-shrink и flex-basis. Второй и третий параметры (flex-shrink, flex-basis) необязательны. Значение по умолчанию — 0 1 auto.

flex: none | [< ‘Flex-grow «> <» flex-shrink’>? || < ‘Flex-basis’>]

align-self

Применяется до дочернему элементу / flex-элемента. Позволяет переопределить выравнивания, заданный по умолчанию или в align-items, для отдельных flex-элементов. Обратитесь к описанию свойства align-items для лучшего понимания доступных значений.

align-self: auto | flex-start | flex-end | center | baseline | stretch

Примеры
Начнем с очень-очень простого примера, встречается практически ежедневно: выравнивание точно по центру. Нет ничего проще, если использовать flexbox.

Parent { display: flex; height: 300px; } .child { width: 100px; / * Або що завгодно * / height: 100px; / * Або що завгодно * / margin: auto; / * Магія! * / }

Этот пример основывается на том, что margin под flex-контейнере, заданный как auto, поглощает лишнее пространство, поэтому задача отступления таким образом выровняет элемент ровно по центру по обеим осям.Теперь давайте используем какие-то свойства. Представьте набор из 6 элементов фиксированного размера (для красоты), но с возможностью изменения размера контейнера. Мы хотим равномерно распределить их по горизонтали, чтобы при изменении размера окна браузера все выглядело хорошо (без @media-запросов!).

Flex-container {
/ * Сначала создадим flex-контекст * /
display: flex;

/ * Теперь определим направление потока и хотим ли мы, чтобы элементы
переносились на новую строку
* Помните, что это тоже самое, что и:
* Flex-direction: row;
* Flex-wrap: wrap;
* /
flex-flow: row wrap;

/ * Теперь определим, как будет распределяться пространство * /
}

Готово. Все остальное — уже дело оформления. Давайте попробуем что-нибудь еще. Представьте, что нам нужна выровнена по правому краю навигация в самом верху нашего сайта, но мы хотим, чтобы она выравнивалась по центру для экранов среднего размера и превращалась в один столбец на маленьких. Все достаточно просто.

/ * Большие экраны * /
.navigation {
display: flex;
flex-flow: row wrap;
/ * Сдвигает элементы к концу строки по главной оси * /
justify-content: flex-end;
}

media all and (max-width: 800px) {
.navigation {
/ * Для экранов среднего размера мы выравниваем навигацию по центру,
равномерно распредляя свободное место между элементами * /
justify-content: space-around;
}
}

/ * Маленькие экраны * /
media all and (max-width: 500px) {
.navigation {
/ * На маленьких экранах вместо строки мы располагаем элементы в столбце * /
flex-direction: column;
}
}

Давайте поиграем с гибкостью flex-элементов! Как насчет ориентированного на мобильные устройства трёхколоночного макета с полноширинной шапкой и подвалом? И другим порядком расположения.

Wrapper {
display: flex;
flex-flow: row wrap;
}

/ * Задаем всем Элеметы ширину в 100% * /
.header, .main, .nav, .aside, .footer {
flex 1100%;
}

/ * В этом случае мы полагаемся на исходный порядок для ориентации на
* Мобильные устройства:
* 1 header
* 2 nav
* 3 main
* 4 aside
* 5 footer
* /

/ * Экраны среднего размера * /
media all and (min-width: 600px) {
/ * Оба сайдбара располагаются в одной строке * /
.aside {flex: 1 auto; }
}

/ * Большие экраны * /

Современный front-end разработчик активно должен уметь применять на практике различные инструменты, позволяющие автоматизировать процесс верстки макетов и программирования клиентской составляющей проекта. Для этого уже существует множество фреймворков, как больших, так и малых, системы сборки, пакетные менеджеры, целая куча пакетов для задач любого уровня, препроцессоры, шаблонизаторы и прочий "сахар", который создан упростить и повысить производительность работы специалиста в данной области.

К сожалению, начинающим фронтам бывает сложно разобраться в изобилии этих инструментов, так как тут нужно постоянно развиваться и знать основы верстки. И многие по этой причине продолжают верстать «по-дедовски», обычный css, с кучей повторяемых селекторов, верстка без понимания принципа различных сеток, дикие головные боли с различного рода центрированием и т.д.

Если раньше, миллион лет назад, верстали на таблицах, а потом перелезли на дивы, то сейчас уже без применения flexbox в сочетании с сетками или же готовым css-фреймворком, чувствую, что даже простая верстка на дивах скоро будет считаться «моветоном». Пока это еще не так, но насколько я наблюдаю (точнее, даже не успеваю наблюдать) за развитием в данной области различных методик и best practices, то скорее всего, такой вариант имеет место быть.

Конечно в этой маленькой заметке, я не смогу рассмотреть все must-have умения хорошего фронта и инструменты для комфортной работы, но некоторые основные принципы, позволяющие оттолкнуться и пойти дальше все же покажу и прокомментирую на примерах.

Верстаем адаптивно

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

Как известно, любой блочный элемент display: block по умолчанию занимает всю доступную ширину экрана, только если мы не определим его ширину явно (либо в px, либо в %) . Но даже если ему будет задана определенная таким образом ширина, то следующий после него блочный элемент будет идти после него с новой строки (этим, кстати и отличается block от inline, который будет следовать друг за другом). Это важный момент, его нужно просто понять, а для того чтобы понять, это дело легко просмотреть в инспекторе любого браузера.

Если же нам надо, чтобы блочные элементы соседствовали друг с другом, то необходимо обтеакание элементов (float), причем нужно задавать ширину блоков в %, чтобы браузер автоматически вычислял ширину в пикселях. Как распространенный пример, это блок контента, а рядом сайдбар. После обтекания элементов, незабываем использовать clearfix, сброс обтекания, чтобы не сломать верстку в дальнейшем.

Самым первым делом мы должны "уведомить" браузер, что хотим использовать адаптивное представление, в соответствии с которым любой браузер будет открывать страницу в этом режиме, делается это вот таким объявлением между тегами head документа:

Meta name="viewport" content="width=device-width, initial-scale=1"

Иными словами, ширина-устройства в масштабе 1:1. И если у вас верстка сделана не адаптивно, то скорее всего будут проблемы при таком отображении в мобильном представлении (скорее всего весь контент сожмется в "гармошку", если логически представить, что может произойти:). Вот с этих пор можно уже говорить о следующем шаге, который есть в любой grid системе или адаптивном фреймворке.

В любой grid системе есть брейкпоинты, точки перехода. Посмотрим на Bootstrap, когда при изменении ширины экрана (мобильный, планшетный вид, и т.д.), происходит проверка элемента, имеющего текущий колоночный класс (к примеру класс десктопа для колонки, в популярном фреймворке Bootstrap, это col-md-{x}, md - десктоп). Классы в свою очередь задают различную ширину в %, равную (100/12) · x, где x - коэффициент ширины, от 1 до 12.

Колоночные классы описывают поведение обтекания элементов: есть класс (в тоже время класс может быть для различных устройств) - обтекание задано, нет - ширина 100% (типично для представления контента на мобильных устройствах). А реализовано это поведение с помощью медиа-запросов, которые понимают все браузеры. Медиа-запрос - в css это понятие означает правило, при выполнении условия которого, подключаются соответствующие стили, например, ширина стала меньше 600px - подключаем новый блок стилей, переопределяющий старый. Например, колоночный класс col-md-{x} подключается по умолчанию от 992px и выше, и отключается до 992px. Но все брейкпоинты бутстраповские по умолчанию можно переопределить своими при компиляции сетки.

Вот и вся простая механика с дивами, которым нужно задать ширину в %, float:left; и очистить обтекание после колонок (в бутстрап колонки оборачиваются во враппер c классом row в этом случае), которые мы выстраиваем в ряд. Все это с легкостью можно реализовать самому и без всякой сетки, когда есть понятие, как это работает, просто в любой сетке прописаны классы и много кода уже написано, вашей задачей остается прописывать классы элементам, вот и все.

Мы же, немного пойдем дальше и рассмотрим еще один вариант. Использование флексбокс, заодно на практике создадим небольшой скелет адаптивной страницы с использованием этой новой технологии верстки. Вообще, грубо говоря, флексы позволяют избавить нас от головной боли типа центрирования, горизонтального и вертикального выравнивания в контейнере. А вкупе с медиа-запросами, имея ввиду описанную механику выше, можно выстроить очень качественный адаптивный шаблон с любым выравниванием, как по вертикали, так и по горизонтали. Играемся, вообщем, как захотим.

Тут хочется отметить, что ширина, заданная в %, как в случае с зоной контента и сайдбаром (шапка и подвал по умолчанию занимают всю ширину, 100%), при резайзинге (или открытии страницы на малом экране) сразу же автоматически пересчитывается. Это, пожалуй главное правило, задавать все в %, все остальное браузер сделает сам.

Простой адаптив

header (logo etc)
content
footer (copyright etc)

В дивах у нас пускай будет просто текст пока что, потренируемся выравнивать текст (по горизонтали/вертикали). Еще хорошая практика футер исключать из общего враппера, задавать html и body, height:100%, врапперу: min-height:100%, чтобы футер всегда был прижат к низу страницы.

Я привык использовать scss, приведу листинг кода на нем:

$grey: #808080; $h: 50px; html, body { margin: 0; height: 100%; } body { font-family: monospace, sans-serif; text-transform: uppercase; } .row { display: flex; } .vertical-center { align-items: center; justify-content: center; } .wrap { min-height: 100%; header, .content, .sidebar { border: 1px solid $grey; } header { height: $h; } .content { height: 100px; padding: 15px 15px 0 15px; border-top-width: 0; margin-right: 1%; width: 75%; } .sidebar { height: 120px; padding: 15px 15px 0 15px; border-top-width: 0; width: 25%; } } footer { height: $h; border: 1px solid $grey; }

display: flex; - вкл. flex-контекст; свойство flex-direction: row; - по умолчанию, если не укажем column явно. Это то что нам позволяет делать многие потрясающие вещи. Нe совсем уверен, но вроде пока что это свойство не везде поддерживается caniuse, но пора бы уже выкинуть все эти старые браузеры и установить современные, не так ли? :)

Еще задаем соотношение для ширины контент - сайдбар, 75% : 25%. Тот же самый эффект получился бы, если бы использовали бутстрап. Только с класами col-md-9 для контента ((100/12 · 9)% - ширина в процентах, 75) и col-md-3 для сайдбара ((100/12 · 3)% - ширина в процентах, 25)

Итак, давайте разберемся, что происходит и как работает флексбокс. Самое первое, это нужно задать display:flex тому контейнеру, в котором нам нужно производить центрирование, к примеру. В разметке у меня это шапка, подвал и контейнер, внутри которого контент и сайдбар. Самое простейшее, что эффетивно делает флексбокс здесь, так это просто берет и выравнивает текст, который в шапке и подвале, при помощи класса.vertical-center:


.vertical-center { align-items: center; // выравниваем по центру, по вертикали justify-content: center; // выравниваем по центру, по горизонтали }

В результате, текст выравнен в двух направлениях, в шапке и подвале. Осталась средняя часть, здесь, если бы мы не задали display:flex, то по умолчанию остался бы display:block, что в итоге с блоками контента и сайдбара, получилось вот так:

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

Но перед тем, как перейти к этому главному вопросу, для которого и создавалась эта заметка, давайте немного улучшим наш простой макет в плане адаптивности. Сейчас при ресайзе, контент и сайдбар не складываются друг под друга. Необходимо исправить это, так как, представьте себе, что весь текст при малых разрешениях будет некрасиво «спрессован» в области контента и сайдбара. Я не говорю уже про картинки. Кстати, изображениям, которые будут адаптивными обязательно надо задавать:


img{ display:block; max-width:100%; height:auto; }

Воспользуемся медиа-запросами. Улучшаем наш css, я его переписывать весь не буду, просто оставлю // ... * там где код тот же остался:


// .. $mobileBreak: 479px; html, body { // ... } body { // ... } .row { // ... } .middle { @media (max-width: $mobileBreak) { display: block; } } .vertical-center { // ... } .wrap { // ... header, .content, .sidebar { // ... } header { // ... } .content { // ... @media (max-width: $mobileBreak) { width: auto; margin-right: 0; } } .sidebar { // ... @media (max-width: $mobileBreak) { width: auto; } } } footer { // ... }

Теперь сайдбар сложится под контент на телефонах (<480px):


Работа с выравниваниями

В качестве теста, создадим в блоке контента, несколько шариков с заливкой разными цветами, так чтобы они были выравнены по горизонтали и по вертикали в области контента, для этого добавляем html:



// ... $mobileBreak: 479px; @mixin wh($w, $h) { width: $w; height: $h; } // ... .content { // ... padding-top: 0; .content-inner { height: 100%; justify-content: space-between; align-items: center; .bounce { -webkit-border-radius: 50%; -moz-border-radius: 50%; border-radius: 50%; } .red { background: #D9534F; } .green { background: #6AB181; } .blue { background: #2D8CD3; } .wh50 { @include wh(50px, 50px); } .wh60 { @include wh(60px, 60px); } .wh35 { @include wh(35px, 35px); } } @media (max-width: $mobileBreak) { // ... } } // ...

Опять таки, там где знаки, // ... , код остается тот же самый.

Результат:



Как видим, шарики выровнены идеально. При добавлении новых шариков, выравнивание будет происходит также без всяких проблем. Свойство align-items: center; отвечает за выравнивание по вертикали, а justify-content: space-between; равномерно выравнивает по горизонтали.

align-items: flex-start; делает вот так:


По аналогии, после применения align-items: flex-end; шарики оказываются внизу контейнера, а align-items: baseline; делает вот так:


Есть еще свойство align-items: stretch;, оно вроде как вытягивает каждый элемент в высоту, но у меня по быстрому не получилось реализовать, поэтому скрин не покажу.

Это все относится к расположению по горизонтальной оси (по умолчанию). Но если мы сделаем явно column:


.content-inner { flex-direction: column; }

То шарики станут по вертикали! И опять таки, применяя различные свойства align-items, мы будем добиваться всего того, что и при горизонтальном построении шариков, но только уже по вертикали! Еще есть свойство align-self, оно переопределяет свойство align-items для одного какого нибудь шарика, или группы. Вот таким вот способом можно гибко управлять всеми выравниваниями.

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

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