{% hint style="info" %} Follow along with code examples here! {% endhint %}
Table of Contents:
- Terms
- Explore Flexbox on Youtube
- Flexbox Puts Things In A Row
- Controlling Flex Items
- Challenge: Styling a Navbar using Flexbox
- Some More Examples!
Resources:
- Flexbox - a
display
type that arranges flexible elements in a container in a row or column. - Flex Container - the element with
display:flex
. - Flex Item - an element inside of a flex container.
- Main Axis — the direction that flex items flow in, (set by
flex-direction
and in therow
direction by default). - Cross Axis — the direction perpendicular to the main axis.
- The essential flex container properties are:
flex-direction
- Determines the direction flex items will be arranged. Defaults torow
but can be set tocolumn
to arrange flex items vertically.justify-content
— defines the spacing along the main axisalign-items
— defines the alignment of elements along the cross axisgap
— controls spacing between flex items (not on outer edges)
- The essential flex item properties are:
flex-grow
— defines the amount a flex item will grow relative to its siblings when there is excess space.flex-shrink
— defines the amount a flex item will shrink relative to its siblings when there is not enough space.flex-basis
— defines the starting size of a flex item.flex
— used as shorthand for the above 3 properties.
Open https://www.youtube.com/ and see how elements shift in size as you resize the window.
Q: Look at a row of video "cards". Are they display:inline
, display:block
or something else? Guess, then inspect the page!
They should be
display: flex;
elements!
- Flexbox is a display type used for arranging elements inside of a container in a row or a column.
- The parent element gets the
display: flex
property, making it a flex container. - The children of the flex container automatically become flex items
With Flexbox, the most common use case is arranging identical elements in a row that will grow or shrink according to the available space.
Consider the following HTML:
{% code title="0-flexbox-demo/index.html"%}
<div class="flex-container" id="squares-container">
<div class="flex-item">A</div>
<div class="flex-item">AB</div>
<div class="flex-item">ABC</div>
<div class="flex-item">ABCD</div>
<div class="flex-item">ABCDE</div>
</div>
{% endcode %}
By default these elements elements will stack on top of each other.
Q: Why is this the default behavior of divs?
By default,
div
elements will be block elements. Block elements always stack on top of each other and take up the full width available to them.
By setting the adding Flexbox to the parent container (the div.flex-container
element), its children will be placed horizontally in a row!
.flex-container {
display: flex;
}
The flex items will all stretch vertically to have equal height but will only take up as much width as is needed.
With Flexbox applied to the parent container, we gain access to a bunch of options for arranging the flex items inside.
We can control:
- the direction that flex items flow with
flex-direction
- how much space is between flex items with
gap
- how the flex items grow or shrink along the main axis with
flex
- how flex items are spaced along the main axis with
justify-content
- how flex items are stretch and are positioned along the cross axis with
align-items
- whether or not flex items wrap when they can't fit in one line with `flex-wrap``
Let's jump into each!
Flexbox has two axes, the main axis and the cross axis. Flex items flow along the main axis and, by default stretch along the cross axis.
By default, the main axis runs in the "row" direction, arranged left to right.
We can arrange flex items in a column (top to bottom) by setting the flex-direction
property to column
:
.flex-container {
display: flex;
flex-direction: column;
}
flex-direction: column
changes the orientation of the main and cross axes.
- The main axis is now vertical (top to bottom)
- The cross axis is now horizontal (left to right)
Knowing the direction of these two axes plays an essential role in controlling how flex items behave inside of a flex container. Let's look at how!
Gap is perhaps the most useful feature of Flexbox. The gap
property makes adding space between elements incredibly easy:
.flex-container {
display: flex;
gap: 1rem;
}
Note that the gap will only be applied to the space between the elements, not before the first element and after the last element.
Q: Why can't we just use margin to do this?
Thus far, if we've wanted to put space between elements, we've had to rely on adding amargin
. However, margins have a few behaviors that can be annoying to deal with:
- Margins are applied to all sides, making it difficult to only add space between elements (the first and last elements will have extra margin on top and bottom)
- Margins can overlap causing unexpected spacing
Gap solves these problems entirely!
The flex
property controls how much a flex item will grow or shrink within a container when there is extra space.
By default, flex items will only take up as much space as they need. However, if there is extra space, flex items with the flex
property will flex to take up that space.
/* The flex property controls the relative "growth rate" of a flex item when there is excess space */
.flex-item {
flex: 1;
}
/* Hovering over a flex item will cause it to grow 3x the size of other flex items */
.flex-item:hover {
flex: 3;
}
With flex: 1;
applied to all flex items, they will all attempt to share the extra space evenly.
With flex: 3;
applied to the one hovered element, it will take 3 times as much extra space as the other elements.
{% hint style="info" %}
flex
is a shorthand for the three properties flex-grow
, flex-shrink
, and flex-basis
. Read more about the flex property on MDN!
{% endhint %}
By default, flex items will arrange themselves at the start of the main axis (left to right in the row direction) of the flex container. We can change this behavior using justify-content
:
.flex-container {
display: flex;
justify-content: space-between;
}
By default, flex items will stretch along the cross axis. We can change this behavior using align-items
.
.flex-container {
display: flex;
align-items: flex-start;
}
By default, flex items will all try to fit onto one line. If there isn't enough space, they will overflow.
Setting flex-wrap: wrap
, flex items will be pushed to the next line when there isn't enough space.
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
One of the most common uses of flexbox is to style a navigation bar. Open up 1-navbar
and look at the <header>
element:
<!-- Often, the header contains a logo and a nav component -->
<header>
<p id="header-logo">Ben's Blog</p>
<nav>
<!-- It is common to put a ul inside with links as list items -->
<ul id="nav-links">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</header>
Below, you can see what the header currently looks like (left) and what we want it to look like (right). What is different?
Q: How do we fix this?
Solution
- Most elements are
display: block
which means they are stacked on top of each other. - We can apply
display: flex
to a parent element to put its children in a row horizontally
header {
display: flex; /* Makes the header a flex container */
justify-content: space-between; /* main-axis spacing */
align-items: center; /* cross-axis spacing */
}
ul {
display: flex;
gap: 1rem; /* increasing spacing between flex items */
}
- The essential flex container properties are:
justify-content
— defines alignment along the main axisalign-items
— defines alignment along the cross axisgap
— controls spacing between flex items (not on outer edges)flex-direction
- defaults torow
but can be set tocolumn
to arrange flex items vertically.
- Check out the
3-photo-gallery/
directory for a cool example of using flexbox to make a wall-to-wall flexible photo gallery based on this post: Adaptive Photo Layout With Flexbox - 19 CSS Flexbox Examples