Layout Technique: Flexbox and Grid
Session Time: 120 minutes
Table of Contents
- Introduction: Modern Layouts for AI Interfaces
- Flexbox: One-Dimensional Layouts
- CSS Grid: Two-Dimensional Layouts
- AI-Assisted Layout Design
- Lab: Building a Multi-Section Layout
- Wrap-Up and Reflection
Learning Objectives
Upon completion of this session, participants will be able to:
- Develop responsive layouts using Flexbox for alignment and CSS Grid for complex structures.
- Analyze layout behavior across different breakpoints (mobile vs. desktop) to ensure content readability.
- Employ AI to simulate alternative layout solutions and troubleshoot common alignment issues (e.g., overflowing content).
Session Breakdown
| Segment | Topic | Duration (minutes) |
|---|---|---|
| Introduction | From Floats to Modern Layout Systems | 15 |
| Concept I | Flexbox (The Axis System) | 25 |
| Concept II | CSS Grid (Rows and Columns) | 25 |
| AI Tooling | Visualizing Code with AI | 15 |
| Practical Lab | Lab: Building a Multi-Section Layout | 30 |
| Conclusion | Wrap-Up and Reflection | 10 |
| Total | 120 minutes |
1. Introduction: Modern Layouts for Web Interfaces
Learning objective: Understand why modern CSS layout systems are essential for UI dashboards and model demos.
Historically, web layout was difficult (using tables or floats). Today, we use two powerful systems: Flexbox and Grid.
The Python Analogy
- Flexbox: One-Dimensional Layout - It handles items in a single line (row or column).
- Grid: The Two Axes Layout - It handles items in both rows and columns simultaneously.
2. Flexbox: One-Dimensional Layouts
Learning objective: Implement Flexbox to align items along a main axis.
Flexbox (Flexible Box Layout) is designed for laying out items in a single dimension. It is perfect for navigation bars, centering elements, or distributing space evenly.
Prior to flexbox, laying out the parts of a web page - from basic navigation headers to complex full-page layouts - was very difficult. The introduction of flexbox revolutionized the way we approach web design.
At first glance, flexbox might seem like it operates only in a single dimension, essentially in a line. However, as you dive deeper into this lesson, you'll discover that flexbox's capabilities extend beyond that. It allows you to nest flexboxes within one another, enabling you to create complex 2-dimensional layouts that were once quite challenging to achieve.

Why Use flexbox?
Here are some key advantages of using flexbox over other methods of positioning in CSS:
Vertically centering content: Flexbox simplifies the task of vertically centering content and elements within a container, a task that used to require tricky workarounds.
Uniform spacing: It provides an elegant solution for evenly spacing child elements within a container, ensuring your designs look polished and consistent.
Equalizing column heights: Flexbox can make the heights of child elements, even if they contain varying amounts of content, appear the same. This is a game-changer for creating visually appealing layouts that contain alot of text.
Responsive design made easy: Flexbox empowers you to create complex, responsive designs with ease. It replaces less dependable strategies, making your code more maintainable and future-proof.
The Two Axes
To use Flexbox, you apply display: flex; to the parent container. You then control the children based on two axes:
- Main Axis: Controlled by
justify-content(e.g., left-to-right). - Cross Axis: Controlled by
align-items(e.g., top-to-bottom).
Common Properties
| Property | Value | Description |
|---|---|---|
display |
flex |
Turns the container into a flex context. |
flex-direction |
row (default) | column |
Defines the main axis direction. |
justify-content |
center | space-between |
Aligns items along the Main Axis. |
align-items |
center | stretch |
Aligns items along the Cross Axis. |
Code Example:
.navbar {
display: flex;
justify-content: space-between; /* Pushes items to edges */
align-items: center; /* Centers vertically */
}Flexbox Fundamentals
Let's explore some fundamental facts about the HTML structure we're dealing with. Building a solid understanding of how our elements behave by default will make it easier to see the changes when we start using flexbox.
<section class="flex-parent">
<div class="flex-child" id="one">1</div>
<div class="flex-child" id="two">2</div>
<div class="flex-child" id="three">3</div>
<div class="flex-child" id="four">4</div>
</section>The <section> element acts as a parent container for all four <div> elements within it. These <div> elements are considered the children of the <section> element, as indicated by our class names. It's important to note we don't see the <section> element's background color anywhere on our page - it is currently hidden behind the backgrounds of its child elements.

The <section> element is a block element. Block elements automatically expand to occupy the entire width of their parent element, which, in this case, is the body element. Since the body element, by default, spans the full width of the browser window, our <section> element also covers the entire width of the browser window.

Each <div> element inside the <section> is also a block element by default. Therefore, they also occupy the entire width of their parent element, which in this case, is the <section>. This explains why each <div> element spans the full width of the browser window.

By default, the height of these elements is determined by the content they contain. Unless you specify otherwise, they will be just as tall as they need to be to accommodate the content within them.

The same height behavior applies to the <section> element. Its height is entirely based on the combined height of its children elements. This is why the background color of the <section> element isn't visible on the page—it matches the total height of its child elements.

If you were to remove the text content from one of the <div> elements, it might seem as if the element has disappeared from the page, but it hasn't! Its height has just been reduced to 0
In our code, we have assigned classes flex-parent and flex-child to these items. However, the actual implementation of flexbox will take place in our CSS file. The class names themselves do not provide any functionality; they are for organizational purposes.
Implementing flexbox
Now, let's explore how to enable flexbox on our page. We've discussed the default behavior of our elements before applying flexbox, but now we'll introduce the changes.
To implement flexbox, you'll need to modify the existing .flex-parent rule in your CSS like this:
.flex-parent {
background-color: black;
display: flex;
}We achieve this by adding a CSS property, display, set to the value flex. This declaration transforms an element into a flex container or parent.
🧠 It's essential to note that the specific class name,
flex-parent, is not crucial to enable flexbox functionality. We're using it here to clarify the establishment of the parent-child relationship. In practice, you'd typically use more descriptive class names likecontainerfor better clarity.
After this change, your browser should look like this:

Let's review what has changed:
The
<section>element has transformed into a flex parent or flex container.When we applied flexbox to it, all the child
<div>elements switched from being block elements to inline-block elements. Their height remains the same, but their width now matches the width of their content.As a result, the
<div>elements no longer stretch to the full width of the<section>. You can now see the black background of the<section>element. Additionally, notice that the height of the<section>element has adjusted to match the combined height of its child elements.The
<div>elements nested inside our flex-parent<section>(these are its children) have become flex children or flex items. They are automatically arranged in a row within their parent. This horizontal arrangement is the default behavior of a flexbox.
4. Flexbox Properties
display: flex
Once you've enabled flexbox on a parent container, the behavior of its children changes. You gain control over how they align both horizontally and vertically within their container.
🧠 It's important to remember that, in flexbox, you primarily apply properties to the parent element, not the children.
Now, let's experiment with what we've learned and coded so far. First to give ourselves more space, we'll make some adjustments to the flex-parent and flex-child classes.
Add the following to the flex-parent:
.flex-parent {
background-color: black;
display: flex;
height: 600px; /* more space to move things around */
}and the following to flex-child:
.flex-child {
font-size: 48px;
height: 100px; /* lets make our boxes larger */
width: 100px;
}Small changes, but note that we have a slightly bigger sandbox to play in now.
justify-content
Now, let's dive into one of the most commonly used alignment properties in flexbox - justify-content. We'll apply it to the flex-parent class to see how it affects the layout of our elements.
.flex-parent {
background-color: black;
display: flex;
height: 600px;
justify-content: space-around;
}With this code, we're telling the browser to arrange our child elements with space distributed evenly around them within the flex container.

The justify-content property in flexbox can take several values, each of which affects how flex items are positioned along the main axis (horizontal axis) inside a flex container.
Take a moment to try out the following values for justify-content:
space-between: It evenly distributes the available space between flex items, with no space before the first item and after the last item. This creates a layout where items are as far apart as possible.space-evenly: This value distributes space evenly between and around flex items, including space before the first item and after the last item.
align-items
The align-items property allows you to control the vertical alignment of flex items within a flex container. By setting this property to values like flex-start, center, or flex-end, you can position your elements along the cross-axis (the perpendicular axis to the main axis) to achieve the desired layout.
🎓 You Do
Using the justify-content and align-items properties, experiment with centering the <div>s inside of the <section> both horizontally and vertically. Note how these properties affect the elements' positioning on a different axis.
flex-direction
Think of flex-direction as the blueprint for arranging your elements. It defines the primary direction in which elements flow within the container.
flex-direction: row (default) is like a horizontal row of books where elements line up from left to right.flex-direction: column is like stacking blocks on top of each other, creating a vertical arrangement.
To test this, let's adjust the .flex-parent rule to create a column layout:
.flex-parent {
background-color: black;
display: flex;
height: 600px;
flex-direction: column;
}And here's the result! Now the elements are laid out in a column!

Let's apply one more change to the .flex-parent rule: justify-content: space-around;

Notice how the behavior of the justify-content property differs from when the flex-direction was its default value, row.
Main axis and cross axis
A flex container always has a main axis as well as a cross axis.
When the flex-direction is set at its default row:
- The main axis is horizontal and is controlled by modifying the
justify-contentproperty. - The cross axis is vertical and is controlled by modifying the
align-itemsproperty.

If the flex-direction is set to column, they reverse:
- The main axis is vertical and is controlled by modifying the
justify-contentproperty. - The cross axis is horizontal and is controlled by modifying the
align-itemsproperty.

🧠 You don't need to memorize this immediately. Practice with flexbox as you build layouts, and you'll understand it over time through hands-on experience. Instead of stressing over memorization, embrace experimentation. It's all about learning by doing!
🚀 Ready to Level up?
Now that you have some base knowledge, you can review and refer to the comprehensive go to guide to flexbox for more in-depth exploration of flexbox capabilities in the future.
5. Nesting Flexboxes
To create more intricate designs, we can nest flexbox containers within other flexbox containers. Here's an example with changes to both the flex-parent and flex-child classes:
.flex-parent {
background-color: black;
display: flex;
height: 600px;
justify-content: space-around;
align-items: center;
}
.flex-child {
font-size: 48px;
height: 100px;
width: 100px;
display: flex;
}Now, any element with the flex-child class becomes a flexbox itself.
Following our naming conventions, flex-child may not be the best name for this class now. However, it demonstrates that flex children can also be flex parents!
A couple of key points to note:
- This doesn't affect how the flex children inside the existing flex parent behave. They will still follow the existing rules for flex children. If needed, we can apply child-specific properties to the
flex-childclass. Just like in real life, someone can simultaneously be a parent of a child and a child of a parent. - What are the child elements of the
flex-child<div>s? Even though there aren't specific elements inside of them, text is considered an element itself. So, if we apply rules to these elements that impact their children, it will affect the text as well.
This means that with this change:
.flex-child {
font-size: 48px;
height: 100px;
width: 100px;
display: flex;
justify-content: center;
align-items: center;
}The text (the numbers in our boxes) will be centered both horizontally and vertically within their boxes. Cool!
CSS Grid : Concepts
CSS Grid emerged as a game-changer in web design, offering a two-dimensional system for precise element alignment and layout control. It replaced older, less flexible methods like floats and positioning, revolutionizing web page layouts.
Why choose CSS Grid?
- Ease of use: Grid's straightforward syntax simplifies layout creation.
- Responsive design: Easily adapt layouts for different screens using media queries.
- Accessibility: Pairing Grid with semantic HTML enhances user accessibility.
- Clean code: Grid reduces code complexity and increases maintainability.
- Versatile layouts: From multi-column to complex structures, Grid handles it all.

Ideal use cases for CSS Grid
- Multi-column layouts: Effortlessly create layouts with multiple columns and sidebars.
- Complex page structures: Manage intricate designs, nested grids, and dynamic content.
- Responsive websites: Build layouts that fluidly adjust to various screen sizes.
- Interactive UI components: Ideal for menus, modals, and carousels.
- Controlled white space: Maintain consistent spacing and dedicated blank areas with grid gap.
Let's dive in!
CSS Grid : Fundamentals
Grids are made of up of several components:
- Tracks (Rows and Columns)
- Rows: Horizontal tracks of the grid. Their size can be defined using
grid-template-rows. - Columns: Vertical tracks of the grid. Their size is set with
grid-template-columns.
- Rows: Horizontal tracks of the grid. Their size can be defined using
- Cells - The intersection of a grid row and a grid column, akin to a cell in a table. Each cell is a single unit of the grid where you can place your content
- Areas - A grid area is a rectangular space created by combining one or more cells
- Gaps - The spaces between rows and columns, previously known as 'gutters'.
This diagram is helpful for visualizing the role each of these components plays:

To read more in depth about grid components and get a detailed user guide, check out the Complete Guide to CSS Grid from CSS Tricks.
Implementing a sample design
Let's start exploring CSS Grid by building a mock website layout. This is a great way to see how it works in a real-world example. We'll put together a straightforward page layout that really shows off what CSS Grid can do.
By the end of this lesson, we'll create a generic (yet common) website layout:

Start with page structure
Creating a layout starts with the physical structure of your page - the HTML.
We'll start with some basic components of a website - header, footer, and something in the middle.
Add the following starter code inside of the <body> tag of your HTML:
<body>
<nav class="nav-links">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Widgets</a>
<a href="#">Log out</a>
</nav>
<aside>Side Content</aside>
<main>Main Content</main>
<footer>Footer Content</footer>
</body>Take a moment to open your page in the browser. Without any css to alter their positioning, these elements behave exactly like we'd expect block level elements to behave.

Creating your first grid
The foundation of any CSS Grid layout is the grid container, an HTML element that serves as the parent for all grid items within.
To create our grid container, we'll need to:
Identify the container element: Begin by selecting an HTML element that will act as the container for your grid. This element will hold all the grid items. Given our current HTML structure, the
bodyelement is the most logical choice.Apply the display property: To apply our grid style to the container, we'll add the
display: grid;property to thebodyelement. This step transforms the element into agrid container, and affects the positioning behavior of the child elements.
Create your grid by adding the following code into css/style.css:
body {
display: grid;
}Great! This code turns our <body> element into a grid container, but when we check the browser, everything looks the same?
Until we give our grid more instructions about how our sections should be laid out, our page structure looks the same.
Let's add a few non grid styles to define the overall look of our page first.
body {
background-color: lightgray;
display: grid;
font-family: sans-serif;
font-size: 24px;
min-height: 100vh;
}These styles add a light gray background, sans-serif font, and ensures that the body element stretches to at least the full height of the viewport.

min-height: 100vhSets the minimum height of the<body>to 100% of the viewport height (vh stands for viewport height). This ensures that the body takes up at least the full height of the screen, regardless of the amount of content. When we apply this, the page allocates equal space to all the vertical elements. This tells our grid layout to fill all available space in the browser window.
Now to add a bit of differentiating style to the individual page sections. Add the following to your css/style.css file:
aside {
background-color: #38b18a;
}
main {
background-color: #92d97c;
}
footer {
background-color: #f9f871;
}Check your work in the browser:

Why the extra gray around the edges?
Remove browser defaults
Browsers often set default styles for certain elements, including margins and padding on elements such as headers and divs. In this case the browser is adding some default margin to the body element, causing this extra stripe of gray around the pages edge. To gain complete control over our layout's margins and padding, let's reset these default styles.
body {
background-color: lightgray;
display: grid;
font-family: sans-serif;
font-size: 24px;
min-height: 100vh;
/* Add the following */
margin: 0;
padding: 0;
}No more extra margin!
Set grid properties
Time to define the columns and rows necessary to bring our layout to life.
Take a look at our design example again:

Considering the layout above:
- How many horizontal rows do we need to define?
- How many vertical columns do we need to define?
If you said 3 rows and 2 columns, you are correct!
We'll use the CSS properties grid-template-columns and grid-template-rows to define the size and number of columns and rows in our grid.
Add the following lines to our existing body rule in css/style.css:
body {
background-color: lightgray;
display: grid;
/* Add the following */
grid-template-rows: auto 1fr auto; /* three rows defined here */
grid-template-columns: 1fr 2fr; /* two columns defined here */
font-family: sans-serif;
font-size: 24px;
min-height: 100vh;
margin: 0;
padding: 0;
}Let's unpack what is happening here:
grid-template-rows: auto 1fr auto;
- This property defines the height of the rows in the grid.
auto: The first and third rows will automatically adjust their height based on the content they contain. The row height will be as tall as the content needs it to be, no more and no less.1fr: The second row will be flexible and take up the remaining space in the grid container.
grid-template-columns: 1fr 2fr;
- This property defines the width of the columns in the grid.
1fr: The first column will take up one fraction of the available space in the grid container.2fr: The second column will take up twice the amount of space as the first column, in other words, two fractions of the available space.- Together, these two values divide the grid container's horizontal space into two columns with the specified width proportions.
The
frunit in CSS Grid is a flexible and relative length unit used to define the size of columns and rows within a grid layout. It stands for "fraction" and represents a fraction of the available space in the grid container.
Take a look at the output after our changes. Not exactly what we were hoping for:

If you think about a grid with 3 rows and 2 columns, you're probably picturing something like this:
| 1 | 2 |
|---|---|
| 3 | 4 |
| 5 | 6 |
There are six spaces, but we only have 4 sections in our page, so grid will try and figure out the layout that we want based on this limited information.
By default, it gives each section one cell from left to right and omits the bottom row because it isn't in use.
Spanning multiple rows and cols
In our design example the nav, and footer sections are meant to go all the way across the screen, spanning the width of both columns in the layout.
Let’s make both the <nav> and the <footer> span two columns each.
There are several ways to accomplish this using the grid-column CSS property. Here are the two most common.
Spanning Multiple Columns: Use
grid-column: span X;to stretch a grid item acrossXnumber of columns. For example,grid-column: span 2; makes an item cover two columns.Starting and Ending Lines: Specify starting and ending column lines with
grid-column: start / end;. For instance,grid-column: 1 / 3;stretches the item from the first to the third column line, spanning two columns.
Let's add the following directly to the nav and footer elements:
nav,
footer {
grid-column: span 2;
}We can achieve the same result with start / end using gide lines:
nav,
footer {
grid-column: 1 / 3;
}That's more like it!

Unsurprisingly, there’s also a grid-row property which allows you to specify the same behavior for grid cells spanning across rows.
Now that our page sections are in their proper positions, we can add a few extra styles to give the nav and footer some extra height.
nav,
footer {
grid-column: span 2;
height: 60px;
}
a {
text-decoration: none; /* remove default underline */
color: black;
}Check your final output:

Great job! You've just created your first grid layout!
Grid Template Areas
grid-template-areas allows us to create a grid layout in a more intuitive way. First, you assign area names to the html elements you want to control your grid. Then you create a "map" of these items using the grid-template-areas property on your grid container.
body {
display: grid;
font-family: sans-serif;
font-size: 24px;
grid-template-rows: auto 1fr auto;
grid-template-columns: 1fr 2fr;
grid-template-areas:
"nav nav nav" /* <- place area names in rows and cols as you want them displayed */
"aside main main"
"footer footer footer";
min-height: 100vh;
margin: 0;
padding: 0;
}Notice how the structure of the named areas in grid-template-areas looks like a mini version of our page layout in our CSS. For this reason, some people find it easier to use grid-template-areas because you can "visualize" the grid in your CSS as you create it.
If you want to test out this alternate syntax, you can replace all of your existing CSS with the following:
body {
display: grid;
font-family: sans-serif;
font-size: 24px;
grid-template-rows: auto 1fr auto;
grid-template-columns: 1fr 2fr;
grid-template-areas:
"nav nav nav"
"aside main main"
"footer footer footer";
min-height: 100vh;
margin: 0;
padding: 0;
}
aside {
background-color: #38b18a;
grid-area: aside; /* name of area */
}
main {
background-color: #92d97c;
grid-area: main; /* name of area */
}
nav {
grid-area: nav; /* name of area */
}
footer {
background-color: #f9f871;
grid-area: footer; /* name of area */
}
footer, nav {
min-height: 60px
}
a {
text-decoration: none;
color: black;
}Naming Tip: In the example above we've chosen to use the semantic HTML tag name as the grid template area name. However, you can name grid template areas just as you would any variable. We could have just as easily called these "section1", "section2", "section3" or more descriptively "featured-article", "trending-topics", or "advertisement".

Flexbox + Grid
Flexbox can be effectively used within CSS Grid cells to center items. While Grid arranges the overall layout, Flexbox excels in aligning and centering content inside Grid cells. This combination offers precise control, making layouts both flexible and visually balanced.
Let's make a stylistic change by creating a class that will center the text of our elements. Add this to your CSS file:
.flex-container {
display: flex;
align-items: center;
justify-content: center;
}Now add the class flex-container to the semantic HTML elements <aside>, <main>, & <footer>.

Ta-da! You now know two ways to structure a grid layout!
Responsive Grids
Media queries
The synergy between CSS Grid and media queries empowers developers to create responsive layouts that respond to changing screen sizes. By utilizing media queries, you can modify grid properties like grid-template-columns, grid-template-rows, and grid-gap to adjust the layout for different viewports.
Consider a two-column grid layout for desktop screens. To make this layout responsive, you can use media queries to transform it into a single-column layout for smaller devices.
.grid-container {
display: grid;
grid-template-columns: 200px 1fr;
grid-gap: 10px;
}
/* Media query for smaller screens */
@media (max-width: 500px) {
.grid-container {
grid-template-columns: 1fr;
}
}This code defines a two-column grid for larger screens. However, when the screen width is less than or equal to 500px, the media query overrides the default grid, converting it into a single-column layout.
CSS Grid: Practical Examples
There are a lot of very well known websites that use grid to achieve their desired layout. Some examples include:
- The New York Times: The New York Times website uses CSS Grid to create a multi-column layout for its articles and news sections.
- AirBnB: The Airbnb website employs CSS Grid to create a dynamic and responsive layout for its homepage.
- Mozilla Developer Network: The MDN web docs make extensive use of CSS Grid to organize and present documentation content.
Can you find other examples of popular sites that use grid?
AI-Assisted Layout Design
Learning objective: Employ AI to simulate alternative layout solutions and troubleshoot.
CSS Grid syntax can be verbose and hard to memorize. This is where AI excels. You can describe the geometry of what you want, and the AI will generate the grid definition.
Comparative Visualization
You can ask an LLM to provide two different approaches to the same problem.
Prompt Strategy:
"I need a gallery of image results for my Stable Diffusion clone. Option A: Use Flexbox. Option B: Use CSS Grid. Show me the code for both and explain which handles responsive resizing better without media queries."
Troubleshooting "Broken" Layouts
Layouts often break when content is dynamic (e.g., an AI generates a very long text response).
Debugging Workflow:
- Identify the issue: "The text is overflowing the card."
- Prompt: "My grid item expands past the viewport width when the text is long. Here is my CSS. How do I force the text to wrap or truncate using CSS Grid properties like
minmax?"
5. Lab: Building a Multi-Section Layout
Learning objective: Create a homepage layout using Flexbox and Grid.
Scenario: You are building the landing page for "NeuroNet," a new AI model serving platform.
Step 1: The Navbar (Flexbox)
- Create a header with a Logo on the left and Navigation Links on the right.
- Task: Use
display: flexandjustify-content: space-between.
Step 2: The Hero Section (Flexbox Centering)
- Create a large banner area with a title and a "Get Started" button.
- Task: Use Flexbox to align the content perfectly in the center (horizontally and vertically) of the container.
Step 3: The Features Grid (CSS Grid)
- Create a section with 4 cards describing features (e.g., "Fast Inference", "Secure", "Scalable", "Python Native").
- Task: Use CSS Grid to create a 2x2 grid layout.
.features { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
Step 4: AI Challenge - Responsive Refinement
- Challenge: The 2x2 grid looks bad on mobile phones.
- AI Prompt: Ask your AI assistant: "How do I modify this CSS Grid code so that it automatically switches to a 1-column layout on screens smaller than 600px?"
- Implement the solution provided (likely using
@mediaqueries).
6. Wrap-Up and Reflection
Group Discussion:
- Why is
display: flexusually better for "micro-layouts" (like a button with an icon) compared to Grid? - How did the AI suggest handling the mobile breakdown? Did it suggest Media Queries or
auto-fit? - What was the most difficult part of shifting your mental model from Python logic to CSS geometry?