Difficulty: Intermediate
Flexbox solves several classic CSS layout problems that were notoriously difficult before its introduction. These patterns -- centering, the holy grail layout, sticky footers, and equal-height columns -- appear constantly in real-world applications and are frequently asked about in interviews. Understanding how to implement each with Flexbox demonstrates mastery of the layout model.
Perfect centering was famously difficult in CSS before Flexbox. The Flexbox solution is just three lines: display: flex, justify-content: center, and align-items: center on the container (plus a defined height). This works for any content -- single elements, groups of elements, text of unknown length. Before Flexbox, developers resorted to hacks like position: absolute with transform: translate(-50%, -50%), or display: table-cell with vertical-align: middle. The Flexbox approach is cleaner, more intuitive, and works without knowing the dimensions of the content.
The holy grail layout is a classic web design pattern consisting of a header, a three-column main section (navigation sidebar, content area, and aside/ads), and a footer. With Flexbox, the outer container uses flex-direction: column to stack header, main, and footer vertically. The main section is itself a flex container in row direction. The sidebar and aside have fixed widths (flex: 0 0 200px) while the content area fills the remaining space (flex: 1). The main section gets flex: 1 to expand and push the footer down.
The sticky footer pattern ensures the footer stays at the bottom of the viewport even when the page content is too short to push it there naturally. Without this pattern, short pages leave an awkward gap between the content and the bottom of the screen. The Flexbox solution wraps the entire page in a column flex container with min-height: 100vh, and sets flex: 1 on the main content area so it expands to fill all available space, pushing the footer to the bottom.
Equal-height columns are another problem Flexbox solves effortlessly. In older layout methods, columns with different amounts of content would have different heights, breaking the visual alignment. With Flexbox, items in a row stretch to the height of the tallest item by default (because align-items defaults to stretch). This means card grids and multi-column layouts automatically have uniform heights without any extra effort.
These patterns can be combined and adapted for complex real-world layouts. A typical application shell might combine the sticky footer pattern with the holy grail layout: the page uses a column flex container (header, main, footer) with the main section containing a sidebar and content area in a row flex container. Understanding how to compose these patterns is what separates a competent CSS developer from a great one.
/* Center anything horizontally and vertically */
.center-page {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Center multiple items in a column */
.center-column {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
gap: 24px;
}
/* Center with a max-width card */
.login-page {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 16px;
background-color: #f3f4f6;
}
.login-card {
width: 100%;
max-width: 420px;
padding: 32px;
background-color: white;
border-radius: 16px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
}
The two-property centering technique works for any content. Adding flex-direction: column stacks centered items vertically. The login card example shows a common real-world pattern with max-width and responsive padding.
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.header {
flex: 0 0 auto;
padding: 16px 24px;
background-color: #1f2937;
color: white;
}
.main {
display: flex;
flex: 1;
}
.sidebar {
flex: 0 0 220px;
padding: 24px;
background-color: #f3f4f6;
}
.content {
flex: 1;
padding: 24px;
}
.aside {
flex: 0 0 200px;
padding: 24px;
background-color: #f9fafb;
}
.footer {
flex: 0 0 auto;
padding: 16px 24px;
background-color: #1f2937;
color: white;
}
/* Responsive: stack on mobile */
@media (max-width: 768px) {
.main {
flex-direction: column;
}
.sidebar, .aside {
flex-basis: auto;
}
}
The page is a column flex container. The main section (flex: 1) is a nested row flex container holding the sidebar, content, and aside. On mobile, the main switches to column direction and the sidebars stack vertically.
/* Approach 1: Body as flex container */
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
.site-header {
flex: 0 0 auto;
}
.site-content {
flex: 1; /* Grows to push footer down */
}
.site-footer {
flex: 0 0 auto;
}
/* Approach 2: Wrapper div */
.page-wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.page-wrapper main {
flex: 1;
}
.page-wrapper footer {
margin-top: auto; /* Alternative: auto margin pushes to bottom */
}
The key is min-height: 100vh on the column flex container and flex: 1 on the main content. When content is short, the main area expands to fill the viewport, keeping the footer at the bottom. When content is long, the page naturally extends beyond the viewport.
.card-row {
display: flex;
gap: 24px;
}
.card {
flex: 1;
display: flex;
flex-direction: column;
background-color: white;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.card-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.card-body {
flex: 1;
padding: 20px;
}
.card-footer {
padding: 16px 20px;
border-top: 1px solid #e5e7eb;
margin-top: auto;
}
Cards in a flex row automatically get equal heights (default align-items: stretch). Each card is itself a column flex container. The card-body uses flex: 1 to fill available space, and the card-footer uses margin-top: auto to pin itself to the bottom regardless of content length.
Centering, Holy Grail, Sticky Footer, Equal-Height Columns, Layout Patterns