Skip to content

Flex Item Properties: Precise Control Over Each Element's Behavior โ€‹

Imagine a buffet restaurant with plates of different sizes on the table. When food is served, large plates can hold more, small plates hold less; when food is scarce, every plate gets a little less. Some special plates (like chef's recommendations) might get priority for more food; some plates might need to stand aside to make room for others.

In the previous chapter, we learned about Flex container properties, which act like the restaurant manager, deciding the overall layout rules. The Flex item properties we are going to learn in this chapter are like special instructions for each plateโ€”even in the same restaurant, each plate can have its own personality.

Flex-Grow: Ability to Expand โ€‹

flex-grow defines the ability of an item to expand when the container has remaining space. Its value is a number representing the expansion ratio of the item relative to other items.

Basic Concept โ€‹

By default, the value of flex-grow is 0, meaning that even if the container has remaining space, the item will not automatically expand.

css
.item {
  flex-grow: 0; /* Default value, do not expand */
}

Let's look at a practical example to understand this property:

html
<div class="container">
  <div class="item item-1">Item 1</div>
  <div class="item item-2">Item 2</div>
  <div class="item item-3">Item 3</div>
</div>
css
.container {
  display: flex;
  width: 800px;
  background-color: #f5f5f5;
  padding: 20px;
}

.item {
  width: 150px; /* Initial width of each item is 150px */
  padding: 20px;
  background-color: #2196f3;
  color: white;
  text-align: center;
  margin: 5px;
}

In this example, the total width of the three items is 450px (excluding padding and margin), but the container width is 800px, leaving 350px of unused space. If we set flex-grow: 1:

css
.item {
  width: 150px;
  flex-grow: 1; /* All items share remaining space equally */
}

Now, this 350px of remaining space will be equally distributed among the three items, with each item getting an extra ~117px, resulting in an actual width of about 267px for each item.

Different Expansion Ratios โ€‹

The real power of flex-grow lies in the ability to set different ratios:

css
.item-1 {
  flex-grow: 1;
}

.item-2 {
  flex-grow: 2; /* Get two shares of space */
}

.item-3 {
  flex-grow: 1;
}

Now let's calculate the actual width of each item. Assuming the container width is 800px, and the initial width of all three items is 150px, after removing padding and margin, the remaining space is 350px.

This 350px will be distributed in a ratio of 1:2:1:

  • Total shares: 1 + 2 + 1 = 4
  • Per share: 350px รท 4 = 87.5px
  • item-1: 150px + 87.5px = 237.5px
  • item-2: 150px + 175px = 325px (gets 2 shares)
  • item-3: 150px + 87.5px = 237.5px

Practical Application Scenarios โ€‹

flex-grow is very useful in many scenarios. Let's look at a classic navigation bar layout:

html
<nav class="navbar">
  <div class="logo">TechCorp</div>
  <div class="search-bar">
    <input type="text" placeholder="Search..." />
    <button>Search</button>
  </div>
  <div class="user-menu">
    <button>Profile</button>
    <button>Logout</button>
  </div>
</nav>
css
.navbar {
  display: flex;
  gap: 20px;
  padding: 15px 30px;
  background-color: #333;
  align-items: center;
}

.logo {
  flex-grow: 0; /* Logo keeps fixed size */
  color: white;
  font-size: 24px;
  font-weight: bold;
}

.search-bar {
  flex-grow: 1; /* Search bar occupies all remaining space */
  display: flex;
  gap: 10px;
}

.search-bar input {
  flex-grow: 1; /* Input fills search bar */
  padding: 8px 15px;
  border: none;
  border-radius: 4px;
}

.search-bar button {
  padding: 8px 20px;
  background-color: #2196f3;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.user-menu {
  flex-grow: 0; /* User menu keeps fixed */
  display: flex;
  gap: 10px;
}

.user-menu button {
  padding: 8px 16px;
  background-color: transparent;
  color: white;
  border: 1px solid white;
  border-radius: 4px;
  cursor: pointer;
}

In this layout, the Logo and user menu keep a fixed size, while the search bar automatically expands to fill all remaining space. No matter how wide the screen is, the layout automatically adapts.

Flex-Shrink: Ability to Shrink โ€‹

If flex-grow is about expansion, then flex-shrink is about shrinking. It defines the ability of an item to shrink when container space is insufficient.

Basic Concept โ€‹

The default value of flex-shrink is 1, meaning that when container space is insufficient, all items will shrink proportionally.

css
.item {
  flex-shrink: 1; /* Default value, can shrink */
}

Let's look at an example:

css
.container {
  display: flex;
  width: 400px; /* Container width */
}

.item {
  width: 200px; /* Each item width 200px */
  flex-shrink: 1;
}

If there are 3 items, their total width is 600px, but the container is only 400px, missing 200px of space. By default (flex-shrink: 1), this 200px will be deducted proportionally from the three items, with each item shrinking by about 67px, resulting in a final width of about 133px.

Preventing Shrinking โ€‹

Sometimes, you don't want a certain item to shrink, you can set flex-shrink to 0:

css
.item-fixed {
  width: 200px;
  flex-shrink: 0; /* Will not shrink */
}

.item-flexible {
  width: 200px;
  flex-shrink: 1; /* Can shrink */
}

Now, if the container width is 500px, and there are two items of 200px each:

  • .item-fixed stays at 200px
  • .item-flexible shrinks to 300px (500px - 200px) - wait, this calculation is for remaining space. If container is 300px:
  • .item-fixed stays at 200px
  • .item-flexible shrinks to 100px (300px - 200px)

Different Shrink Ratios โ€‹

Like flex-grow, flex-shrink can also set different shrink ratios:

css
.item-1 {
  width: 200px;
  flex-shrink: 1;
}

.item-2 {
  width: 200px;
  flex-shrink: 2; /* Shrinks more */
}

.item-3 {
  width: 200px;
  flex-shrink: 1;
}

If the container width is 400px, three items total 600px, need to shrink 200px. According to the 1:2:1 ratio:

  • Total shares: 1 + 2 + 1 = 4
  • Per share: 200px รท 4 = 50px
  • item-1: 200px - 50px = 150px
  • item-2: 200px - 100px = 100px (shrinks 2 shares)
  • item-3: 200px - 50px = 150px

Practical Application: Responsive Table โ€‹

flex-shrink is particularly useful when creating responsive tables:

html
<div class="table-row">
  <div class="cell cell-name">John Smith</div>
  <div class="cell cell-email">[email protected]</div>
  <div class="cell cell-role">Developer</div>
  <div class="cell cell-actions">
    <button>Edit</button>
    <button>Delete</button>
  </div>
</div>
css
.table-row {
  display: flex;
  gap: 15px;
  padding: 15px;
  background-color: white;
  border-bottom: 1px solid #eee;
}

.cell-name {
  flex: 1 1 200px; /* Can expand and shrink, base 200px */
}

.cell-email {
  flex: 2 1 300px; /* Can expand and shrink more */
}

.cell-role {
  flex: 0 1 150px; /* Does not expand, can shrink */
}

.cell-actions {
  flex: 0 0 160px; /* Does not expand or shrink, keeps fixed */
}

In this layout:

  • Name column can adjust appropriately
  • Email column is the most flexible, can occupy more space
  • Role column can shrink but not expand
  • Action buttons column keeps fixed width

Flex-Basis: Base Size of Item โ€‹

flex-basis defines the main axis space occupied by the item before remaining space is distributed. You can think of it as the "ideal size" of the item.

Basic Concept โ€‹

The default value of flex-basis is auto, meaning the item's size is determined by its content or explicitly set width/height.

css
.item {
  flex-basis: auto; /* Default value */
}

You can set a specific length value for flex-basis:

css
.item {
  flex-basis: 200px; /* Base size is 200px */
}

flex-basis vs width โ€‹

Many people wonder: What is the difference between flex-basis and width (when main axis is horizontal)?

Simply put:

  • width is a rigid size, unless the item needs to shrink (flex-shrink) or expand (flex-grow)
  • flex-basis is the "ideal size", the starting point for Flexbox calculations

Let's look at a comparison:

css
/* Using width */
.item-width {
  width: 200px; /* Set width */
  flex-grow: 1; /* Can expand */
}

/* Using flex-basis */
.item-basis {
  flex-basis: 200px; /* Set base size */
  flex-grow: 1; /* Can expand */
}

In most cases, the effect of these two writings is the same. But there is an important difference: flex-basis has higher priority.

css
.item {
  width: 150px;
  flex-basis: 200px; /* flex-basis overrides width */
}

In this example, the actual base size of the item is 200px, not 150px.

Special Values: auto and content โ€‹

flex-basis has two special values:

flex-basis: auto (Default)

The item's size is determined by the width/height property. If width/height is not set, it is determined by content.

css
.item {
  flex-basis: auto; /* If width exists, use width; otherwise use content width */
  width: 200px; /* Base size will be 200px */
}

flex-basis: content

The item's size is completely determined by content, ignoring width/height properties.

css
.item {
  flex-basis: content; /* Completely determined by content */
  width: 200px; /* This value will be ignored */
}

Percentage Values โ€‹

flex-basis can be set as a percentage, relative to the container's main axis size:

css
.container {
  display: flex;
  width: 1000px;
}

.item {
  flex-basis: 30%; /* 300px (1000px ร— 30%) */
}

This is useful when creating proportional layouts:

html
<div class="layout">
  <aside class="sidebar">Sidebar</aside>
  <main class="main-content">Main Content</main>
</div>
css
.layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 250px; /* Fixed 250px width */
  background-color: #f5f5f5;
  padding: 20px;
}

.main-content {
  flex: 1 1 auto; /* Occupy remaining space */
  padding: 20px;
}

Flex Shorthand: Comprehensive Control โ€‹

flex is a shorthand property for flex-grow, flex-shrink, and flex-basis. It is one of the most commonly used properties in Flexbox.

Basic Syntax โ€‹

css
.item {
  flex: <flex-grow> <flex-shrink> <flex-basis>;
}

For example:

css
.item {
  flex: 1 1 200px;
  /* Equivalent to:
     flex-grow: 1;
     flex-shrink: 1;
     flex-basis: 200px;
  */
}

Single Value Syntax โ€‹

When only one value is written, the meaning changes depending on the value type:

Number value: sets flex-grow

css
.item {
  flex: 1;
  /* Equivalent to:
     flex-grow: 1;
     flex-shrink: 1;
     flex-basis: 0%;
  */
}

Note that here flex-basis becomes 0%, not the default auto. This is an important difference!

Length value: sets flex-basis

css
.item {
  flex: 200px;
  /* Equivalent to:
     flex-grow: 1;
     flex-shrink: 1;
     flex-basis: 200px;
  */
}

Two Value Syntax โ€‹

Number + Number: flex-grow and flex-shrink

css
.item {
  flex: 2 1;
  /* Equivalent to:
     flex-grow: 2;
     flex-shrink: 1;
     flex-basis: 0%;
  */
}

Number + Length: flex-grow and flex-basis

css
.item {
  flex: 1 200px;
  /* Equivalent to:
     flex-grow: 1;
     flex-shrink: 1;
     flex-basis: 200px;
  */
}

Common flex Values โ€‹

In actual development, the following flex values are most commonly used:

flex: 1

This is the most common value, meaning the item can expand and shrink, and will share space equally.

css
.item {
  flex: 1;
  /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
}

Practical application:

css
.equal-columns {
  display: flex;
}

.column {
  flex: 1; /* All columns equal width */
  padding: 20px;
}

flex: auto

Item can expand and shrink, base size determined by content or width.

css
.item {
  flex: auto;
  /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
}

This value is suitable for content-driven layouts:

css
.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.tag {
  flex: auto; /* Tag size determined by content */
  padding: 6px 12px;
  background-color: #e3f2fd;
  border-radius: 4px;
}

flex: none

Item does not expand or shrink, keeps fixed size.

css
.item {
  flex: none;
  /* flex-grow: 0, flex-shrink: 0, flex-basis: auto */
}

This is equivalent to completely turning off Flexbox's elastic features:

css
.fixed-sidebar {
  flex: none;
  width: 250px; /* Keep fixed width */
}

flex: 0 0 auto

Similar to flex: none, but more explicit.

css
.item {
  flex: 0 0 auto;
  /* No expand, no shrink, size by content or width */
}

flex: 1 0 auto

Item can expand but will not shrink.

css
.item {
  flex: 1 0 auto;
  /* Can expand to fill space, but won't shrink below natural size */
}

Deep Understanding of flex: 1 โ€‹

flex: 1 is one of the most easily misunderstood values. Let's understand its behavior in detail.

html
<div class="container">
  <div class="item">Short</div>
  <div class="item">A much longer text content</div>
  <div class="item">Medium</div>
</div>
css
.container {
  display: flex;
  width: 600px;
}

.item {
  flex: 1; /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
}

Because flex-basis: 0%, all items start calculating from 0. The container's 600px will be equally divided into 3 parts, each item getting 200px. Even if the content of the second item is longer, it will be 200px (content might wrap).

If we use flex: auto:

css
.item {
  flex: auto; /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
}

Now each item first determines base size based on content (e.g., 60px, 180px, 80px), then the remaining space (600px - 320px = 280px) is distributed equally. The final width might be:

  • First item: 60px + 93px = 153px
  • Second item: 180px + 93px = 273px
  • Third item: 80px + 93px = 173px

So:

  • flex: 1 makes all items strictly equal width
  • flex: auto distributes space considering content

Align-Self: Personalized Alignment โ€‹

align-self allows a single item to have a different cross axis alignment than other items, overriding the container's align-items setting.

Basic Usage โ€‹

The values of align-self are the same as align-items:

css
.item {
  align-self: auto; /* Default value, uses container's align-items value */
}

Other available values:

  • flex-start: Align to cross axis start
  • flex-end: Align to cross axis end
  • center: Align to cross axis center
  • baseline: Align to baseline
  • stretch: Stretch to fill container

Practical Application โ€‹

Let's look at a card layout example where a "Featured" card needs special handling:

html
<div class="card-container">
  <div class="card">
    <h3>Standard Plan</h3>
    <p>Basic features</p>
    <div class="price">$9/month</div>
  </div>
  <div class="card featured">
    <div class="badge">Best Value</div>
    <h3>Pro Plan</h3>
    <p>All features included</p>
    <div class="price">$29/month</div>
  </div>
  <div class="card">
    <h3>Enterprise</h3>
    <p>Custom solutions</p>
    <div class="price">$99/month</div>
  </div>
</div>
css
.card-container {
  display: flex;
  align-items: flex-start; /* Default all cards align top */
  gap: 20px;
  padding: 40px;
}

.card {
  flex: 1;
  padding: 30px;
  background-color: white;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.card.featured {
  align-self: stretch; /* Featured card stretches to fill full height */
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border: 2px solid #667eea;
  position: relative;
}

.badge {
  position: absolute;
  top: -15px;
  right: 20px;
  padding: 8px 16px;
  background-color: #ff9800;
  border-radius: 20px;
  font-size: 12px;
  font-weight: bold;
}

In this example, normal cards align top with natural height, while the featured card stretches to the same height as the tallest card, highlighting it.

align-self in Vertical Layout โ€‹

When the main axis is vertical, align-self controls horizontal alignment:

html
<div class="vertical-container">
  <div class="item item-start">Left</div>
  <div class="item item-center">Center</div>
  <div class="item item-end">Right</div>
</div>
css
.vertical-container {
  display: flex;
  flex-direction: column; /* Vertical main axis */
  align-items: flex-start; /* Default left align */
  height: 400px;
  width: 500px;
  background-color: #f5f5f5;
  padding: 20px;
}

.item {
  padding: 15px 30px;
  background-color: #2196f3;
  color: white;
  margin: 10px 0;
}

.item-center {
  align-self: center; /* This item centers */
}

.item-end {
  align-self: flex-end; /* This item aligns right */
}

Order: Reordering Items โ€‹

The order property allows you to change the display order of items without modifying the HTML structure.

Basic Concept โ€‹

By default, the order value of all items is 0, and they are arranged in the order in HTML.

css
.item {
  order: 0; /* Default value */
}

You can set positive or negative numbers to change the order. Smaller numbers come first.

html
<div class="container">
  <div class="item item-1">First in HTML</div>
  <div class="item item-2">Second in HTML</div>
  <div class="item item-3">Third in HTML</div>
</div>
css
.item-1 {
  order: 3; /* Display last */
}

.item-2 {
  order: 1; /* Display in middle */
}

.item-3 {
  order: 2; /* Display second */
}

The display order is now: item-2, item-3, item-1.

Practical Application: Responsive Layout โ€‹

order is particularly useful in responsive design to rearrange elements on different screen sizes:

html
<div class="article">
  <aside class="sidebar">Sidebar</aside>
  <main class="content">Main Content</main>
  <div class="ads">Advertisements</div>
</div>
css
.article {
  display: flex;
  flex-direction: column;
}

/* Mobile: Content first */
.content {
  order: 1;
}

.sidebar {
  order: 2;
}

.ads {
  order: 3;
}

/* Desktop: Restore normal order */
@media (min-width: 768px) {
  .article {
    flex-direction: row;
  }

  .sidebar {
    order: 1;
    flex: 0 0 250px;
  }

  .content {
    order: 2;
    flex: 1;
  }

  .ads {
    order: 3;
    flex: 0 0 200px;
  }
}

On mobile, main content displays first; on desktop, sidebar returns to the left.

Considerations โ€‹

There are a few points to note when using order:

  1. Accessibility Issues: order only changes visual order, not DOM order. Screen readers and keyboard navigation still follow HTML order. If visual order and DOM order differ too much, it might confuse users using assistive technologies.

  2. Performance Impact: Overusing order might affect performance because the browser needs to recalculate layout.

  3. Maintenance Difficulty: If order is used heavily, code readability decreases because visual order and HTML order are inconsistent.

Comprehensive Example: Complex Layout โ€‹

Let's use a complex example to comprehensively apply these properties:

html
<div class="dashboard">
  <header class="header">
    <div class="logo">Dashboard</div>
    <div class="search">
      <input type="text" placeholder="Search..." />
    </div>
    <div class="user-info">
      <img src="avatar.jpg" alt="User" />
      <span>John Smith</span>
    </div>
  </header>

  <div class="main-layout">
    <nav class="sidebar">
      <a href="#">Home</a>
      <a href="#">Projects</a>
      <a href="#">Team</a>
      <a href="#">Settings</a>
    </nav>

    <main class="content">
      <div class="widget-grid">
        <div class="widget widget-large">
          <h3>Revenue</h3>
          <div class="chart">Chart Placeholder</div>
        </div>
        <div class="widget">
          <h3>Users</h3>
          <div class="stat">1,234</div>
        </div>
        <div class="widget">
          <h3>Orders</h3>
          <div class="stat">567</div>
        </div>
        <div class="widget widget-wide">
          <h3>Recent Activity</h3>
          <ul class="activity-list">
            <li>User registered</li>
            <li>Order placed</li>
            <li>Payment received</li>
          </ul>
        </div>
      </div>
    </main>

    <aside class="notifications">
      <h3>Notifications</h3>
      <div class="notification">New message</div>
      <div class="notification">Task completed</div>
    </aside>
  </div>
</div>
css
/* Overall Layout */
.dashboard {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Top Header */
.header {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 15px 30px;
  background-color: #2c3e50;
  color: white;
}

.logo {
  flex: 0 0 auto;
  font-size: 24px;
  font-weight: bold;
}

.search {
  flex: 1 1 auto; /* Search box occupies remaining space */
}

.search input {
  width: 100%;
  padding: 8px 15px;
  border: none;
  border-radius: 4px;
}

.user-info {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

.user-info img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
}

/* Main Layout Area */
.main-layout {
  display: flex;
  flex: 1; /* Occupy remaining height */
}

.sidebar {
  flex: 0 0 200px; /* Fixed width sidebar */
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 20px;
  background-color: #34495e;
}

.sidebar a {
  padding: 12px 15px;
  color: white;
  text-decoration: none;
  border-radius: 4px;
  transition: background-color 0.3s;
}

.sidebar a:hover {
  background-color: #2c3e50;
}

.content {
  flex: 1 1 auto; /* Occupy remaining space */
  padding: 30px;
  background-color: #ecf0f1;
}

.notifications {
  flex: 0 0 250px; /* Fixed width notification bar */
  padding: 20px;
  background-color: #f5f5f5;
  border-left: 1px solid #ddd;
  order: 3; /* Ensure it's on the far right */
}

/* Widget Grid */
.widget-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.widget {
  flex: 1 1 calc(33.333% - 20px); /* 3 per row */
  min-width: 250px;
  padding: 25px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.widget-large {
  flex: 2 1 calc(66.666% - 20px); /* Occupy 2/3 width */
}

.widget-wide {
  flex: 1 1 100%; /* Occupy full row */
}

.stat {
  font-size: 36px;
  font-weight: bold;
  color: #2196f3;
  margin-top: 15px;
}

/* Responsive Adaptation */
@media (max-width: 1024px) {
  .notifications {
    flex: 0 0 200px; /* Shrink notification bar */
  }

  .widget {
    flex: 1 1 calc(50% - 20px); /* 2 per row */
  }
}

@media (max-width: 768px) {
  .main-layout {
    flex-direction: column;
  }

  .sidebar {
    flex: 0 0 auto;
    order: 1;
  }

  .content {
    order: 2;
  }

  .notifications {
    flex: 0 0 auto;
    order: 3;
  }

  .widget {
    flex: 1 1 100%; /* 1 per row */
  }

  .widget-large,
  .widget-wide {
    flex: 1 1 100%;
  }
}

This complex dashboard layout demonstrates:

  • Using flex-grow and flex-shrink to create a flexible search bar
  • Using flex-basis to set fixed-width sidebars and notification bars
  • Using order to rearrange elements in responsive layouts
  • Using flex shorthand to create complex grid layouts
  • Using align-items to achieve vertical centered alignment

Summary โ€‹

Flex item properties allow you to finely control the behavior of each element, which is where Flexbox is truly powerful.

Core Properties Review:

  • flex-grow: Defines expansion ability, larger number gets more remaining space
  • flex-shrink: Defines shrinking ability, set to 0 to prevent shrinking
  • flex-basis: Defines base size, starting point for space calculation
  • flex: Shorthand for three properties, most commonly used are flex: 1 and flex: auto
  • align-self: Overrides container's align-items, achieving personalized alignment
  • order: Changes visual order, does not change DOM order

Common flex Values:

  • flex: 1: Fully elastic, all items equal width (1 1 0%)
  • flex: auto: Elastic, but considers content size (1 1 auto)
  • flex: none: Completely fixed (0 0 auto)
  • flex: 0 0 200px: Fixed 200px width

Best Practices:

  1. Prioritize using flex shorthand, code is more concise
  2. Understand the role of flex-basis, it affects space distribution
  3. Use order cautiously, pay attention to accessibility issues
  4. Combine container properties and item properties to create powerful layouts
  5. In responsive design, flexibly use changes in flex values

Having mastered Flex item properties, you now have the ability to create various complex layouts using Flexbox. In the next section, we will learn how to apply this knowledge to actual projects to solve common layout problems.