Flex Container Properties: Mastering the Core of Flexbox Layout â
Imagine you are an event planner responsible for arranging people's positions in a venue. As a planner, you need to decide: Should people stand in a row or a column? Should they be arranged from left to right or right to left? If there isn't enough space, should they wrap to the next line? How should the spacing between people be distributed? These decisions will affect the layout and atmosphere of the entire event.
In Flexbox, the Flex container is this planner. It controls the arrangement, alignment, and space distribution of the items inside it through a series of properties. Once you master these properties, you can create almost any layout effect you want.
Display: The Key to Enabling Flexbox â
Before diving into specific layout properties, we first need to understand how to enable Flexbox. This involves two special values of the display property.
display: flex â
This is the most commonly used way. When you set display: flex on an element, the element itself behaves as a block-level element (occupies a full line) externally, but its internal child elements will be arranged according to Flexbox rules.
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>.container {
display: flex;
background-color: #f5f5f5;
padding: 20px;
}
.item {
padding: 15px 30px;
background-color: #2196f3;
color: white;
margin: 5px;
}In this example, .container will occupy a full line, just like a normal <div>. But the three .item elements inside it will be arranged horizontally, which is the effect of Flexbox.
display: inline-flex â
Sometimes, you want the container itself to behave like an inline element, arranged on the same line as other elements. In this case, you can use display: inline-flex.
<div class="page-content">
This is a paragraph of text, followed by a
<div class="inline-container">
<span class="tag">Tag 1</span>
<span class="tag">Tag 2</span>
</div>
and then the text continues.
</div>.inline-container {
display: inline-flex; /* Container behaves as inline */
gap: 10px;
padding: 5px 10px;
background-color: #e3f2fd;
border-radius: 4px;
}
.tag {
padding: 4px 8px;
background-color: #2196f3;
color: white;
border-radius: 3px;
font-size: 12px;
}In this example, .inline-container will blend into the text flow, just like a normal <span> element. But the tags inside it will be arranged according to Flexbox rules.
The difference between the two can be understood as follows:
display: flex: Container is block externally (occupies a full line), flex internally (children follow Flexbox)display: inline-flex: Container is inline externally (can be on the same line as other elements), flex internally
In actual development, display: flex is used much more frequently than display: inline-flex because most layout containers need to occupy a full line.
Flex-Direction: Defining the Main Axis Direction â
flex-direction is probably one of the most important properties in Flexbox because it determines the direction of the main axis, which in turn affects the behavior of many other properties.
flex-direction: row (Default) â
This is the default value. The main axis is horizontal, from left to right. Items will be arranged from left to right like text.
.container {
display: flex;
flex-direction: row; /* Can be omitted as it is the default value */
}<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>Items will be arranged from left to right in the order of 1, 2, 3, 4. This is our most common Flexbox layout method.
flex-direction: row-reverse â
This value reverses the direction of the main axis, causing items to be arranged from right to left. Note that this doesn't just reverse the visual order, but truly changes the direction of the main axisâthe main axis start becomes the right side, and the end becomes the left side.
.container-reverse {
display: flex;
flex-direction: row-reverse;
}Using the same HTML, items will now be arranged from right to left in the order of 4, 3, 2, 1. This is useful in certain layouts, such as when you want the most important content on the right, or need to adapt to right-to-left languages (like Arabic).
flex-direction: column â
When you need vertical arrangement, use column. This changes the main axis direction to vertical, from top to bottom.
.container-column {
display: flex;
flex-direction: column;
height: 400px; /* Vertical layout usually requires explicit height */
}Now items will be arranged from top to bottom in the order of 1, 2, 3, 4, just like normal block-level elements. But the difference is that you can use all of Flexbox's alignment and space distribution functions.
A common application scenario is creating a vertical navigation menu:
<nav class="sidebar">
<a href="#" class="nav-link">Dashboard</a>
<a href="#" class="nav-link">Projects</a>
<a href="#" class="nav-link">Team</a>
<a href="#" class="nav-link">Settings</a>
</nav>.sidebar {
display: flex;
flex-direction: column;
width: 200px;
background-color: #2c3e50;
padding: 20px 0;
}
.nav-link {
padding: 15px 25px;
color: white;
text-decoration: none;
transition: background-color 0.3s;
}
.nav-link:hover {
background-color: #34495e;
}flex-direction: column-reverse â
Similar to row-reverse, this value reverses the vertical direction, causing items to be arranged from bottom to top.
.container-column-reverse {
display: flex;
flex-direction: column-reverse;
height: 400px;
}Items will be arranged from bottom to top in the order of 4, 3, 2, 1. This value is rarely used in practice, but can be useful in certain special scenarios, such as displaying the latest messages at the bottom in a chat interface.
Impact of Main Axis Direction â
Understanding flex-direction is important because it affects the behavior of other properties:
When
flex-directionisroworrow-reverse:- The main axis is horizontal,
justify-contentcontrols horizontal alignment - The cross axis is vertical,
align-itemscontrols vertical alignment
- The main axis is horizontal,
When
flex-directioniscolumnorcolumn-reverse:- The main axis is vertical,
justify-contentcontrols vertical alignment - The cross axis is horizontal,
align-itemscontrols horizontal alignment
- The main axis is vertical,
This might seem a bit confusing, but remember a simple rule: justify-content always controls the main axis direction, and align-items always controls the cross axis direction. Which direction is the main axis depends on flex-direction.
Flex-Wrap: Controlling Wrap Behavior â
By default, all flex items will try to squeeze into one line (or one column), even if there isn't enough space in the container. The flex-wrap property allows you to change this behavior.
flex-wrap: nowrap (Default) â
This is the default value. All items will be arranged in one line and will not wrap. If space is insufficient, items will shrink or overflow.
.container {
display: flex;
flex-wrap: nowrap; /* Default value, can be omitted */
width: 500px;
}
.item {
width: 150px; /* Each item is 150px */
padding: 20px;
}If we have 5 items, each 150px, totaling 750px, but the container is only 500px. In nowrap mode, the browser will force all items to squeeze into one line, and each item will be compressed to about 100px.
flex-wrap: wrap â
This value allows items to wrap. When one line cannot fit, items will automatically wrap to the next line.
.container-wrap {
display: flex;
flex-wrap: wrap;
width: 500px;
}
.item {
width: 150px;
padding: 20px;
}Now, if there are 5 items, the first 3 will be on the first line (3 Ã 150px = 450px, less than 500px), and the last 2 will automatically wrap to the second line. This is as natural as text typesetting.
A common application is responsive card layout:
<div class="card-grid">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<div class="card">Card 4</div>
<div class="card">Card 5</div>
<div class="card">Card 6</div>
</div>.card-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding: 20px;
}
.card {
width: 300px; /* Fixed width */
padding: 30px;
background-color: white;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}In this layout, cards will automatically wrap according to the container width. If the container width is 1000px, one line can fit 3 cards (considering gap); if the container width shrinks to 700px, one line can only fit 2 cards.
flex-wrap: wrap-reverse â
This value also allows wrapping, but new lines will appear above instead of below.
.container-wrap-reverse {
display: flex;
flex-wrap: wrap-reverse;
width: 500px;
}If 5 items need two lines, when using wrap, items 1-3 are on top, and items 4-5 are on the bottom. When using wrap-reverse, items 4-5 will be on top, and items 1-3 will be on the bottom.
This value is rarely used in practice, but might be used in some special visual designs.
Flex-Flow: Shorthand for Flex-Direction and Flex-Wrap â
flex-flow is a shorthand property for flex-direction and flex-wrap, making the code more concise.
/* Written separately */
.container {
flex-direction: row;
flex-wrap: wrap;
}
/* Using shorthand */
.container {
flex-flow: row wrap;
}The first value is flex-direction, and the second value is flex-wrap. If only one value is written, the other will use the default value.
.container {
flex-flow: column; /* Equivalent to flex-direction: column; flex-wrap: nowrap; */
}In actual development, whether to use flex-flow or write flex-direction and flex-wrap separately mainly depends on personal preference and team standards. Shorthand is more concise, while separate writing is more explicit.
Justify-Content: Main Axis Alignment â
justify-content controls the alignment and space distribution of items along the main axis. This is one of the most commonly used properties in Flexbox and can easily achieve various alignment effects.
justify-content: flex-start (Default) â
Items are arranged starting from the main axis start. This is the default behavior.
.container {
display: flex;
justify-content: flex-start; /* Default value */
}If the main axis is horizontal (flex-direction: row), items will align to the left. If the main axis is vertical (flex-direction: column), items will align to the top.
justify-content: flex-end â
Items are arranged starting from the main axis end.
.container-end {
display: flex;
justify-content: flex-end;
}In a horizontal main axis, items will align to the right. In a vertical main axis, items will align to the bottom.
This is useful when creating right-aligned navigation bars or button groups:
<div class="button-group">
<button class="btn btn-cancel">Cancel</button>
<button class="btn btn-primary">Save</button>
</div>.button-group {
display: flex;
justify-content: flex-end; /* Buttons align to the right */
gap: 15px;
padding: 20px;
}
.btn {
padding: 10px 24px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-cancel {
background-color: #e0e0e0;
color: #333;
}
.btn-primary {
background-color: #2196f3;
color: white;
}justify-content: center â
Items are arranged centered along the main axis.
.container-center {
display: flex;
justify-content: center;
}This is the simplest way to achieve horizontal centering. In traditional CSS, horizontal centering required setting margin: 0 auto and knowing the element width. In Flexbox, just one line justify-content: center.
<div class="hero">
<div class="hero-content">
<h1>Welcome to TechCorp</h1>
<p>Innovative solutions for modern businesses</p>
<button class="cta-button">Get Started</button>
</div>
</div>.hero {
display: flex;
justify-content: center; /* Horizontal centering */
align-items: center; /* Vertical centering */
min-height: 500px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.hero-content {
text-align: center;
color: white;
}justify-content: space-between â
This is a very practical value. It distributes items evenly, with the first item at the start and the last item at the end, and other items evenly distributed in between.
.container-between {
display: flex;
justify-content: space-between;
}Let's look at a concrete example. Suppose the container width is 600px, there are 4 items, each with a width of 100px:
<div class="nav">
<div class="logo">Logo</div>
<div class="nav-links">
<a href="#">Home</a>
<a href="#">Products</a>
<a href="#">Contact</a>
</div>
</div>.nav {
display: flex;
justify-content: space-between; /* Logo on left, links on right */
align-items: center;
padding: 20px 40px;
background-color: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.logo {
font-size: 24px;
font-weight: bold;
color: #2196f3;
}
.nav-links {
display: flex;
gap: 30px;
}
.nav-links a {
color: #333;
text-decoration: none;
}In this navigation bar, the Logo will automatically align to the left, navigation links will automatically align to the right, and the empty space in the middle will be automatically filled. This is the most common application scenario for space-between.
justify-content: space-around â
This value allocates equal space to both sides of each item. Note that this means the space between items is twice the space between items and the edges.
.container-around {
display: flex;
justify-content: space-around;
}If the container width is 800px, there are 3 items, each 100px, the remaining space is 500px. This 500px will be divided into 6 parts (one for each side of each item), each part about 83px. So:
- Left edge to first item: 83px
- First item to second item: 166px (83px + 83px)
- Second item to third item: 166px
- Third item to right edge: 83px
justify-content: space-evenly â
This value makes all spaces equal, including the space between items and edges.
.container-evenly {
display: flex;
justify-content: space-evenly;
}Using the same example (container 800px, 3 items 100px each), the remaining 500px will be divided into 4 parts (between items and two edges), each part 125px. So:
- Left edge to first item: 125px
- First item to second item: 125px
- Second item to third item: 125px
- Third item to right edge: 125px
This even distribution effect is useful in scenarios like icon groups and social media links:
<div class="social-links">
<a href="#" class="social-icon">đ</a>
<a href="#" class="social-icon">đĻ</a>
<a href="#" class="social-icon">đˇ</a>
<a href="#" class="social-icon">đŧ</a>
</div>.social-links {
display: flex;
justify-content: space-evenly;
padding: 30px;
background-color: #f5f5f5;
border-radius: 8px;
}
.social-icon {
font-size: 32px;
text-decoration: none;
transition: transform 0.3s;
}
.social-icon:hover {
transform: scale(1.2);
}Align-Items: Cross Axis Alignment â
If justify-content controls the main axis, then align-items controls the cross axis. It determines how items align along the cross axis direction.
align-items: stretch (Default) â
This is the default value. Items will stretch to fill the height (or width) of the container along the cross axis.
.container {
display: flex;
align-items: stretch; /* Default value */
height: 200px;
}If the container height is 200px, all items will automatically stretch to 200px high, even if they have little content. This is why achieving equal-height columns is so simple in Flexbox.
Note that if items have an explicit height set (when main axis is row) or width (when main axis is column), the stretch effect will be overridden.
align-items: flex-start â
Items align at the start of the cross axis.
.container-start {
display: flex;
align-items: flex-start;
height: 200px;
}In a horizontal main axis, items will align to the top. In a vertical main axis, items will align to the left. Items will not stretch but maintain their natural height.
align-items: flex-end â
Items align at the end of the cross axis.
.container-end {
display: flex;
align-items: flex-end;
height: 200px;
}In a horizontal main axis, items will align to the bottom. This is useful when creating bottom-aligned elements, like buttons at the bottom of price cards.
align-items: center â
Items align centered along the cross axis. This is probably one of the most commonly used values for align-items.
.container-center {
display: flex;
align-items: center;
height: 200px;
}Combined with justify-content: center, you can easily achieve perfect horizontal and vertical centering:
.perfect-center {
display: flex;
justify-content: center; /* Horizontal centering */
align-items: center; /* Vertical centering */
height: 400px;
background-color: #f5f5f5;
}These two lines of code solve one of the oldest problems in CSS.
align-items: baseline â
Items align according to their baseline. The baseline is a concept in typography, simply understood as the reference line at the bottom of the text.
<div class="baseline-demo">
<div class="item item-small">Small</div>
<div class="item item-medium">Medium</div>
<div class="item item-large">Large</div>
</div>.baseline-demo {
display: flex;
align-items: baseline;
height: 200px;
background-color: #f5f5f5;
}
.item-small {
font-size: 16px;
}
.item-medium {
font-size: 24px;
}
.item-large {
font-size: 48px;
}Although the font sizes of the three items are different, the bottom of their text will be on the same line. This is useful in scenarios where you need to align text of different sizes.
Align-Content: Multi-line Alignment â
align-content only has an effect when there are multiple lines, that is, when flex-wrap: wrap is set and items actually wrap. It controls the alignment and space distribution between multiple lines.
Why Need align-content â
When items wrap, multiple lines (or columns) are created. align-items controls the alignment of items within each line, while align-content controls the alignment of these lines themselves.
<div class="multi-line">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>.multi-line {
display: flex;
flex-wrap: wrap;
width: 400px;
height: 300px;
background-color: #f5f5f5;
border: 2px solid #333;
}
.item {
width: 120px;
padding: 20px;
background-color: #2196f3;
color: white;
margin: 5px;
}In this example, each line can fit 3 items (considering margin), so there will be two lines. align-content determines how these two lines are distributed within the 300px height.
Various Values of align-content â
The values of align-content are very similar to justify-content:
- stretch (Default): Lines stretch to fill remaining space
- flex-start: Lines pack to the start of the cross axis
- flex-end: Lines pack to the end of the cross axis
- center: Lines pack to the center of the cross axis
- space-between: First line at start, last line at end, others distributed evenly
- space-around: Equal space on both sides of each line
- space-evenly: All spaces are equal
/* Evenly distribute between lines */
.multi-line-between {
display: flex;
flex-wrap: wrap;
align-content: space-between;
width: 400px;
height: 300px;
}Gap: Modern Spacing Control â
gap is a relatively new property that provides a more intuitive way to set spacing between items. Before gap appeared, we usually used margin to set spacing, but this caused some problems.
Problems with Traditional Methods â
When using margin to set spacing, items on the edges also get margin, which is usually not what we want:
/* Problem with using margin */
.item {
margin: 10px; /* Each item has margin */
}This causes a 10px gap at the edges of the container as well. We need to use various tricks to eliminate the edge margin, such as:
.container {
margin: -10px; /* Offset with negative margin */
}
.item {
margin: 10px;
}
/* Or */
.item:first-child {
margin-left: 0;
}
.item:last-child {
margin-right: 0;
}These methods are not elegant enough.
Using the gap Property â
The gap property only creates spacing between items, not at the edges:
.container {
display: flex;
gap: 20px; /* Create 20px spacing only between items */
}It's that simple! No negative margins, no edge cases to handle.
gap is actually a shorthand for row-gap and column-gap:
/* Full syntax */
.container {
row-gap: 20px; /* Spacing between rows */
column-gap: 30px; /* Spacing between columns */
}
/* Shorthand */
.container {
gap: 20px 30px; /* First value is row-gap, second is column-gap */
}
/* If both values are the same, you can write just one */
.container {
gap: 20px; /* row-gap and column-gap are both 20px */
}In wrapped Flexbox layouts, gap is particularly useful:
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 30px; /* 30px spacing between all cards */
}
.card {
width: calc(33.333% - 20px); /* Width calculation considering gap */
}Browser Support â
Note that support for the gap property in Flexbox is relatively new. Older browsers might not support it. If you need to support old browsers, you might still have to use the traditional margin method.
Support status of major browsers (gap in Flexbox):
- Chrome 84+ (2020)
- Firefox 63+ (2018)
- Safari 14.1+ (2021)
- Edge 84+ (2020)
If your project needs to support older browsers, you can use CSS feature detection:
.container {
display: flex;
}
.item {
margin: 10px; /* Fallback solution */
}
@supports (gap: 20px) {
.container {
gap: 20px;
}
.item {
margin: 0; /* If gap is supported, remove margin */
}
}Practical Application Examples â
Let's synthesize these properties through a few complete examples.
Responsive Navigation Bar â
<nav class="navbar">
<div class="brand">
<img src="logo.png" alt="Logo" class="logo" />
<span class="brand-name">TechCorp</span>
</div>
<ul class="nav-menu">
<li><a href="#home">Home</a></li>
<li><a href="#services">Services</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
<div class="nav-actions">
<button class="btn-login">Login</button>
<button class="btn-signup">Sign Up</button>
</div>
</nav>.navbar {
display: flex;
justify-content: space-between; /* Three areas at ends and middle */
align-items: center; /* Vertical centering */
padding: 15px 40px;
background-color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.brand {
display: flex;
align-items: center;
gap: 12px;
}
.logo {
width: 40px;
height: 40px;
}
.brand-name {
font-size: 20px;
font-weight: bold;
color: #2196f3;
}
.nav-menu {
display: flex;
gap: 30px;
list-style: none;
margin: 0;
padding: 0;
}
.nav-menu a {
color: #333;
text-decoration: none;
font-weight: 500;
transition: color 0.3s;
}
.nav-menu a:hover {
color: #2196f3;
}
.nav-actions {
display: flex;
gap: 15px;
}
.btn-login,
.btn-signup {
padding: 10px 24px;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
transition: all 0.3s;
}
.btn-login {
background-color: transparent;
color: #2196f3;
}
.btn-login:hover {
background-color: #e3f2fd;
}
.btn-signup {
background-color: #2196f3;
color: white;
}
.btn-signup:hover {
background-color: #1976d2;
}
/* Responsive: Small screens */
@media (max-width: 768px) {
.navbar {
flex-direction: column;
gap: 20px;
}
.nav-menu {
flex-direction: column;
text-align: center;
gap: 15px;
}
}Pricing Table Layout â
<div class="pricing-container">
<div class="pricing-card">
<h3>Starter</h3>
<div class="price">$9<span>/month</span></div>
<ul class="features">
<li>5 Projects</li>
<li>2GB Storage</li>
<li>Email Support</li>
</ul>
<button class="btn-choose">Choose Plan</button>
</div>
<div class="pricing-card featured">
<div class="badge">Popular</div>
<h3>Professional</h3>
<div class="price">$29<span>/month</span></div>
<ul class="features">
<li>Unlimited Projects</li>
<li>50GB Storage</li>
<li>Priority Support</li>
<li>Advanced Analytics</li>
</ul>
<button class="btn-choose">Choose Plan</button>
</div>
<div class="pricing-card">
<h3>Enterprise</h3>
<div class="price">$99<span>/month</span></div>
<ul class="features">
<li>Unlimited Everything</li>
<li>500GB Storage</li>
<li>24/7 Support</li>
<li>Custom Solutions</li>
</ul>
<button class="btn-choose">Choose Plan</button>
</div>
</div>.pricing-container {
display: flex;
justify-content: center; /* Center cards */
align-items: stretch; /* All cards equal height */
gap: 30px;
padding: 60px 20px;
background-color: #f5f5f5;
}
.pricing-card {
position: relative;
display: flex;
flex-direction: column; /* Vertically arrange content */
width: 320px;
padding: 40px 30px;
background-color: white;
border-radius: 12px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
transition: transform 0.3s, box-shadow 0.3s;
}
.pricing-card:hover {
transform: translateY(-8px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
.pricing-card.featured {
border: 2px solid #2196f3;
transform: scale(1.05);
}
.badge {
position: absolute;
top: 20px;
right: 20px;
padding: 6px 12px;
background-color: #2196f3;
color: white;
font-size: 12px;
font-weight: bold;
border-radius: 4px;
}
.pricing-card h3 {
margin: 0 0 20px 0;
font-size: 24px;
color: #333;
}
.price {
margin-bottom: 30px;
font-size: 48px;
font-weight: bold;
color: #2196f3;
}
.price span {
font-size: 18px;
color: #666;
font-weight: normal;
}
.features {
flex-grow: 1; /* Occupy all remaining space */
margin: 0 0 30px 0;
padding: 0;
list-style: none;
}
.features li {
padding: 12px 0;
color: #666;
border-bottom: 1px solid #eee;
}
.features li:last-child {
border-bottom: none;
}
.btn-choose {
padding: 14px 28px;
background-color: #2196f3;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.3s;
}
.btn-choose:hover {
background-color: #1976d2;
}Summary â
Flex container properties are the core of mastering Flexbox layout. Let's review the key points:
Core Properties:
- display: flex / inline-flex: Enables Flexbox, determines the external behavior of the container
- flex-direction: Defines the main axis direction (row, column, row-reverse, column-reverse)
- flex-wrap: Controls whether to wrap (nowrap, wrap, wrap-reverse)
- justify-content: Main axis alignment (flex-start, flex-end, center, space-between, space-around, space-evenly)
- align-items: Cross axis alignment (stretch, flex-start, flex-end, center, baseline)
- align-content: Multi-line alignment (only effective when wrapping)
- gap: Item spacing (modern method, concise and intuitive)
Memory Tricks:
justify-contentalways controls the main axisalign-itemsalways controls the cross axis- Main axis direction is determined by
flex-direction gaponly creates spacing between items, not affecting edges
Best Practices:
- Start with simple
display: flex - Determine the main axis direction first (
flex-direction) - Adjust alignment as needed (
justify-contentandalign-items) - Use
gapinstead ofmarginto set spacing (if browser supports) - Use
flex-wrap: wrapin layouts that need to wrap
After mastering these container properties, you can already create most common layouts. In the next section, we will learn about Flex item properties, which allow you to control the behavior of individual items more precisely.