Bootstrap v4 explained: Flexing with utilities
When you browse through the #help channel on the Bootstrap Slack workspace, you will see a few questions being asked over and over again. In this series I will try and answer these questions thoroughly in the hopes you will understand what techniques are used and how to use it properly.
I’m a big fan of the new flex utilities included in Bootstrap v4. They give you great flexibility , no pun intended, and are perfect for any alignment use case. We’ll have a look at every class that Bootstrap provides and also walk through the styles the classes add.
You can read through the documentation on getbootstrap.com.
If you just want to know how to use it, scroll down till the next three dots.
Techniques
As you might have guessed: it’s all flexbox for this one. Everything you’ve used floats for, in my opinion, you’re better of with flexbox. If you don’t now what flexbox is you can take a look at the following links. I highly recommend playing the Flexbox Froggy game, it’s the most fun way to learn flexbox.
- Flexbox Froggy
- CSS Tricks: A Complete Guide to Flexbox
- Mozilla Developers Network: Basic Concepts of Flexbox
- Flexbox the animated tutorial by JavaScript Teacher
If you really want to know everything you can also read the CSS working group spec for flexbox. Kudos if you actually read it start to finish, I sure as hell haven’t.
W3C: CSS Flexible Box Layout Module Level 1
The tiny scss file only contains 51 lines, but packs a lot of power. Take a look at it on Github.
But before we dive into the file, there are a few things you need to be aware of.
- These classes only have effect on an element if it has or is a child of an element that has the
display: flex;
property. You can also use thed-flex
class to add it without writing custom css. This is called the flex container. display: flex;
tells the children of flex container how to behave. Only a few properties can control how a single child will behave. A child of a flex container is called a flex item.
If it’s not clear yet you’ll need to read every link I mentioned above, even the w3c spec, just to be thorough 😏.
OK, lets get flexin’!
Breakpoints
This will use the same setup as the display utilities, so look over there if you want a complete explanation of every line. Short version: this will loop through every breakpoint and creates a @media (min-width: ##px){...}
for each breakpoint. It also creates the $infix
variable that we can use in our classes. The infix will correspond to the breakpoint, so sm
, md
, lg
or xl
prepended with a —
.
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints); ...
}
}
Flex-direction
To control the direction, also called the main axis, that the flex container will flow it’s flex items we use the flex-direction
property. This property only accepts row
, column
and their reversed options row-reversed
and column-reversed
. The default value for this property on a flex container is row
, so you don’t need to explicitly add the class to get it to work as a row. The css that will control these is as follows.
.flex#{$infix}-row { flex-direction: row !important; }
.flex#{$infix}-column { flex-direction: column !important; }
.flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }
.flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }
As you can see it’s really simple and solid. To be certain our utility class has effect, we need to append every declaration with !important
otherwise we might be looking for why it isn’t working for an hour and add it anyways.
Flex-wrap
By default a flex container will keep all it’s flex items on one row (or column). We can tell the flex container to wrap it into a second row by adding the flex-wrap
property. This can be done in 3 ways: the default nowrap
, wrap
or its reversed brother wrap-reverse
. These result in the classes below.
.flex#{$infix}-wrap { flex-wrap: wrap !important; }
.flex#{$infix}-nowrap { flex-wrap: nowrap !important; }
.flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }
Flex-fill
This isn’t an actual property. It is a nifty way of making a flex item take up as much space as it can, in other words: fill up the remaining space. If you have two flex items next to each other with this class, they will be equal in width as they both take up as much space as they can. To do this we use the shorthand property flex
. This is a shorthand to declare flex-grow
, flex-shrink
and flex-basis
, in that order.
This is one of the rare properties that can only be used on a flex item.
.flex#{$infix}-fill { flex: 1 1 auto !important; }
By setting flex-grow
and flex-shrink
to 1
we give the flex item the freedom to shrink and grow as much as it can. Setting the flex-basis
to auto will tell the flex item that it’s width doesn’t matter. I’m not sure why it’s auto
, to my knowledge this value can also be 0
, but it still does the same.
Flex-grow and flex-shrink
We can also control flex-grow
and flex-shrink
independently by using these properties themselves instead of the shorthand. This gives you the flexibility to let flex items grow and shrink or to constrain them to flex-basis
or width
properties. Bootstrap only provides a class for the 1
and 0
value of this property. I only encountered a few cases where I wanted to set larger values for these, but these two option are enough in almost all use cases.
This is one of the rare properties that can only be used on a flex item.
.flex#{$infix}-grow-0 { flex-grow: 0 !important; }
.flex#{$infix}-grow-1 { flex-grow: 1 !important; }
.flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }
.flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }
You can think of these classes as booleans for telling the flex item to grow/shrink (1
) or not (0
).
Justify-content
To align flex items along the main axis we can use justify-content
. It accepts 5 values that give you a lot of flexibility. flex-start
and flex-end
will align the flex items at the start
or end
of the main axis. So if the flex-direction
is set to row
, flex-end
will align all flex items to the right. Using center
will, as you might guess, center it on the axis. space-between
does a bit more special things. It spaces the flex items along the main axis of the flex container with even spaces between each item. space-around
will create even spaces around each item. The difference is that the flex items with space-between
will be flush with the sides of the flex container. space-around
will create space between the edge of a flex item and the edge of the flex-container. The examples in the next paragraph will explain this better.
.justify-content#{$infix}-start { justify-content: flex-start !important; }
.justify-content#{$infix}-end { justify-content: flex-end !important; }
.justify-content#{$infix}-center { justify-content: center !important; }
.justify-content#{$infix}-between { justify-content: space-between !important; }
.justify-content#{$infix}-around { justify-content: space-around !important; }
As you can see the classes classes are shortened to be easier to use.
Align-items
We can also align on the cross axis by adding align-items
to the flexbox element. The values you can use for this property are: flex-start
which is the default, flex-end
, center
, baseline
and stretch
. flex end and start work the same
So if flex-direction
is set to row
we can align our elements to the bottom of the row in the flexbox element, by setting the value to flex-end
. Now the part bottom of the row in the flexbox element
is important here. Because when your flexbox items are overflowing your flexbox element, it wraps the items into a new row. Now these element will get aligned relative to the other elements in the row. The next property align-content
does it the other way around.
.align-items#{$infix}-start { align-items: flex-start !important;}
.align-items#{$infix}-end { align-items: flex-end !important;}
.align-items#{$infix}-center { align-items: center !important;}
.align-items#{$infix}-baseline { align-items: baseline !important;}
.align-items#{$infix}-stretch { align-items: stretch !important;}
Align-content
Align content will align the rows of the flexbox items grouped together relative to the flexbox element. So image your items are all 20px high in 2 rows, and your flexbox element is 50px high, you’ll get 5px “padding” at the top and bottom of the flexbox element. Stay put till the example for a clearer explanation.
.align-content#{$infix}-start { align-content: flex-start !important; }
.align-content#{$infix}-end { align-content: flex-end !important; }
.align-content#{$infix}-center { align-content: center !important; }
.align-content#{$infix}-between { align-content: space-between !important; }
.align-content#{$infix}-around { align-content: space-around !important; }
.align-content#{$infix}-stretch { align-content: stretch !important; }
Align-self
With align-self
you can override how a flex item aligns to the cross axis. So we can override the value set with align-items
to the flex element with align-self
. The possible values are the same as align-items
with the addition of auto
, which is the default value.
.align-self#{$infix}-auto { align-self: auto !important; }
.align-self#{$infix}-start { align-self: flex-start !important; }
.align-self#{$infix}-end { align-self: flex-end !important; }
.align-self#{$infix}-center { align-self: center !important; }
.align-self#{$infix}-baseline { align-self: baseline !important; }
.align-self#{$infix}-stretch { align-self: stretch !important; }
For some reason the auto option, though it is present in the scss file, is not mentioned in Bootstrap’s documentation. But believe me, it’s a thing.
Order
The order classes isn’t actually a part of the flexbox utilities, but is created in the grid-framework.scss
file. The classes are created inside the make-grid-columns
mixin. But as they are included in the bootstrap docs as utility classes, this is how they work.
.order#{$infix}-first { order: -1; }
.order#{$infix}-last { order: $columns + 1; }
@for $i from 0 through $columns {
.order#{$infix}-#{$i} { order: $i; }
}
It’s again wrapped in a loop that creates a media query for each breakpoint and passes an infix on as a variable. Bootstrap provides a way to order a flex item as the last or first, but also provides an order class for each column plus a reset option. The for loop above will go from 0 to, by default, 12 and create the order class for each column on every breakpoint. The 0 though is a way to reset the elements ordering. When you use the .order-0
class, the element will be reset to the natural html order. With the other classes you can swap the fifth elements with the second element by using order-5
and order-2
.
So now we’ve got that out of the way… I actually did read most of the W3C article… I now realize you should definitely read through to fully understand flexbox, it’s really well explained.
Allright let’s go on with the examples and show you how to use the classes.
Using the classes
Bootstrap has a few components that are already based on flexbox. That means you can use these classes without the need of adding the .d-flex
class. A good example of one of these elements is the navbar. It already is a flex element and has the justify-content
property set to space-between
. We can now work on some examples with the flexbox utility classes.
The examples will only use Bootstrap utility classes, just to show their power.
flex-direction
flex-wrap
flex-fill, flex-grow and flex-shrink
justify-content
align-items
align-content
align-self
order
Combining these utilities gives you great capability and flexibility (pun intended) to create whatever you want.
Now, get flexing and prototype your site in minutes.
Thanks for reading, hope you learned something.
Let me know what you want explained next, i’ll be glad to do it.