In CSS Lesson 7, the properties went on the container. This lesson's properties go on the items, so each one can get its own size and place.
flag
What you'll learn
How flex items share extra space with flex-grow, and give up space with flex-shrink.
How flex-basis sets a starting size, and how the flex shorthand sets all three.
How to move one item with order and line up one item with align-self.
waving_handLet's share the space
When items sit in a flex row, there is often space left over, or not enough space. Flex item properties decide what each item does: grow into the extra space, shrink to fit, or keep its size.
chair
Think of cushions on a long bench. Every cushion starts at its normal size (flex-basis). If there is room left, some cushions puff up to fill it (flex-grow), and a cushion set to 2 takes twice as big a share.
If the bench is too short, the cushions get squeezed (flex-shrink), unless one is too firm to squeeze.
Aflex: 1;
Bflex: 2;
Cflex: 1;
D
Now let's see the CSS ↓
Aflex: 1;
Bflex: 2;
Cflex: 1;
D
D: flex: 0 0 72px; align-self: flex-start;
B has flex: 2, so it gets twice the share that A and C get. D keeps a fixed size and sits at the top of the bench instead of the bottom.
searchA closer look
flex-grow: sharing extra space
Each box below is a flex container with three items. Only the items' flex-grow values change.
0 · 0 · 0
1 · 1 · 1
1 · 2 · 1
flex-shrink and flex-basis
flex-basis is the size an item starts at, before any space is shared. When the row is too small, items shrink below that size. flex-shrink: 0; stops one item from shrinking, which is useful for sidebars, logos and icons.
The flex shorthand
flex sets grow, shrink and basis in one line: flex: 1 1 0;. The short form flex: 1; means "grow 1, shrink 1, start at 0". Because every item starts at 0, all the space is shared, so items with flex: 1 and flex: 2 get exactly a 1 : 2 share. Padding and borders are added on top.
order and align-self
order moves an item without changing the HTML: lower numbers come first. align-self lines up just one item along the cross axis, like align-items does for all of them.
order: -1 on C
ABC
align-self: flex-end on B
constructionLet's build it
Let's size the buttons and the two columns of a Front Page Bytes page. The containers already use display: flex from CSS Lesson 7. Each code box opens on the CSS tab with the new lines highlighted. Click HTML to see the page being styled.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
flex-grow: 1; on every button shares the extra space of the row evenly, so the three buttons fill it from edge to edge.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
.special gets flex-grow: 2;, so the Deals button takes twice as much of the extra space as the others. It grows more, but it isn't exactly twice as wide, because each button also keeps the width of its text.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
flex-basis: 140px; asks for a 140px sidebar. But the long story needs a lot of room, so both columns shrink to fit, and the sidebar ends up narrower than 140px.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
flex-shrink: 0; keeps the sidebar at its full 140px. Only the story column shrinks now.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
The flex shorthand replaces those lines. flex: 1; and flex: 2; start every button at 0, so all the space is shared, and Deals gets exactly twice the share of each other button. flex: 0 0 140px; means "don't grow, don't shrink, be 140px".
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
order: -1; moves the Deals button to the front of the row. In the HTML tab, it's still last.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
Flex items stretch to the row's height by default, so the sidebar was as tall as the story. align-self: flex-start; lets only the sidebar shrink to its own content, at the top.
sticky_note_2Quick notes
flex-growTake a share of extra space
.btn { flex-grow: 1; }
How to use
0Does not grow. This is the default.
1Takes a share of the extra space.
2Takes twice as big a share as an item with 1.
Only the extra space is shared, not the whole row.
Examples
Buttons that fill a whole row.
.btn { flex-grow: 1;}
A search box that takes all the space next to a button.
.search { flex-grow: 1;}
flex-shrinkShrink when space is tight
.side { flex-shrink: 0; }
How to use
1Can shrink when space is tight. This is the default.
0Keeps its size and does not shrink.
2Shrinks twice as much as an item with 1.
Examples
A sidebar that keeps its width on small screens.
.side { flex-shrink: 0;}
A logo that never gets squeezed.
.logo { flex-shrink: 0;}
flex-basisStarting size
.side { flex-basis: 140px; }
How to use
140pxThe starting width in a row (or height in a column).
30%A part of the container.
autoUses the width, or the size of the content. This is the default.
Examples
A sidebar that starts at 140px wide.
.side { flex-basis: 140px;}
Cards that start at a third of the row.
.card { flex-basis: 30%;}
flexGrow, shrink and basis in one
.btn { flex: 1; }
How to use
flex: 1;Grow 1, shrink 1, start at 0. Items with flex: 1 share the row evenly.
flex: 2;Twice the share of an item with flex: 1.
flex: 0 0 140px;Exactly 140px: no growing, no shrinking.
flex: none;The same as 0 0 auto.
Examples
Three equal columns.
.col { flex: 1;}
A main area twice as wide as the sidebar.
.main { flex: 2;}.side { flex: 1;}
A fixed 140px sidebar.
.side { flex: 0 0 140px;}
orderChange the order you see
.special { order: -1; }
How to use
0The usual place, by HTML order. This is the default.
-1Moves the item before the others.
1Moves the item after the others.
Only the look changes. Screen readers and the Tab key still follow the HTML order.
Examples
Show the newest button first.
.new { order: -1;}
Move a sidebar below the story on phones.
.side { order: 1;}
align-selfLine up one item
.side { align-self: flex-start; }
How to use
flex-startThis one item lines up at the top.
centerThis one item sits in the middle.
flex-endThis one item lines up at the bottom.
stretchThis one item fills the row's height.
Examples
One card that stays short in a row of tall cards.
.note { align-self: flex-start;}
One button pushed to the bottom of a tall bar.
.help { align-self: flex-end;}
reportCommon mistakes
These are mistakes many beginners make. Each mini browser shows what really happens.
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
.buttons is the container, and flex-grow only works on items. The buttons stay their small size at the left.
tips_and_updatesTip: Put flex-grow on the items you want to grow: .btn { flex-grow: 1; }
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
Neither column may shrink now. The story wants to be as wide as its whole paragraph, so the row gets wider than the page and sticks out on the right.
tips_and_updatesTip: Use flex-shrink: 0; only on items that need a fixed size, like the sidebar.
error
Expecting flex-grow: 2 to mean twice as wide
<!DOCTYPE html><html lang="en"> <head> <title>Front Page Bytes</title> </head> <body> <div class="buttons"> <a class="btn" href="/news">News</a> <a class="btn" href="/games">Games</a> <a class="btn special" href="/deals">Deals</a> </div> <div class="row"> <div class="main"> <h2>Top Stories</h2> <p>Three new phones go on sale on Friday. Each one has a bigger battery, a sharper camera and faster charging. Stores in Manila and Cebu open early.</p> </div> <div class="side"> <h3>Weather</h3> <p>Sunny, 32°C</p> </div> </div> </body></html>
What you see
description(no title)
flex-grow shares only the extra space. Each button keeps its text width first, so Deals is a little wider than the others, but not twice as wide.
tips_and_updatesTip: To share all the space 1 : 2, use the shorthand flex: 1; and flex: 2; so every item starts at 0.
quizTest your knowledge
Edit the CSS on the left. Open the HTML tab to see the class names you can use. The mini browser updates as you type, and each goal gets a check mark when it's done.
auto_awesomeNo clicking needed. Each goal gets a check mark by itself once your code does it.
Make every .link grow to fill the menu.not done yet
Move the .weather link to the front with order.not done yet
Stop the .side box from shrinking.not done yet
Line up the .side box at the top with align-self.not done yet