Работа с flexbox
Содержание:
- Сценарии использования — более одного фактора гибкости
- Пример 1. Как сделать фотогалерею на Флексбокс
- Свойство align-content
- flexbox froggy 24 уровень Вывод
- Разница между устаревшими подходами и современными стандартами
- Когда не стоит использовать флексы?
- Properties for the Children(flex items)
- CSS Advanced
- Как использовать Flexbox
- CSS Advanced
- Пример 3: Как сделать макет сайта, используя Флексбокс
- Основы
- Вопросы отладки связанных размеров
Сценарии использования — более одного фактора гибкости
Здесь я имею в виду использование flex-grow или flex-shrink, но со значением, отличным от 1. В этом разделе я рассмотрю некоторые идеи использования.
Действия в футоре
Вдохновленный Facebook (я тоже украл значки), этот нижний колонтитул (footer) действий состоит из четырех элементов, а последний имеет меньшую ширину. Мы можем сделать это следующим образом:
.actions { display: flex; flex-wrap: wrap; } .actions__item { flex: 2; } .actions__item.user { flex: 1; }
Расширяющая анимацию
Мы можем сделать интересную вещь — анимировать flex элемент при наведении курсора. Это может быть чрезвычайно полезно. Вот простой пример этого:
.palette { display: flex; flex-wrap: wrap; } .palette__item { flex: 1; transition: flex 0.3s ease-out; } .palette__item:hover { flex: 4; }
Когда контент больше, чем его оболочка
Некоторое время назад я получил письмо от читателя с вопросом о проблеме, с которой он столкнулся. Как и на рисунке, у нас есть два изображения, которые должны оставаться в границах своей оболочки.
.wrapper { display: flex; } .wrapper img { flex: 1; }
Однако даже с flex: 1 изображения все равно выходят за пределы оболочки. Согласно спецификации CSS:
В нашем случае изображения слишком большие, и flexbox не сжимает их, чтобы поместиться в оболочку. Чтобы изменить это поведение, нам нужно установить следующее:
.wrapper img { flex: 1; min-width: 0; }
Я объяснил эту проблему в своей о минимальной и максимальной width / height в CSS.
Пример 1. Как сделать фотогалерею на Флексбокс
Разместить фотографии по строкам и столбцам на Флексбокс гораздо проще, чем многим кажется. Рассмотрим простую сетку:
<main class="gallery"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> <img src="/sample.jpg"> </main>
У нас есть main.gallery и 10 изображений в нем. Убедимся, что main.gallery растягивается на весь доступный экран:
.gallery { min-height: 100vh }
Кое-что об изображениях
По умолчанию все изображения inline-block элементы. У них есть ширина и высота. Они выстроятся в линию (только если они не слишком большие и могут все поместиться)
На старт
Сейчас наша галерея будет выглядеть следующим образом:
Размеры всех 10 изображений остались нетронутыми. При необходимости картинки переместятся на вторую строку. Послушные ребята =)
А теперь, на сцену выходит Флексбокс:
.gallery { display: flex }
С этого момента поведение изображений изменилось. Из inline-block элементов они стали flex-items. В результате применения Флексбокс к .gallery все картинки уместились в одну линию. Да еще и растянулись по вертикали, вот так:
Картинки теперь уместились все в одну линию, да еще и растянулись по вертикали. Жалкое зрелище =(
Все это результат стандартного поведения Флексбокс:
- Сплющить все дочерние элементы в одну линию и никуда их не переносить. Не самое лучшее решение для галереи, так что изменим его:
.gallery { flex-wrap: wrap }
Это разрешит перенос элементов на другую строку как и полагается
Изображения перенесены
2. Теперь картинки располагаются в несколько линий. Но они все еще растянуты по вертикали и это определенно не характерно для изображений в галерее. Свойство align-items флекс-контейнера по умолчанию равно значению stretch
.align-items: stretch
Изменим его:
.gallery { ... align-items: flex-start }
Это защитит картинки от растягивания.
Кроме того они выровнены относительно начала вертикальной оси:
Теперь в нашей галерее неискаженные изображения. Почти такие же как и были, пока мы не подключили флексбокс
Наша мощная флексбокс-галерея готова.
Преимущества использования Флексбокс
Сейчас преимущества использования Флексбокс не особо заметны, ведь тот же самый вид был и до его подключения.
Кроме легко получаемой адаптивности, преимущество флексбокс заключается в возможностях выравнивания. Флекс-контейнер .gallery имеет несколько свойств для настройки выравнивания:flex-direction: row ,justify-content: flex-startиalign-items: flex-start. Разметку галереи можно легко поменять поигравшись со следующим значением:
.gallery { ... justify-content:center; }
Теперь изображения идеально отцентрованы по горизонтали
Кроме того, картинки могут быть отцентрованы и по горизонтали и по вертикали .gallery.
.gallery { ... justify-content:center; align-items: center; }
А теперь изображения выровнены не только горизонтально, но и вертикально
Флексбокс предоставляет много вариантов выравнивания. Играйтесь со значениями, как сочтете нужным.
Можете посмотреть на действующую Флексбокс галереюздесь.
Свойство align-content
Это свойство применяется только в том случае, если в контейнере flexbox имеется несколько строк элементов. Эффект, который мы получим, будет выравниванием и разделением строк на вторичной оси.
Примечание: Хотите получить несколько строк элементов вконтейнере flex, нужно будет применить к ним “flex-flow: wrap”, и, конечно, есть достаточно элементов с достаточной шириной, такдля их распространения требуется несколько строк.
В конце концов, эффект, который мы получаем с align-content, похож на эффект, который мы получаем с align-items, в том смысле,он будет применять к дочерней оси свой эффект распределения, только здесь мы указываем не на размещение одной строки, а на все строки. Кроме того, это также похоже на justify-content в том смысле, мы определяем разделение между элементами, но влияем на строки элементов, а не на свободные элементы.
- flex-start: указывает,строки будут склеены друг с другом (очевидно, они не будут точно склеены, если мы поместили в него margin), от начала дочерней оси.
- flex-end: строки будут склеены друг с другом, но на этот раз склеены в конце вторичной оси.
- center: они будут расположены в центре вторичной оси, склеены друг с другом.
- stretch: ваши размеры будут расти, длязанятия максимальное доступного пространства (если только в элементах не было размещено другое измерение).
- space-between: указывает, строки будут разделены друг от друга, оставляя пропорциональное пространство между ними.
- space-around: указывает, строки будут разделены, оставляя между ними пропорциональное пространство, также с границей.
Я думаю, это будет лучше понятно с точки зрения следующей картины.
flexbox froggy 24 уровень Вывод
Мы уже видели много теории, которую вы должны изучить при работе с Flexbox, и возможностей этого стандарта. Вы, конечно, по достоинству оценили, это позволяет много игры и очень интересные варианты, которые будут практичными во многих случаях изо дня в день.
Разница между устаревшими подходами и современными стандартами
Теперь, когда у вас есть представление о том, как проблему решали раньше, давайте взглянем, на что способны Flexbox и Grid.
Flexbox и Grid — это идеальные решения для CSS-разметки, являющиеся современными стандартами. Если вам необходимо писать CSS-код на хорошем уровне, то обязательно изучите их.
Решение задачи с помощью Flexbox
Контекст форматирования Flexbox инициализируется путем создания flex-контейнера.
Родительским элементом является . Он содержит боковую панель и основную зону. Создаём контейнер:
И получаем:
Flexbox в действии
Не забудем о пропорциях:
Вуаля! Проблему можно считать решенной:
Задача решена
С Flexbox можно делать много разных вещей:
-
Отцентрировать боковую панель и основную зону по вертикальной оси:
-
Изменить положение одного из дочерних элементов:
-
Менять порядок дочерних элементов без изменения HTML-кода:
И я затронул лишь верхушку айсберга Flexbox.
Flexbox доступен в большинстве поддерживаемых браузеров. Им можно полноценно пользоваться в Firefox с 28 версии, Chrome с 29, Safari с 6.1 и Edge с 12.
Прим. перев. Разобраться с Flexbox поможет наше наглядное введение.
Решение проблемы с помощью Grid
В отличие от Flexbox, который по большей части работает в одном измерении, с CSS Grid вы можете использовать как ряды, так и колонки. Посмотрим, как решить нашу проблему с его помощью.
Начинается всё так же, как и в случае с Flexbox. Создаём контейнер:
Вот весь CSS:
И вот что мы получим:
Первичный вариант
Grid доступен в большинстве поддерживаемых браузеров, хотя и в меньшем количестве. Им можно полноценно пользоваться в Firefox с 52 версии, Chrome с 57, Safari с 10.1 и Edge с 16.
Наше последнее изображение пока никак не отличается от предыдущих. Так в чём же магия?
Что, если мы разделим пропорции ширины, как раньше:
Пропорциональное распределение ширины для дочерних элементов
Да, результат отличается, но нам он не подходит. Боковая панель пока не расположена сбоку от главной зоны.
Вот мы и подошли к сути Grid-разметки. После инициализации Grid-контейнера при помощи необходимо определить ряды и строки внутри него.
Вот как это делается:
Решение в одну строку — красиво, не правда ли? определяет пропорции столбцов в сетке.
Задача решена
Но с помощью Grid можно сделать гораздо больше.
Сначала добавим немного цвета главному блоку, чтобы примеры были более наглядными:
Вот что мы должны получить:
Заливка цветом зоны основного контента
Посмотрим, что хорошего может предложить Grid:
-
Можно определить разрыв между столбцами:
Вот результат:
Нет необходимости в добавлении отступов к блокам и : это делает .
-
Можно сделать столько столбцов, сколько вам нужно. Примеры выше использовали только по одному элементу и . Добавим ещё два:
Grid сам понял, что нам надо — не пришлось даже трогать CSS.
-
Можно определить пробел между строками:
Для упрощения можно использовать сокращение: вместо и .
-
Можно определять размеры строк:
Теперь высота первой, второй и третьей строк равна 200, 300 и 400 пикселей соответственно.
Для начала хватит и этого — но это далеко не всё.
Когда не стоит использовать флексы?
Мы рассмотрели некоторые причины, по которым думаю, cтоит выбирать флексы вместо раскладки на гридах, поэтому можем посмотреть на некоторые случаи, когда флекс — не лучший вариант. Мы уже посмотрели на пример с флексом против грида, где элементы выровнены по горизонтали и вертикали в отличие от элементов, которые занимают место построчно. И это различие стоит учитывать в первую очередь.
Вот пример грида с двумерной раскладкой. Раскладка одновременно и в строках, и в колонках. Пример на флексах — это одномерная раскладка. Мы позволили перенос флекс-строк, но распределение места на строке ведётся построчно. Каждая строка естественно ведёт себя как новый флекс-контейнер по направлению главной оси.
Следовательно, если компоненту нужна двумерная раскладка, лучше будет использовать гриды вместо флексов
Неважно, большой или маленький у вас компонент. Если запомните из этой статьи только одно, пусть это будет следующее: выкиньте из головы идею о том, что гриды предназначены только для основной раскладки страницы, а флексы — для компонентов
У вас может быть крошечный компонент, которому требуется двумерная раскладка, и структура главной страницы, которой лучше подойдёт одномерная раскладка.
Ещё один хороший пример, где гриды будут лучшим решением: если вы задаёте ширину или базовый размер флекса по главной оси — как единицу длины для ваших элементов, для того чтобы выровнять их с другим рядом таких же элементов, или чтобы каким-то образом ограничить гибкость. Довольно часто это показатель того, что вам нужна двумерная раскладка, или того, что вашей раскладке лучше подойдёт контроль со стороны контейнера сетки.
Например, мы можем сделать нашу раскладку на флексах более похожей на гриды, ограничив гибкость элементов. Задайте свойство и выставите размеры элементов в процентах, подобно тому, как мы поступали с размерами элементов в раскладке на флоатах. Если обнаружите, что поступаете так, предположу, что раскладка на гридах подойдёт вам лучше, ведь она и была создана для этого.
See the Pen Smashing Flexbox Series 4: wrapped flex items with percentage widths by rachelandrew (@rachelandrew) on CodePen.
Принимая во внимание всё вышесказанное, помните, что часто нет чёткого правильного или неправильного ответа. Иногда единственное, что можно сделать — это попробовать разные варианты и посмотреть, что лучше всего подходит этому компоненту
Помните, что также можно переключаться между методами раскладки, используя флексы на одной контрольной точке и гриды на другой.
Properties for the Children(flex items)
order
By default, flex items are laid out in the source order. However, the property controls the order in which they appear in the flex container.
flex-grow
This defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.
If all items have set to 1, the remaining space in the container will be distributed equally to all children. If one of the children has a value of 2, the remaining space would take up twice as much space as the others (or it will try to, at least).
Negative numbers are invalid.
This defines the ability for a flex item to shrink if necessary.
Negative numbers are invalid.
flex-basis
This defines the default size of an element before the remaining space is distributed. It can be a length (e.g. 20%, 5rem, etc.) or a keyword. The keyword means “look at my width or height property” (which was temporarily done by the keyword until deprecated). The keyword means “size it based on the item’s content” – this keyword isn’t well supported yet, so it’s hard to test and harder to know what its brethren , , and do.
If set to , the extra space around content isn’t factored in. If set to , the extra space is distributed based on its value. See this graphic.
flex
This is the shorthand for and combined. The second and third parameters ( and ) are optional. The default is , but if you set it with a single number value, it’s like .
It is recommended that you use this shorthand property rather than set the individual properties. The shorthand sets the other values intelligently.
align-self
This allows the default alignment (or the one specified by ) to be overridden for individual flex items.
Please see the explanation to understand the available values.
Note that , and have no effect on a flex item.
CSS Advanced
CSS Rounded CornersCSS Border ImagesCSS BackgroundsCSS ColorsCSS Color KeywordsCSS Gradients
Linear Gradients
Radial Gradients
CSS Shadows
Shadow Effects
Box Shadow
CSS Text EffectsCSS Web FontsCSS 2D TransformsCSS 3D TransformsCSS TransitionsCSS AnimationsCSS TooltipsCSS Style ImagesCSS Image ReflectionCSS object-fitCSS object-positionCSS ButtonsCSS PaginationCSS Multiple ColumnsCSS User InterfaceCSS Variables
The var() Function
Overriding Variables
Variables and JavaScript
Variables in Media Queries
CSS Box SizingCSS Media QueriesCSS MQ ExamplesCSS Flexbox
CSS Flexbox
CSS Flex Container
CSS Flex Items
CSS Flex Responsive
Как использовать Flexbox
(О выборе между Grid и Flexbox можно почитать в статье «Grid — для макетов, Flexbox — для компонентов», — прим. ред. Techrocks).
Допустим, у нас есть документ, в котором по порядку идут три одинаковых элемента-потомка какого-нибудь родительского блока. Они располагаются друг за другом вертикально.
Но что, если нам нужно расположить их в ряд?
Здесь нам на помощь приходит Flexbox. Этот функционал CSS позволяет располагать элементы с учетом строк и столбцов, а также задавать промежутки между ними (пространство вокруг них).
Для начала давайте создадим родительский блок с тремя элементами-потомками внутри него.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Position and Flexbox</title> <link rel="stylesheet" href="./index.css"> </head> <body> <div class="parent"> <div class="child-one"></div> <div class="child-two"></div> <div class="child-three"></div> </div> </body> </html>
CSS:
/* Flexbox container */ .parent { background-color: #00AAFF; width: 300px; height: 300px; display: flex; } .child-one { background-color: rgb(116, 255, 116); width: 300px; height: 300px; } .child-two { background-color: rgb(248, 117, 117); width: 300px; height: 300px; } .child-three { background-color: rgb(255, 116, 232); width: 300px; height: 300px; }
Обратите внимание, что для класса установлено свойство. Благодаря этому наши элементы-потомки расположились в ряд
Это расположение, принятое во Flexbox по умолчанию.
Давайте посмотрим другие варианты расположений.
Как располагать элементы при помощи Flexbox
flex-direction
Свойство служит для указания главной оси, по которой будут располагаться элементы. То есть, оно определяет, как элементы будут отображаться на экране: горизонтально или вертикально.
Свойству назначают значение row, если элементы нужно расположить в ряд, слева направо (это значение по умолчанию):
Значение позволяет расположить элементы в виде столбцов, т. е. вертикально:
Значение работает так же, как , но порядок элементов будет обратным. Первый элемент станет последним, а последний — первым. расположение элементов будет противоположным тому, что было бы при значении :
Аналогично, значение служит для расположения элементов вертикально, но в обратном порядке.
justify-content
Это свойство определяет выравнивание элементов вдоль горизонтальной оси контейнера.
Если задано значение , элементы будут располагаться по центру контейнера.
При значении — в начале страницы.
При значении — в конце страницы.
Значение позволяет распределить элементы по ширине flex-блока. Элементы будут разделены промежутками. Расстояния между каждой парой соседних элементов будут одинаковыми, а пустые пространства перед первым элементом и после последнего элемента будут равны половине пространства между парами элементов.
Вы видите, что пространства между , и одинаковые, а пространства перед и после — меньше.
Значение максимизирует пространство между элементами, прижимая первый и последний к началу и концу контейнера по главной оси.
Значение дает эффекта, похожий на эффект от значения , с той разницей, что пространство от краев контейнера до первого и последнего элементов будет таким же, как и пространство между элементами.
align-items
Свойство аналогично свойству , но служит для выравнивания элементов по вертикали. Работает только с фиксированной высотой контейнера.
Значение позволяет центрировать элементы по вертикали.
При значении элементы выравниваются по верхнему краю страницы.
При значении — выравниваются по нижнему краю.
Теперь вы знаете основы Flexbox.
Как выравнивать элементы по центру экрана
Свойства Flexbox можно использовать вместе. Например, если мы хотим расположить элементы по центру и по горизонтали, и по вертикали, мы можем задать и , и .
CSS Advanced
CSS Rounded CornersCSS Border ImagesCSS BackgroundsCSS ColorsCSS Color KeywordsCSS Gradients
Linear Gradients
Radial Gradients
CSS Shadows
Shadow Effects
Box Shadow
CSS Text EffectsCSS Web FontsCSS 2D TransformsCSS 3D TransformsCSS TransitionsCSS AnimationsCSS TooltipsCSS Style ImagesCSS Image ReflectionCSS object-fitCSS object-positionCSS ButtonsCSS PaginationCSS Multiple ColumnsCSS User InterfaceCSS Variables
The var() Function
Overriding Variables
Variables and JavaScript
Variables in Media Queries
CSS Box SizingCSS Media QueriesCSS MQ ExamplesCSS Flexbox
CSS Flexbox
CSS Flex Container
CSS Flex Items
CSS Flex Responsive
Пример 3: Как сделать макет сайта, используя Флексбокс
Строительство макетов полностью на Флексбокс не особо одобряется сообществом разработчиков. И, разделяя данное мнение, я все же считаю, что бывают ситуации, когда это допустимо. Самый главный совет, который я могу вам дать:Используйте флексбокс, когда это имеет смысл. Я объясню это на следующем примере.
Макет сайта “святой Грааль”
Самый наистандартнейший макет страницы на свете
Макет “святой Грааль” – хэдер, футер и 3 контейнера для контента
Есть два способа попытаться построить этот макет с помощью Flexbox. Начнем с первого. Для него нужно разместить во флекс-контейнере header, footer, nav, article и aside.
Разметка
Так выглядит наша разметка:
<body> <header>Header</header> <main> <article>Article</article> <nav>Nav</nav> <aside>Aside</aside> </main> <footer>Footer</footer> </body>
Среди прочих, в стандартнейшей разметке есть особое правило: центральная колонка, article в разметке должна идти перед обоими сайдбарами nav и aside.
Article должен идти в разметке первым, но располагаться по центру макета
Подключаем флексбокс
body { display: flex }
Поскольку дочерние элементы должны идти сверху вниз, изменим стандартное направление флексбокс
body { ... flex-direction: column }
- header и footer должны быть фиксированной ширины
header, footer { height: 20vh /*you can use pixels e.g. 200px*/ }
- main должен занимать все свободное пространство в контейнере
main { flex: 1 }
Надеюсь, вы помните, что запись flex: 1 означает тоже самое что и flex-grow: 1, flex-shrink: 1 и flex-basis: 0
Это приведет к тому, что main вырастет и займет все доступное ему место
На этом этапе необходимо позаботиться о содержимом main – блоках article, nav и aside. Сделаем main флекс-контейнером
main { display: flex }
А для nav и aside установим значение width
nav, aside { width: 20vw }
Убедимся, что article занимает все доступное ему пространство
article { flex: 1 }
Теперь article занимает все свободное место
Осталось сделать всего одну вещь. Поменяем значения flex-order, чтобы nav отображался первым
nav { order: -1 }
Готовый вариант
Свойство order используется, чтобы переопределить порядок flex-items. Все элементы flex-items внутри контейнера отображаются в порядке возрастания значения order. Элемент с наименьшим значением будет отображаться первым. По умолчанию значение order для всех flex-items равно 0.
Второе решение для макета
Предыдущее решение использует flex-container для всего контейнера. Макет очень сильно зависит от flexbox. Посмотрим на более разумный подход. Еще раз взглянем на результат, который должен у нас получиться.
Макет “святой Грааль”
header и footer могут быть блочными элементами. Без лишних вмешательств они и так заполнят все доступное им простанство контейнера и будут прижаты к верху и низу
<body> <header>Header</header> <main> <article>Article</article> <nav>Nav</nav> <aside>Aside</aside> </main> <footer>Footer</footer> </body>
Что означает, что флекс-контейнер необходим только для main. Единственная сложность здесь заключается в том, что вам необходимо самим вычислить высоту блока main. Он должен занимать все свободное пространство между header и footer
main { height: calc(100vh - 40vh); }
Рассмотрим этот код. Он использует CSS функцию calc для того, чтобы вычислить высоту main. Высота блока должна быть равна calc (100vh – высота хэдера – высота футера). В предыдущем случае вы должны были задать фиксированную высоту футеру и хэдеру. Теперь вы поступаете таким же образом только с main.Здесьлежит готовый результат.
Макет сайта в 2 колонки
Двухколоночный макет очень распространен. Их тоже очень легко строить на флексбокс.
Макет сайта в две колонки (сайдбар и основной контент)
Вот наша верстка:
<body> <aside>sidebar</aside> <main>main</main> </body>
Инициализируем флексбокс
body { display: flex; }
Задаем блоку aside фиксированную ширину
aside { width: 20vw }
И, наконец, убедимся, что main занимает все доступное пространство
main { flex: 1 }
Вот, в общем-то, и все, что нужно сделать.
Основы
Прежде чем начать описание свойств flexbox, давайте немного познакомимся с основами модели flexbox. Flex-раскладка состоит из родительского контейнера, именуемого flex-контейнером, и его непосредственных дочерних элементов – flex-элементов.
На схеме выше представлены свойства и терминология, которая используется для описания flex-контейнера и его дочерних элементов. Для получения более подробной информации об их значении читайте в официальной спецификации на W3C.
Flexbox-раскладка прошла через многие итерации и несколько изменений синтаксиса по сравнению с исходным черновиком из 2009-го, поэтому, чтобы избежать путаницы, для ясности, мы будем использовать синтаксис только из последнего рабочего черновика (сентябрь 2014). Если вам нужна совместимость со старыми браузерами, то прочитайте эту статью о том, как сделать это наилучшим образом.
Браузеры с поддержкой последней спецификации flexbox:
- Chrome 29+
- Firefox 28+
- Internet Explorer 11+
- Opera 17+
- Safari 6.1+ (с префиксом )
- Android 4.4+
- iOS 7.1+ (с префиксом )
Более детальную поддержку и совместимость с браузерами можно посмотреть здесь.
Вопросы отладки связанных размеров
Если ваши flex элементы заканчиваются неожиданными размерами, то это обычно происходит потому, что ваш flex-basis имеет auto, и есть что-то, что дает этому элементу ширину, которая затем используется в качестве flex-basis. Проверка элемента в DevTools может помочь определить, откуда берется размер. Вы также можете попробовать установить flex-basis в 0, который заставит Flexbox обрабатывать элемент как имеющий нулевую ширину. Даже если это не тот результат, который вы хотите, это поможет определить значение flex-basis в использовании в качестве виновника ваших проблем с размерами.