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.
Module 6: Modern CSS & Layouts - Monday (Lecture 3)
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.
These properties work together to determine how flex items size themselves and position themselves within their container. Let's explore each one in detail.
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.
/* 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;
}
Here's how the browser calculates the width of items with flex-grow:
flex-basis (or intrinsic size if flex-basis: auto)flex-grow valuesflex-grow value
For example, if three items have flex-grow values of 1, 2, and 1 respectively, and there's 400px of remaining space:
flex-grow is 1 + 2 + 1 = 4A 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.
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.
/* 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;
}
Here's how the browser calculates the width of items with flex-shrink:
flex-basisflex-shrink value and the item's sizeflex-shrink value multiplied by its size
The calculation is a bit more complex than flex-grow because it factors in the item's size:
flex-shrink valueflex-shrink: 0 prevents the item from shrinking below its flex-basisIn 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.
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.
/* 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%;
}
The different values of flex-basis have important implications:
auto: The item's size is determined by its content (or width/height if specified)0: The item starts with zero size, meaning flex-grow will determine the size without considering content200px): The item starts with this exact size
One key distinction is flex-basis: 0 vs. flex-basis: auto when used with flex-grow:
flex-basis: auto, items with more content will naturally be largerflex-basis: 0, the content size is ignored, and items will be sized purely based on their flex-grow valuesWhen 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.
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.
/* 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;
}
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 declaration flex: 1 is one of the most common and useful Flexbox patterns. It's equivalent to:
flex-grow: 1 - The item can grow to fill available spaceflex-shrink: 1 - The item can shrink if necessaryflex-basis: 0% - The item starts with zero size, ignoring content size
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.
A common pattern for dashboard layouts is to have a mix of flexible and fixed-width widgets:
.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.
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.
/* 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;
}
align-self is particularly useful when:
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.
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 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;
}
The browser arranges flex items in ascending order based on their order value:
order value are arranged according to their source order in the HTMLorder values appear before items with higher valuesorder values are valid and will place items before those with order: 0
While order is powerful, it's important to consider accessibility:
order property only affects the visual order, not the source order in the HTML
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.
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.
A common e-commerce pattern is a grid of product cards with consistent layouts:
.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.
A news website might have a layout with a main featured article and sidebar articles:
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.
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 */
}
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 */
}
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 */
}
Creating columns of equal height regardless of content:
.container {
display: flex;
}
.column {
flex: 1 1 0; /* Equal growth, starting from zero basis */
}
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 */
}
Instead of setting flex-grow, flex-shrink, and flex-basis separately, use the flex shorthand for more concise and readable code.
Understand the difference between flex: 1 1 auto and flex: 1 1 0:
flex: 1 1 auto - Items will be sized based on their content before distributing extra spaceflex: 1 1 0 (or simply flex: 1) - Items will ignore their content size and distribute space purely based on flex-grow valuesBe aware that flex items can overflow their container if:
flex-shrink: 0 and there's not enough space
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.
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.
Always test how your flex items behave when the container is resized. Items might not shrink or grow as expected under certain conditions.
Use media queries to adjust flex item properties at different screen sizes, creating truly responsive layouts.
If items have substantial content (like text that doesn't wrap), they might not shrink as expected even with flex-shrink: 1. Solutions include:
min-width: 0 to allow further shrinkingoverflow: hidden or other overflow properties to clip contentword-wrap: break-word
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.
Images can cause layout issues in flex items if they're too large. Solutions include:
max-width: 100% on imagesobject-fit for better image sizing control
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.
If you have items with flex: 0 0 [size] and they don't fit, they'll overflow the container. Consider:
flex-wrap: wrap on the containermin-width instead of flex-basis for a more flexible approachCreate a layout with three cards where:
Populate the cards with varying amounts of content to test the layout.
Create a form with the following requirements:
Create a magazine-style layout with:
Create a demo that shows how the order property affects layout:
In this lecture, we've explored the properties of flex items in depth:
flex-grow - Controls how items grow to fill available spaceflex-shrink - Controls how items shrink when there's not enough spaceflex-basis - Sets the initial size of items before growing/shrinkingflex - Shorthand for the above three propertiesalign-self - Overrides the container's align-items for individual itemsorder - Controls the visual order of itemsThese 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.