Complete CSS Course Module 8: Intermediate: Flexbox Layout

Flex Grow, Shrink, Basis and Wrap

  • Beginner
  • Lesson 8.3
  • 5 min read
  • 33 of 77 in the course

In short

Learn how flex-grow, flex-shrink and flex-basis control the size of flex items, what flex: 1 means, and how flex-wrap and order help you build equal-width cards that wrap. How do flex items decide their size? So far, our flex items were only as wide as their content.

Learn how flex-grow, flex-shrink and flex-basis control the size of flex items, what flex: 1 means, and how flex-wrap and order help you build equal-width cards that wrap.

How do flex items decide their size?

So far, our flex items were only as wide as their content. Three properties on the items control how they share the space in the container:

  • flex-basis – the starting size of the item before free space is shared. The default is auto, which means "use my width, or my content size".
  • flex-grow – how much of the extra space the item takes. The default is 0, so items don't grow.
  • flex-shrink – how much the item shrinks when there is not enough space. The default is 1, so items shrink equally.

Think of a pizza shared by friends. flex-basis is the slice each person gets first. If there is pizza left, flex-grow decides who gets more. If there is not enough, flex-shrink decides who gives some back.

<div class="search-bar">
  <input type="search" placeholder="Search courses">
  <button>Search</button>
</div>
.search-bar {
  display: flex;
  gap: 8px;
  max-width: 600px;
}

.search-bar input {
  flex-grow: 1;
  padding: 10px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
}

.search-bar button {
  padding: 10px 20px;
  border: none;
  border-radius: 8px;
  background: #2563eb;
  color: white;
}

The button keeps its natural width, and the input grows to fill all the remaining space. If the bar gets wider or narrower, the input changes size and the button stays the same. If two items both had flex-grow: 1, they would share the extra space equally. An item with flex-grow: 2 would get twice as much extra space as one with flex-grow: 1.

To stop an item from shrinking, for example a logo or an avatar, use flex-shrink: 0.

What does flex: 1 mean?

The flex shorthand sets all three values at once, in the order grow, shrink, basis. The common values are worth learning by heart:

ShorthandMeansUse it when...
flex: 11 1 0%Items should share the space equally.
flex: auto1 1 autoItems grow and shrink, but start from their content size.
flex: none0 0 autoThe item should keep its size and never grow or shrink.
flex: 0 0 200pxFixed 200pxYou want an exact width, like a sidebar.
flex: 1 1 250pxStart at 250px, then flexCards that should be about 250px wide.

flex: 1 sets the basis to zero, so all items start from nothing and share all the space equally. That is why flex: 1 gives equal-width columns even when the content is different. With flex: auto, an item with more text ends up wider.

Tip: Use the flex shorthand instead of the three separate properties. It is shorter, and it sets sensible values for the parts you don't write.

Wrapping items with flex-wrap

By default, flex items all stay on one line, and they shrink to fit, even when they get very narrow. flex-wrap: wrap lets items move to a new line when there is no more room, just like words in a paragraph.

  • nowrap – everything on one line (default).
  • wrap – items move to new lines from top to bottom.
  • wrap-reverse – items wrap from bottom to top.

When items wrap, align-content controls the space between the lines, with the same values as justify-content. The shorthand flex-flow: row wrap; sets direction and wrap together.

Changing the visual order with order

The order property changes the order in which items appear, without changing the HTML. All items start at order: 0. Lower numbers come first, so order: -1 moves an item to the front.

Common mistake: Using order to fix a confusing HTML structure. Screen readers and the Tab key still follow the HTML order, so keyboard users may jump around the page in a strange way. Use order only for small visual changes, and keep the HTML in a logical order.

Building equal-width cards that wrap

Now let's combine everything into a row of course cards. On a wide screen there are three or four per line, and on a phone they stack one per line, with no media queries.

<section class="courses">
  <article class="course">
    <h3>HTML Basics</h3>
    <p>Build your first web page step by step.</p>
    <a href="#">Start</a>
  </article>
  <article class="course">
    <h3>CSS Flexbox</h3>
    <p>Lay out rows and columns with ease.</p>
    <a href="#">Start</a>
  </article>
  <article class="course featured">
    <h3>CSS Grid</h3>
    <p>Create full page layouts in two directions.</p>
    <a href="#">Start</a>
  </article>
  <article class="course">
    <h3>JavaScript</h3>
    <p>Make your pages interactive.</p>
    <a href="#">Start</a>
  </article>
</section>
.courses {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 20px;
}

.course {
  flex: 1 1 220px;
  display: flex;
  flex-direction: column;
  padding: 20px;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  font-family: system-ui, sans-serif;
}

.course a {
  margin-top: auto;
  align-self: flex-start;
  background: #2563eb;
  color: white;
  padding: 8px 16px;
  border-radius: 6px;
  text-decoration: none;
}

.featured {
  order: -1;
  border-color: #2563eb;
}

Each card starts at 220 pixels wide, then grows to share any extra space. When a card can no longer fit at 220px, it wraps to the next line. On a phone, each card takes the full width. Each card is also a column flex container, and margin-top: auto pushes the "Start" button to the bottom, so all buttons line up even when the text is different. The featured CSS Grid card moves to the front with order: -1.

Note: With flex wrap, the last line can have fewer cards, and they will grow wider than the cards above. If you want every card to be exactly the same width in every row, CSS Grid with auto-fit is a better tool. You will learn it in the Grid module.

Practice exercise

Create a layout with a 240px sidebar and a main content area that takes the rest of the width. The sidebar should never shrink. Then add a row of tags (like "HTML", "CSS", "Design") inside the main area that wrap onto new lines when the window is narrow.

Hint: use flex: 0 0 240px for the sidebar and flex: 1 for the main area. For the tags, use flex-wrap: wrap and gap.

Key takeaways

  • flex-basis is the starting size, flex-grow shares extra space, and flex-shrink handles too little space.
  • flex: 1 makes items share the space equally; flex: none keeps an item's size fixed.
  • flex-wrap: wrap lets items move to new lines instead of squeezing.
  • order changes visual order only; keep the HTML in a logical order.
  • flex: 1 1 220px with flex-wrap: wrap makes cards that wrap without media queries.