CSS · Lesson 8

Flexbox: Items

Sizing and moving each flex item

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.

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.

Let'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.

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.

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.

A closer look

flex-grow: sharing extra space

Each box below is a flex container with three items. Only the items' flex-grow values change.

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.

Let'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.

Step 1: Let the buttons grow

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex-grow: 1;}
What you see

flex-grow: 1; on every button shares the extra space of the row evenly, so the three buttons fill it from edge to edge.

Step 2: Give one button a bigger share

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex-grow: 1;}.special {  flex-grow: 2;}
What you see

.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.

Step 3: Give the sidebar a starting size

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex-grow: 1;}.special {  flex-grow: 2;}.side {  flex-basis: 140px;}
What you see

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.

Step 4: Stop the sidebar from shrinking

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex-grow: 1;}.special {  flex-grow: 2;}.side {  flex-basis: 140px;  flex-shrink: 0;}
What you see

flex-shrink: 0; keeps the sidebar at its full 140px. Only the story column shrinks now.

Step 5: Say it shorter with flex

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex: 1;}.special {  flex: 2;}.side {  flex: 0 0 140px;}
What you see

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".

Step 6: Move a button with order

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex: 1;}.special {  flex: 2;  order: -1;}.side {  flex: 0 0 140px;}
What you see

order: -1; moves the Deals button to the front of the row. In the HTML tab, it's still last.

Step 7: Line up one item with align-self

Your code
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex: 1;}.special {  flex: 2;  order: -1;}.side {  flex: 0 0 140px;  align-self: flex-start;}
What you see

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.

Quick notes

flex-grow Take a share of extra space
.btn { flex-grow: 1; }

How to use

  • 0 Does not grow. This is the default.
  • 1 Takes a share of the extra space.
  • 2 Takes twice as big a share as an item with 1.
  • Only the extra space is shared, not the whole row.

Examples

  1. Buttons that fill a whole row.

    .btn {  flex-grow: 1;}
  2. A search box that takes all the space next to a button.

    .search {  flex-grow: 1;}
flex-shrink Shrink when space is tight
.side { flex-shrink: 0; }

How to use

  • 1 Can shrink when space is tight. This is the default.
  • 0 Keeps its size and does not shrink.
  • 2 Shrinks twice as much as an item with 1.

Examples

  1. A sidebar that keeps its width on small screens.

    .side {  flex-shrink: 0;}
  2. A logo that never gets squeezed.

    .logo {  flex-shrink: 0;}
flex-basis Starting size
.side { flex-basis: 140px; }

How to use

  • 140px The starting width in a row (or height in a column).
  • 30% A part of the container.
  • auto Uses the width, or the size of the content. This is the default.

Examples

  1. A sidebar that starts at 140px wide.

    .side {  flex-basis: 140px;}
  2. Cards that start at a third of the row.

    .card {  flex-basis: 30%;}
flex Grow, 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

  1. Three equal columns.

    .col {  flex: 1;}
  2. A main area twice as wide as the sidebar.

    .main {  flex: 2;}.side {  flex: 1;}
  3. A fixed 140px sidebar.

    .side {  flex: 0 0 140px;}
order Change the order you see
.special { order: -1; }

How to use

  • 0 The usual place, by HTML order. This is the default.
  • -1 Moves the item before the others.
  • 1 Moves the item after the others.
  • Only the look changes. Screen readers and the Tab key still follow the HTML order.

Examples

  1. Show the newest button first.

    .new {  order: -1;}
  2. Move a sidebar below the story on phones.

    .side {  order: 1;}
align-self Line up one item
.side { align-self: flex-start; }

How to use

  • flex-start This one item lines up at the top.
  • center This one item sits in the middle.
  • flex-end This one item lines up at the bottom.
  • stretch This one item fills the row's height.

Examples

  1. One card that stays short in a row of tall cards.

    .note {  align-self: flex-start;}
  2. One button pushed to the bottom of a tall bar.

    .help {  align-self: flex-end;}

Common mistakes

These are mistakes many beginners make. Each mini browser shows what really happens.

Putting flex-grow on the container

The mistake
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.buttons {  flex-grow: 1;}
What you see

.buttons is the container, and flex-grow only works on items. The buttons stay their small size at the left.

Tip: Put flex-grow on the items you want to grow: .btn { flex-grow: 1; }

Stopping every item from shrinking

The mistake
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.main,.side {  flex-shrink: 0;}
What you see

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.

Tip: Use flex-shrink: 0; only on items that need a fixed size, like the sidebar.

Expecting flex-grow: 2 to mean twice as wide

The mistake
body {  background-color: #F0F7FF;  font-family: Arial, Helvetica, sans-serif;}.buttons {  display: flex;  gap: 8px;}.btn {  background-color: #FFD043;  border: 2px solid #11141A;  padding: 8px 12px;  color: #11141A;  text-decoration: none;}.row {  display: flex;  gap: 12px;  margin-top: 12px;}.main,.side {  background-color: white;  border: 3px solid #11141A;  padding: 0 12px;}.btn {  flex-grow: 1;}.special {  flex-grow: 2;}
What you see

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.

Tip: To share all the space 1 : 2, use the shorthand flex: 1; and flex: 2; so every item starts at 0.

Test 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.

No clicking needed. Each goal gets a check mark by itself once your code does it.

  1. Make every .link grow to fill the menu. not done yet
  2. Move the .weather link to the front with order. not done yet
  3. Stop the .side box from shrinking. not done yet
  4. Line up the .side box at the top with align-self. not done yet
Your code
What you see

Go to Exercises

Recap

  • flex-basis sets an item's starting size. flex-grow shares extra space, and flex-shrink decides who gives up space when it's tight.
  • flex: 1; is the short way to make items share a row evenly, and flex: 0 0 140px; makes a fixed size.
  • order moves one item, and align-self lines up one item differently from the rest.

References

Lesson content prepared by the WebCore F.E. team for beginner learners. The following references were used in preparing this lesson.

  • W3C. CSS Flexible Box Layout Module Level 1 (official specification). Open reference
  • W3C. CSS Box Alignment Module Level 3 (official specification, align-self). Open reference
  • LibreTexts. Web Site Design (2022, open textbook). Open reference