Flex Item Properties

Module 6: Modern CSS & Layouts - Monday (Lecture 3)

Introduction to Flex Item Properties

In our previous lectures, we covered Flexbox fundamentals and explored the properties that apply to flex containers. Now, we'll focus on the properties that apply to flex items—the direct children of a flex container.

These properties give you precise control over how individual flex items behave within their container, allowing for complex and dynamic layouts that respond intelligently to their content and available space.

graph TD A[Flex Item Properties] --> B[flex-grow] A --> C[flex-shrink] A --> D[flex-basis] A --> E[flex] A --> F[align-self] A --> G[order] style A fill:#e3f2fd,stroke:#2196f3,stroke-width:2px style B,C,D,E,F,G fill:#bbdefb,stroke:#1976d2,stroke-width:1px

These properties work together to determine how flex items size themselves and position themselves within their container. Let's explore each one in detail.

flex-grow Property

The flex-grow property defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.

Basic flex-grow Example

grow: 1
grow: 1
grow: 1

Different flex-grow Values

grow: 1
grow: 2
grow: 1

Mixed flex-grow Values

grow: 0
grow: 1
grow: 2
grow: 0
/* Item won't grow beyond its flex-basis */
.item {
  flex-grow: 0; /* Default value */
}

/* Item will grow to fill available space */
.item {
  flex-grow: 1;
}

/* Item will grow at twice the rate of an item with flex-grow: 1 */
.item {
  flex-grow: 2;
}

How flex-grow Works

Here's how the browser calculates the width of items with flex-grow:

  1. The browser first lays out all flex items according to their flex-basis (or intrinsic size if flex-basis: auto)
  2. If there's remaining space in the container, it calculates the total of all flex-grow values
  3. Each item gets a portion of the remaining space proportional to its flex-grow value

For example, if three items have flex-grow values of 1, 2, and 1 respectively, and there's 400px of remaining space:

Real-World Example: Navbar with Space-Filling Element

A common pattern in navigation bars is to have a spacer element that pushes other elements to the edges:

/* The spacer element grows to fill available space */
.navbar-spacer {
  flex-grow: 1;
}

This simple technique pushes the actions to the right side of the navbar without requiring complex positioning or additional container elements.

flex-shrink Property

The flex-shrink property defines the ability for a flex item to shrink if necessary. Like flex-grow, it accepts a unitless value that serves as a proportion. It determines how much the item will shrink relative to other items when there isn't enough space in the container.

Basic flex-shrink Example (resize your browser to see the effect)

shrink: 1
shrink: 1
shrink: 1

Different flex-shrink Values

shrink: 1
shrink: 2
shrink: 1

The flex-shrink: 0 Property

shrink: 0
shrink: 1
shrink: 1
/* Item won't shrink below its flex-basis */
.item {
  flex-shrink: 0;
}

/* Item will shrink if necessary (default) */
.item {
  flex-shrink: 1;
}

/* Item will shrink at twice the rate of an item with flex-shrink: 1 */
.item {
  flex-shrink: 2;
}

How flex-shrink Works

Here's how the browser calculates the width of items with flex-shrink:

  1. The browser first calculates the total size of all flex items according to their flex-basis
  2. If the total exceeds the container's size, it calculates by how much items need to shrink
  3. It factors in both the flex-shrink value and the item's size
  4. Each item shrinks proportionally to its flex-shrink value multiplied by its size

The calculation is a bit more complex than flex-grow because it factors in the item's size:

Real-World Example: Sidebar Layout

In a layout with a sidebar and main content, you might want the sidebar to maintain its width while the main content shrinks:

.sidebar {
  flex: 0 0 250px; /* Don't grow, don't shrink, stay at 250px */
}

.main-content {
  flex: 1 1 auto; /* Grow and shrink as needed */
}

This ensures the sidebar maintains a consistent width even when the viewport becomes narrower, while the main content area adjusts to fill the remaining space.

flex-basis Property

The flex-basis property defines the initial size of a flex item before growing or shrinking happens. It can be a length (e.g., pixels, percentages) or the keyword auto.

flex-basis: auto (default)

auto
auto with more content
auto

flex-basis: 0

0 (grow: 1)
0 with more content (grow: 1)
0 (grow: 1)

fixed flex-basis

100px
200px
100px

percentage flex-basis

50%
50%
/* Item size is determined by its content */
.item {
  flex-basis: auto; /* Default value */
}

/* Item starts with zero size, relying entirely on flex-grow */
.item {
  flex-basis: 0;
}

/* Item starts at a fixed size */
.item {
  flex-basis: 200px;
}

/* Item starts with a percentage of the container */
.item {
  flex-basis: 50%;
}

Understanding flex-basis Values

The different values of flex-basis have important implications:

One key distinction is flex-basis: 0 vs. flex-basis: auto when used with flex-grow:

Real-World Example: Equal-Width Columns Regardless of Content

When creating equal-width columns that should remain equal regardless of content:

.column {
  flex: 1 1 0; /* grow: 1, shrink: 1, basis: 0 */
}

Using flex-basis: 0 ensures all columns have the same starting point (zero) and then grow equally, regardless of their content. If you used flex-basis: auto, columns with more content would be wider.

flex Shorthand Property

The flex property is a shorthand that sets flex-grow, flex-shrink, and flex-basis in a single declaration. It's more concise and generally recommended over setting the individual properties.

flex: 1 (shorthand for flex: 1 1 0)

flex: 1
flex: 1 with more content
flex: 1

Different flex values

flex: 1
flex: 2
flex: 1

Full syntax: flex: grow shrink basis

1 1 100px
0 1 auto
1 0 100px
/* Fully flexible item */
.item {
  flex: 1; /* Equivalent to flex: 1 1 0 */
}

/* Item that grows but maintains its size */
.item {
  flex: 1 0 auto;
}

/* Fixed-width item that doesn't grow or shrink */
.item {
  flex: 0 0 200px;
}

/* Flexible item with minimum width */
.item {
  flex: 1 1 200px;
}

Common flex Shorthand Values

There are several common patterns for the flex shorthand:

/* Initial value, item won't grow or shrink */
flex: 0 1 auto;

/* Equal distribution of space */
flex: 1; /* Equivalent to flex: 1 1 0 */

/* Auto sizing with the ability to grow */
flex: 1 1 auto;

/* Fixed width that won't grow or shrink */
flex: 0 0 200px;

/* Fixed minimum width that can grow but not shrink */
flex: 1 0 200px;

The Magic of flex: 1

The declaration flex: 1 is one of the most common and useful Flexbox patterns. It's equivalent to:

This combination ensures all items with flex: 1 will be exactly the same size, regardless of their content, and will distribute available space equally among them.

Real-World Example: Dashboard Layout

A common pattern for dashboard layouts is to have a mix of flexible and fixed-width widgets:

Normal Widget
Wide Widget
Fixed Width
Normal Widget
.dashboard-item {
  flex: 1 1 250px; /* Grow, shrink, minimum width */
}

.dashboard-item-wide {
  flex: 2 1 500px; /* Grow twice as much */
}

.dashboard-item-fixed {
  flex: 0 0 200px; /* Fixed width, no growing or shrinking */
}

This creates a responsive layout where widgets wrap to new lines as needed, with some widgets taking more space than others.

align-self Property

The align-self property allows individual flex items to override the align-items value set on the flex container. It controls how the item aligns along the cross axis.

align-self Values

flex-start
center
flex-end
stretch
auto (default)
/* Item aligns according to container's align-items value */
.item {
  align-self: auto; /* Default value */
}

/* Item is placed at the start of the cross axis */
.item {
  align-self: flex-start;
}

/* Item is centered along the cross axis */
.item {
  align-self: center;
}

/* Item is placed at the end of the cross axis */
.item {
  align-self: flex-end;
}

/* Item stretches to fill the container along the cross axis */
.item {
  align-self: stretch;
}

When to Use align-self

align-self is particularly useful when:

Real-World Example: Form with Call-to-Action

In a form layout, you might want to align action buttons differently from the input fields:

.form-row {
  display: flex;
  align-items: flex-start;
}

.form-buttons {
  display: flex;
  justify-content: flex-end; /* Align buttons to the right */
}

This creates a well-organized form with properly aligned fields and buttons positioned intuitively at the end of the form.

order Property

The order property controls the order in which flex items appear within their container, without changing the source order in the HTML. By default, all items have an order value of 0, and they appear in the order they're defined in the HTML.

Default Order (as defined in HTML)

1 (order: 0)
2 (order: 0)
3 (order: 0)
4 (order: 0)

Custom Order Values

1 (order: 2)
2 (order: 0)
3 (order: 1)
4 (order: -1)

Moving an Item to the End

First in HTML, Last visually
2
3
4
/* Default order value */
.item {
  order: 0;
}

/* Will appear before items with higher order values */
.item {
  order: -1;
}

/* Will appear after items with lower order values */
.item {
  order: 1;
}

How order Works

The browser arranges flex items in ascending order based on their order value:

Accessibility Considerations

While order is powerful, it's important to consider accessibility:

Real-World Example: Responsive Layout Adaptations

The order property is particularly useful for responsive layouts where you want to change the visual order at different screen sizes:

/* Mobile layout: sidebar appears after main content */
.sidebar {
  order: 2;
}

.main-content {
  order: 1;
}

/* Desktop layout: sidebar appears before main content */
@media (min-width: 768px) {
  .sidebar {
    order: 1;
  }
  
  .main-content {
    order: 2;
  }
}

This allows you to prioritize the main content on mobile devices while maintaining a more traditional layout on desktop, all without changing the HTML structure.

Practical Applications and Examples

Now that we understand the individual flex item properties, let's explore some practical applications that demonstrate how these properties work together to create useful layouts.

Product Cards Layout

A common e-commerce pattern is a grid of product cards with consistent layouts:

Product Image
Product 1
A short description of the product.
Product Image
Product 2
This product has a much longer description that wraps to multiple lines, but the card layout still works perfectly.
Product Image
Product 3
Another product description.
.product-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.product-card {
  display: flex;
  flex-direction: column;
  width: 250px;
}

.product-info {
  flex-grow: 1; /* This ensures all cards have the same height */
}

.product-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

This layout uses flex-grow: 1 on the info section to ensure all cards have the same height, regardless of content length, and the footer always sticks to the bottom of the card.

News Website Layout

A news website might have a layout with a main featured article and sidebar articles:

Main Headline

The main article with in-depth coverage of a major news story. This article gets more space due to its importance and comprehensive content.

Additional paragraphs with more details about the story would go here.

.news-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.main-article {
  flex: 2 1 400px; /* Grow twice as much, basis 400px */
}

.sidebar-articles {
  flex: 1 1 200px; /* Grow normally, basis 200px */
  display: flex;
  flex-direction: column;
  gap: 15px;
}

This layout gives more space to the main article (with flex: 2) while allowing the layout to adapt to different screen sizes. On smaller screens, both sections will stack, with the main article taking full width.

Advanced Techniques and Patterns

The Holy Grail Layout

The "Holy Grail" layout (header, footer, content area, and two sidebars) can be implemented elegantly with flex item properties:

.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header, .footer {
  flex: 0 0 auto; /* Don't grow or shrink, height based on content */
}

.body {
  display: flex;
  flex: 1 0 auto; /* Grow to fill available space */
}

.main-content {
  flex: 1 1 auto; /* Grow and shrink as needed */
}

.left-sidebar, .right-sidebar {
  flex: 0 0 200px; /* Fixed width */
}

/* Responsive behavior */
@media (max-width: 768px) {
  .body {
    flex-direction: column;
  }
  
  .left-sidebar, .right-sidebar {
    flex: 0 0 auto; /* Height based on content */
  }
  
  /* Change order on mobile */
  .left-sidebar { order: -1; } /* Always first */
  .right-sidebar { order: 1; } /* After content */
  .main-content { order: 0; } /* Between sidebars */
}

Vertical Centering

A classic challenge in CSS that Flexbox solves elegantly:

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.centered-content {
  /* Content will be perfectly centered */
}

The Sticky Footer

Ensuring a footer sticks to the bottom of the page, even with minimal content:

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
}

main {
  flex: 1 0 auto; /* Grow to fill available space */
}

footer {
  flex-shrink: 0; /* Prevent footer from shrinking */
}

Equal-Height Columns

Creating columns of equal height regardless of content:

.container {
  display: flex;
}

.column {
  flex: 1 1 0; /* Equal growth, starting from zero basis */
}

Card Layouts with Varying Content

Creating card layouts where the footer always sticks to the bottom:

.card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.card-content {
  flex: 1 0 auto; /* Grow to fill available space */
}

.card-footer {
  flex-shrink: 0; /* Prevent footer from shrinking */
}

Best Practices for Flex Items

1. Prefer the flex Shorthand

Instead of setting flex-grow, flex-shrink, and flex-basis separately, use the flex shorthand for more concise and readable code.

2. Be Careful with flex-basis: auto vs. 0

Understand the difference between flex: 1 1 auto and flex: 1 1 0:

3. Mind Your Overflow

Be aware that flex items can overflow their container if:

4. Use Logical Values for order

When using the order property, use logical values like -1, 0, and 1 rather than arbitrary numbers like 5, 10, and 15. This makes the code more maintainable and easier to understand.

5. Consider Accessibility When Reordering

Remember that order only affects visual order, not the source order in the HTML. This can create a disconnect between visual and tab order, potentially confusing users who navigate with a keyboard.

6. Test Resize Behavior

Always test how your flex items behave when the container is resized. Items might not shrink or grow as expected under certain conditions.

7. Combine with Media Queries for Responsiveness

Use media queries to adjust flex item properties at different screen sizes, creating truly responsive layouts.

Common Gotchas and Troubleshooting

1. Items Won't Shrink Below Their Content Size

If items have substantial content (like text that doesn't wrap), they might not shrink as expected even with flex-shrink: 1. Solutions include:

2. Unexpected Sizing with flex-basis: auto

When using flex-basis: auto, items size based on their content, which can lead to uneven distributions even with equal flex-grow values. If you want truly equal sizing, use flex-basis: 0.

3. Images Causing Layout Issues

Images can cause layout issues in flex items if they're too large. Solutions include:

4. Nested Flex Items Behaving Unexpectedly

When flex items are also flex containers, sizing can become complex. Be explicit about whether properties like flex: 1 apply to the item as a container or as an item.

5. Fixed-Size Items Overflowing

If you have items with flex: 0 0 [size] and they don't fit, they'll overflow the container. Consider:

Practice Activities

Exercise 1: Dynamic Content Cards

Create a layout with three cards where:

Populate the cards with varying amounts of content to test the layout.

Exercise 2: Flexible Form Layout

Create a form with the following requirements:

Exercise 3: Magazine Layout

Create a magazine-style layout with:

Exercise 4: Interactive Order Example

Create a demo that shows how the order property affects layout:

Summary

In this lecture, we've explored the properties of flex items in depth:

These properties give you precise control over individual flex items, allowing for complex and responsive layouts. By combining these with the flex container properties we covered earlier, you have a powerful toolkit for creating almost any layout imaginable.

Remember that Flexbox is just one part of the modern CSS layout system. In the next modules, we'll explore CSS Grid, which complements Flexbox by providing a two-dimensional layout system that's perfect for more complex grid-based designs.