In this file, you will learn about:
- Flex Container
- Main & Cross Axises
- Important Flex Container Properties
- Understanding
space-between
&space-around
&space-evenly
Values - Flex Items
- Important Flex Items Properties
flex
Shorthand
If we set display: flex;
to an element, this element will be turned so-called flex container. Inside of our flex container, we should have other nested elements and those elements are so-called flex items (or children).
Once we turned our elements into a flexbox construct, we can set different properties to these elements. Consider:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div>Hamid</div>
<div>Hamed</div>
</div>
</body>
</html>
.container {
display: flex;
}
We have flex-flow
, justify-content
, align-content
and align-items
properties for our parent element (i.e. .container
class selector).
Then we have order
, flex
and align-self
properties for flex items or children.
Consider this content and style:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="class-1">div</div>
<div class="class-2">width=400px</div>
<div class="class-3">height=600px</div>
<div class="class-4">width/height=300px</div>
<div class="class-5">width=300px</div>
<div class="class-6">width=300px</div>
</div>
</body>
</html>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
}
.class-1,
.class-2,
.class-3,
.class-4,
.class-5,
.class-6 {
margin: 1px 2px;
border: 10px black solid;
}
.class-1 {
background-color: rgba(0, 0, 0, 0.5);
margin: 1px 0;
color: white;
}
.class-2 {
background-color: yellowgreen;
width: 400px;
}
.class-3 {
background-color: violet;
height: 600px;
}
.class-4 {
background-color: aqua;
width: 300px;
height: 300px;
}
.class-5 {
background-color: darkviolet;
width: 300px;
}
.class-6 {
background-color: darkred;
width: 300px;
}
If we see the page, we will see bunch of colors with different widths and heights. If we use flex
for our container, we see strange thing in there. All elements get close to each other.
All those flex items get the highest height
when one of them is tall.
Note: If we specify the height
of an element, it would not be affected on the tallest item. It's totally separated from other flex items.
We can change it to inline-flex
as value. It's like flex
display, but when we want to resize the windows, container and the items don't resize anymore. We cover it later at this file.
We can change the direction of container, for example:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-direction: row;
}
By default, the direction value is row
. We can change it to column
, for example:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-direction: column;
}
It's looks like we remove the flex
display. But it doesn't. Another property is flex-wrap
. We can set wrap and nowrap betwen our flex items, for example:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-wrap: wrap;
}
Now if change the size of the window, we can see flex items are wrapped. The initial value is nowrap
.
If we want to reverse the order of items, we can use wrap-reverse
value:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-wrap: wrap-reverse;
}
The order is reverse when the size of the window is decreased enough. If we turn the full screen, items order will be turned back. But we also see that the width/height=300px
is at in bottom of the container (display would be top to bottom).
Note: We also have column-reverse
and row-reverse
as values of flex-direction
(no flex-wrap
) property:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-direction: column-reverse;
}
/* or */
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
}
Look at this image (dir => row):
We have these two concepts here, the main axis goes top-left corner to right and the cross axis goes the same starting point to the bottom. It's in the default behavior of flex direcion.
Note: If we use flex-direction: row-reverse
, the arrows will be reverse too. For example, the main axis goes top-right corner to left and the cross axis goes the same starting point to the bottom (like splitted picture).
For example, if we have HTML content like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="class-1">div</div>
<div class="class-2">width=400px</div>
<div class="class-3">height=600px</div>
<div class="class-4">width/height=300px</div>
<div class="class-5">width=300px</div>
<div class="class-6">width=300px</div>
</div>
</body>
</html>
This <div class="class-1">div</div>
element, what we can see here, is that the first flex item starts in the top-left corner. This is a main axis. If we resize the window (smaller window), it wraps along the cross axis (top-left corner to buttom).
If we use flex-direction: row-reverse
, all behaviors will be reversed, the cross axis still not changed. If we resize the window (smaller size), we see that the first flex item starts in top again. Thst's the image we show you to this explain this concept.
Look at this image (dir => column):
That's the column direction which we see; the cross axis goes top-left corner to right and the main axis goes the same starting point to the bottom.
Note: If we use flex-direction: column-reverse
, the arrows will be reverse too, but with some differences. For example, the cross axis goes bottom-left corner to right and the main axis goes the same starting point to the top.
Important: Don't confuse the row and column direction, if you see the from row or column sight, we can really understand these concepts (i.e. main and cross axises).
For example, if we have HTML content like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="class-1">div</div>
<div class="class-2">width=400px</div>
<div class="class-3">height=600px</div>
<div class="class-4">width/height=300px</div>
<div class="class-5">width=300px</div>
<div class="class-6">width=300px</div>
</div>
</body>
</html>
This <div class="class-1">div</div>
element, what we can see here, is that the first flex item starts in the top-left corner. So the main axis starts in the top-left corner and the items are aligned along the main axis (i.e. the main axis goes from top to bottom).
If we use flex-direction: column-reverse
, all behaviors will be reversed like mirror.; and the flex items are aligned along the main axis again.
Before we dive deeper in flexbox, we want to introduce the nice property shorthand for mixed flex-direction
and flex-wrap
properties. That's flex-flow
property:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
/* flex-direction: row;
flex-wrap: wrap; */
flex-flow: row wrap;
}
Once we understand this property, we want to introduce more properties, for example aligning the flex items:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-flow: row wrap;
align-items: stretch;
}
The default value is stretch
for items alignment. We can put them in center, for example:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-flow: row wrap;
align-items: center;
}
The interesting thing is that we see the height of flex items changed. Because there are no more stretched items in there. Indeed, it centered our flex items along the cross axis.
If we use this style:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-flow: column wrap;
align-items: flex-start;
}
We see that the flex items are ordered at top-left corner to bottom-left corner (cause of cross axis). If we use flex-end
in align-items
, they go from top-right corner to bottom-right corner.
Note: You can practice flex-start
and flex-end
in row
direction.
Important: align-items
always refers to the cross axis.
But how about main axis? How can we change the items's alignment from main axis. We can do that with justify-content
property.
Important: justify-content
always refers to the main axis.
For example, we center all items along the main axis with:
.container {
margin: 10px;
padding: 10px;
background-color: #ccc;
border: 2px black solid;
display: flex;
flex-flow: row wrap;
align-items: flex-end;
justify-content: center;
}
Note: There is another value that we can use it for align-items
and justify-content
properties. That's baseline
, it's for baseline of element. For example, if we use padding for .class-1
selector, we see the different result in our page.
Important: align-content
property allows us to align our items along the cross axis. We don't want to dive deeper with this property.
Consider this content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
</div>
</body>
</html>
We want practice that flexbox in new way. We want to use space-between
and space-around
values in there, so if we have some styles like this:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
display: flex;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
}
.color2 {
background-color: green;
}
.color3 {
background-color: blue;
}
we see that thare are three boxes (RGB) which are near together. If we use space-between
value, we see that some spaces are between these boxes.
.main {
display: flex;
align-items: center; /* like vertical-align */
justify-content: space-between;
}
If we use space-around
value, we see that some spaces are around each box (i.e. each flex item).
.main {
display: flex;
align-items: center;
justify-content: space-around;
}
And if we use space-evenly
value, we see that several spaces are evenly spaced around the items.
.main {
display: flex;
align-items: center;
justify-content: space-evenly;
}
If you read our articles from older files, in Diving Depper
file, we talk about lists and list items. For example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="main-header">
<nav>
<ul>
<li><a href="packages/index.html">Packages</a></li>
<li><a href="customers/index.html">Customers</a></li>
<li><a href="contact-us/index.html">Contact us</a></li>
</ul>
</nav>
</header>
</body>
</html>
* {
box-sizing: border-box;
}
.main-header {
background-color: lightgreen;
width: 100%;
}
.main-header > * {
display: inline-block;
padding: 10px;
}
.main-header a {
width: 100%;
text-decoration: none;
color: red;
font-weight: bold;
}
nav {
width: 100%; /* or calc(100% - 10%) */
text-align: right;
}
li {
display: inline-block;
padding: 0 10px;
}
a {
width: 100px;
}
We want to convert this list items to flexbox. So we have:
* {
box-sizing: border-box;
}
.main-header {
background-color: lightgreen;
}
.main-header > * {
padding: 10px;
}
.main-header a {
width: 100%;
text-decoration: none;
color: red;
font-weight: bold;
}
nav {
display: flex;
align-items: center;
justify-content: flex-end;
}
li {
display: inline-block;
padding: 0 10px;
}
a {
width: 100px;
}
What's the different? Let's see the nav
selector. We have clean and flexible code now. We don't use 100%
as width
.
important: We can also use flexbox for mobile view (with flex-direction: column
and so on).
If you go to Positioning
file, we quoted that:
The z-index
only work if we just set a position of non-static value. Because we moving an element in z-axis (depth).
But in flexbox, all flex items can have this property even if no position
property was applied. For example:
* {
box-sizing: border-box;
}
.main-header {
background-color: lightgreen;
}
.main-header > * {
padding: 10px;
}
.main-header a {
width: 100%;
text-decoration: none;
color: red;
font-weight: bold;
}
nav {
display: flex;
align-items: center;
justify-content: flex-end;
}
ul {
z-index: -10;
}
li {
display: inline-block;
padding: 0 10px;
}
a {
width: 100px;
}
If you see the ul
selector, we set z-index: -10
and the unordered list will be hidden (behind the main nav). If you are careful, you'll see we don't use position
property. Because the parent of the ul
(i.e. nav
) has flex
display. Indeed, it's flex container.
Until now, we worked with flex container, but now we want to work with single item inside the flex container, i.e. flex item. It's time to work with them (i.e. flex items). There are three most important properies for flex items in flexbox:
order
align-self
flex-grow
flex-shrink
flex-basis
We can change the order of flex container's children (i.e. flex items) with order
property. The value of this property is 1
to n
, for example for RGB colors, we want to change the color order:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
display: flex;
align-items: center;
justify-content: space-evenly;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
order: 3;
}
.color2 {
background-color: green;
order: 2;
}
.color3 {
background-color: blue;
order: 1;
}
Now our boxes colored BRG instead of RGB. Because the order of the:
- Blue box: 1
- Green box: 2
- Red box: 3
order
property allows us to change the order of the elements that the elements initially have based on the code in HTML; and by adding numbers, we say that the bigger number we apply to the order, the later the element will be positioned. For example:
.color1 {
background-color: red;
}
.color2 {
background-color: green;
}
.color3 {
background-color: blue;
order: -1;
}
In this example, the blue box is positioned as the first element. If we change it to 1
like:
.color3 {
background-color: blue;
order: 1;
}
we see that the blue box goes the last element. Because red and green boxes has 0
order value (based on HTML order).
Note: The default value of order
property is 0
zero.
We can change the individual element position with align-self
property. For example, we want to move the red box to the bottom (along the cross axis), for example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styling</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
</div>
</body>
</html>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
background-color: #ccc;
display: flex;
align-items: center;
justify-content: center;
height: 400px;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
align-self: flex-end;
}
.color2 {
background-color: green;
}
.color3 {
background-color: blue;
}
First of all, we set height
for our flex container (.main
selector) and set background color (light gray) for that container. Then we set align-self: flex-end
to red box.
As you can see, the red box goes to the bottom along the cross axis (in relation to the cross axis).
Important: align-items
referred to all elements, but align-self
allows us to define the position of a single element which is part of a flex container. Both align-items
and align-self
refer to the cross axis.
This property is very good for the flexed item. If we use this property, it's like we're stretching it. INded, it sets the flex grow factor. For example;
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
background-color: #ccc;
display: flex;
align-items: center;
justify-content: center;
height: 400px;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
}
.color2 {
flex-grow: 1;
background-color: green;
}
.color3 {
background-color: blue;
}
If we reload the page, we see that the green box stretched like gum. This element used the remaining space available and don't care about element width
value.
If we have multiple grow factors like:
.color1 {
background-color: red;
}
.color2 {
flex-grow: 2;
background-color: green;
}
.color3 {
flex-grow: 3;
background-color: blue;
}
we see that the blue box is bigger than the green box. What happens in there? We have 5 parts in there. Because we have 2
for green box and 3
for blue box and how this remaining total space should be divided.
So for 2/5
of it, will be applied to our green box and for 3/5
of it, will be applied to our blue box.
Note: Negative numbers are invalid.
Important: If we use wrap
in flex-wrap
property in our flex container like:
.main {
background-color: #ccc;
display: flex;
align-items: center;
justify-content: center;
height: 400px;
flex-wrap: wrap;
}
and when we shrink the window size, the blue box goes to the second line with full width. Because lots of free spaces in the second line.
Note: Default value for flex-grow
is 0
.
It something like that the reverse of the flex-grow
property. For example:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
background-color: #ccc;
display: flex;
align-items: center;
justify-content: center;
height: 400px;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
}
.color2 {
background-color: green;
}
.color3 {
flex-shrink: 2;
background-color: blue;
}
We set flex-shrink: 2
and it means that the blue box can't be smallest as it with size (limit the width shrinking size). Indeed, the bigger number is equal the reduce the limitation:
.color3 {
flex-shrink: 10;
background-color: blue;
}
Important1: Negative numbers are invalid.
Important2: Both flex-grow
and flex-shrink
are for width. Not the height.
Note: Default value for flex-shrink
is 1
. The 0
value means that the element can't shrink all the time.
This property defines the size of an element depending on the main axis. So flex-basis
in not the width or the height, it can be both width and height which is dependent on the flex direction:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
padding: 10px;
background-color: #ccc;
display: flex;
align-items: center;
justify-content: center;
height: 400px;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
}
.color2 {
background-color: green;
}
.color3 {
flex-basis: 400px;
background-color: blue;
}
In this example, all boxes have 200px
width and height. We set 400px
as flex basis and we now see the blue box in main axis in wider (i.e. doubled). If we have full screen, we see that the red and green boxes have width of 200px
and blue box has 400px
.
Important: If we set width and height manually, flex-basis
overwrite them and don't look at them in main axis. In cross axis the width and height are affected, for example:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.main {
padding: 10px;
background-color: #ccc;
display: flex;
/* flex-direction: column; */
align-items: center;
justify-content: center;
height: 400px;
}
.color1,
.color2,
.color3 {
width: 200px;
height: 200px;
}
.color1 {
background-color: red;
}
.color2 {
background-color: green;
}
.color3 {
height: 600px;
flex-basis: 300px;
background-color: blue;
}
If we want flex-basis
doesn't affect on width and heigh, we can use flex-basis: auto
as value.
We talked alot about the flex items. Now we want to work with use some properties in one property. To do that, we use the flex
property. The skeleton of this property is:
.flex-item {
flex: flex-grow flex-shrink flex-basis;
}
for example:
.color3 {
background-color: blue;
flex: 0 1 200px;
}
Flexbox:
- Changes the way elements are displayed on a website
- Flexbox consists of the flex container and flex items
Flex Container:
-
Adding
display: flex
to an element will turn it into a flex container:flex-direction
flex-wrap
flex-flow
align-items
justify-content
align-content
- and so on
Flex Items:
-
All elements/children of the flex container will become flex items
-
Behavior can be changed by properties applied to the flex container and applied to individual flex items:
order
align-self
flex-grow
flex=shrink
flex-basis
flex
- and so on
Main and Cross Axises:
flex-direction
defines main axis- Properties refer to main or cross axis
- Behavior of flex items changes depending on
flex-direction