Lesson 04: CSS Layout

Learning Outcomes

After this lesson, you will understand how CSS controls the positioning and layout of elements on a web page. You will be able to use the box model to control spacing and sizing, understand display properties and how they affect layout, and create multi-column layouts using flexbox. You will also understand when to use different layout techniques and how these methods work together to create page structures.

Prerequisites

You should be comfortable with basic CSS properties like color, font-size, margin, and padding from Lesson 03. Understanding how CSS selectors work and how to link external stylesheets is also necessary.

The CSS Box Model

Every HTML element on a web page is represented as a rectangular box. Understanding this box model is fundamental to controlling layout because it explains how spacing, borders, and sizing work together.

The box model consists of four layers, each building outward from the center:

  1. Content - The innermost layer
  2. Padding - Space inside the element
  3. Border - Visible edge around padding
  4. Margin - Space outside the element

Understanding Each Layer

At the center is the content area, which contains the actual text, images, or other content of the element. The width and height properties you set in CSS apply to this content area by default.

Surrounding the content is padding, which creates space inside the element between the content and the border. Padding:

Next comes the border, which is a visible line around the element if you choose to add one. Borders are optional but useful for:

Finally, margin creates space outside the element, separating it from other elements. Margin is:

Visual Box Model Breakdown

Here's how to visualize the box model layers from inside to outside:

Content Area

This is the innermost layer containing your text, images, etc.

Padding (blue area) - space inside the element

Border (blue line) - visible edge around padding

Margin (transparent space outside) - separates this element from others

Think of it like a picture frame: the content is the picture, padding is the matting, the border is the frame edge, and margin is the wall space around the frame.

Total Element Size Calculation

When you set an element's width to 300px, by default that means the content area is 300 pixels wide. But the total space the element actually takes up on the page includes:

Example calculation:

This can lead to elements being larger than expected if you don't account for padding and borders. That's why box-sizing: border-box is so useful!

Box-Sizing: content-box vs border-box

CSS provides the box-sizing property to control how width and height are calculated. Understanding the difference is crucial:

content-box (default): Width and height apply only to the content area. Padding and border add to the total size.

.example-content-box { width: 300px; padding: 20px; border: 2px solid black; box-sizing: content-box; /* This is the default */ } /* Total width = 300px (content) + 40px (padding) + 4px (border) = 344px */

border-box (recommended): Width and height include padding and border. The content area automatically adjusts.

.example-border-box { width: 300px; padding: 20px; border: 2px solid black; box-sizing: border-box; /* Recommended for easier calculations */ } /* Total width = 300px (includes padding and border) Content area = 300px - 40px (padding) - 4px (border) = 256px */

Best Practice: Many developers set box-sizing: border-box; on all elements using the universal selector (* { box-sizing: border-box; }). This makes width calculations much more predictable and is what this tutorial uses.

Common Box Model Pitfalls

Margin Collapse: Vertical margins between adjacent elements collapse into a single margin equal to the larger of the two margins. This only happens with vertical (top/bottom) margins, not horizontal margins.

/* If element A has margin-bottom: 30px */ /* and element B has margin-top: 20px */ /* The space between them is 30px (not 50px!) */ .element-a { margin-bottom: 30px; } .element-b { margin-top: 20px; /* Only the larger margin (30px) applies */ }

Solution: If you need exact spacing, use padding instead of margin, or use flexbox/grid which don't have margin collapse.

Forgetting Box-Sizing: When using content-box, elements become larger than expected. Always account for padding and borders, or use border-box.

Inline Element Margins: Vertical margins (top/bottom) on inline elements don't work as expected. Use inline-block or padding if you need vertical spacing.

Understanding the box model matters because spacing issues are one of the most common problems beginners encounter. When elements don't appear where you expect or aren't the size you intended, it's usually related to how margin, padding, and borders interact with the element's dimensions. Learning to visualize elements as boxes with these layers helps you predict and control spacing effectively.

Understanding Display Properties

The display property is one of the most important CSS properties for controlling layout because it determines how an element behaves in relation to other elements. Different display values fundamentally change how elements flow and interact on the page.

Block-Level Elements

Block-level elements have display: block; by default for elements like div, p, and h1.

Characteristics of block elements:

Use block elements for:

div { display: block; /* Default for div elements */ width: 100%; /* Takes full width */ margin: 1rem 0; /* Vertical spacing works */ }

Inline Elements

Inline elements have display: inline; by default for elements like span, a, and strong.

Characteristics of inline elements:

Use inline elements for:

span { display: inline; /* Default for span elements */ /* width and height don't work! */ /* vertical margins don't create space */ }

Inline-Block Elements

Inline-block elements combine characteristics of both block and inline elements.

Characteristics of inline-block elements:

Use inline-block for:

.nav-item { display: inline-block; /* Horizontal but with size control */ width: 150px; height: 50px; margin: 1rem; /* Vertical margins work! */ }

Choosing the Right Display Value

Understanding display properties helps you choose the right approach for your layout needs. Most layout work involves:

Creating Layouts with Flexbox

Flexbox, short for Flexible Box Layout, is a CSS layout method designed to help you create flexible, responsive layouts with less code than older methods. Flexbox excels at distributing space and aligning items within containers, making it ideal for navigation bars, card layouts, and centering content.

To use flexbox, you set display: flex; on a container element. This container becomes a flex container, and its direct children become flex items. The flex container automatically arranges its children, and you control the arrangement using flex properties. By default, flex items arrange horizontally in a row, but you can change this to arrange vertically or reverse the order.

The flex-direction property controls which direction flex items are arranged. The default value is row, which arranges items horizontally from left to right. Setting it to column arranges items vertically from top to bottom. You can also reverse either direction using row-reverse or column-reverse.

The justify-content property controls how flex items are distributed along the main axis (the direction they're arranged). Setting justify-content: center; centers items, space-between places equal space between items with no space at the edges, space-around places equal space around each item, and space-evenly distributes space evenly including at the edges. This property is powerful for creating balanced layouts without manually calculating margins.

The align-items property controls how items align along the cross axis (perpendicular to the main direction). Setting align-items: center; centers items vertically when flex-direction is row, or horizontally when it's column. Other values include flex-start to align to the beginning, flex-end to align to the end, and stretch to fill the container.

Flex items can also have a flex property that controls how they grow or shrink to fill available space. Setting flex: 1; on an item makes it grow to fill available space. If multiple items have flex: 1, they share the space equally. You can also use specific values like flex: 2; to make an item take twice as much space as items with flex: 1. This creates responsive layouts where elements adjust automatically to container size.

Flexbox solves many common layout problems with simple properties. Centering content both horizontally and vertically, which previously required complex techniques, becomes straightforward with flexbox. Creating equal-height columns, flexible navigation bars, and responsive card grids all become much simpler when you understand flexbox fundamentals.

Understanding Flex Container vs Flex Items

It's crucial to understand which properties apply to the container and which apply to items:

Flex Container (parent element with display: flex):

  • flex-direction - controls row vs column direction
  • justify-content - controls spacing along main axis
  • align-items - controls alignment along cross axis
  • gap - space between items
  • flex-wrap - whether items wrap to new line

Flex Items (direct children of flex container):

  • flex - how item grows/shrinks (e.g., flex: 1)
  • align-self - overrides container's align-items for this item
  • order - changes visual order without changing HTML

Key Point: When you set display: flex on a container, only its direct children become flex items. Nested children are NOT flex items unless you also set display: flex on their parent.

Flexbox Direction: Row vs Column Comparison

Understanding flex-direction is essential. Here's how it changes the layout:

Row (default) - Horizontal Layout:

.container { display: flex; flex-direction: row; /* Items arranged left to right */ justify-content: space-between; } /* Main axis = horizontal, Cross axis = vertical */ /* justify-content controls horizontal spacing */ /* align-items controls vertical alignment */

Use for: navigation bars, horizontal card layouts, side-by-side content

Column - Vertical Layout:

.container { display: flex; flex-direction: column; /* Items arranged top to bottom */ align-items: center; } /* Main axis = vertical, Cross axis = horizontal */ /* justify-content controls vertical spacing */ /* align-items controls horizontal alignment */

Use for: stacked content, vertical navigation, mobile layouts

Common Flexbox Mistakes and Solutions

Mistake 1: Forgetting display: flex

If flexbox properties aren't working, you probably forgot to set display: flex on the container.

/* WRONG - flexbox properties won't work without display: flex */ .container { justify-content: center; /* Does nothing! */ } /* CORRECT - always start with display: flex */ .container { display: flex; /* Required first step */ justify-content: center; /* Now this works */ }

Mistake 2: Confusing justify-content and align-items

Remember: justify-content works along the main axis (the flex-direction), while align-items works along the cross axis.

  • If flex-direction: row (default): justify-content = horizontal, align-items = vertical
  • If flex-direction: column: justify-content = vertical, align-items = horizontal

Mistake 3: Items not growing/shrinking

If items don't fill space or don't shrink, set the flex property on items:

/* Items will grow to fill available space equally */ .item { flex: 1; } /* Or control individually */ .item-large { flex: 2; /* Takes twice the space of items with flex: 1 */ } .item-small { flex: 0.5; /* Takes half the space */ }

Mistake 4: Using flexbox for everything

Flexbox is great, but it's not always the right tool. Use flexbox for one-dimensional layouts (row OR column). For two-dimensional layouts (rows AND columns), consider CSS Grid instead.

Worked Example: Creating a Navigation Bar with Flexbox

Building a navigation bar demonstrates how flexbox creates flexible, aligned layouts with minimal code. We'll create a horizontal navigation bar with evenly spaced links that automatically adjust to different screen sizes.

Start with HTML structure. Create a nav element containing an unordered list with several list items, each containing a link. The semantic HTML provides the content structure, and we'll use CSS to arrange it visually using flexbox.

In your CSS file, target the nav element and set display: flex;. This makes the nav a flex container. Next, set justify-content: space-between; to distribute the navigation items evenly across the width of the container. This automatically handles spacing without needing to calculate individual margins.

You'll likely want to remove the default list styling. Target the ul element inside nav and set list-style: none; to remove bullets, and padding: 0; and margin: 0; to remove default spacing. Then set the ul to display: flex; as well, which arranges the list items horizontally.

Style the links within the navigation. You might want to remove underlines, set colors, add padding for clickable areas, and perhaps change the appearance on hover. The flexbox layout ensures all navigation items align nicely regardless of their text length.

nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; background-color: #333; } nav ul { display: flex; list-style: none; padding: 0; margin: 0; gap: 2rem; } nav a { color: white; text-decoration: none; padding: 0.5rem 1rem; } nav a:hover { background-color: #555; border-radius: 4px; }

The flexbox properties handle the horizontal arrangement and spacing automatically. If you add or remove navigation items, they'll redistribute evenly. The gap property (if your browser supports it) or manual margins on list items provide consistent spacing between items. This approach is much simpler than older layout methods that required floating elements and clearing floats.

Positioning Elements

The position property provides another method for controlling where elements appear on the page. While flexbox handles flow and distribution of elements, positioning handles precise placement or taking elements out of normal document flow.

Static positioning is the default, where elements flow normally in the document order. Elements with position: static; aren't affected by top, right, bottom, or left properties.

Relative positioning keeps the element in normal flow but allows you to offset it using top, right, bottom, or left properties. The element still occupies its original space in the layout, but appears moved. This is useful for fine-tuning element positions without affecting other elements.

Absolute positioning removes the element from normal document flow entirely. The element is positioned relative to its nearest positioned ancestor (an ancestor with position other than static), or relative to the document if no positioned ancestor exists. Other elements behave as if the absolutely positioned element doesn't exist. This is useful for overlays, dropdown menus, or precisely positioned elements.

Fixed positioning is similar to absolute but positions relative to the viewport instead of a parent element. Fixed elements stay in the same position even when the page scrolls, making them ideal for navigation bars that should always be visible or sticky headers.

Positioning is powerful but should be used thoughtfully. Removing elements from normal flow with absolute or fixed positioning can make layouts fragile and harder to maintain. Flexbox often provides better solutions for most layout needs, with positioning reserved for specific cases like overlays or sticky elements.

CSS Grid vs Flexbox: When to Use Each

Both CSS Grid and Flexbox are powerful layout tools, but they excel at different tasks. Understanding when to use each helps you choose the right tool for your layout needs.

Flexbox: One-Dimensional Layouts

Flexbox is ideal when you need to arrange items in a single direction - either horizontally (row) or vertically (column).

Best for:

  • Navigation bars (horizontal or vertical)
  • Centering content (both horizontally and vertically)
  • Distributing space between items
  • Creating equal-height columns
  • Aligning items within a container
/* Flexbox example: horizontal navigation */ nav { display: flex; justify-content: space-between; /* Space items evenly */ align-items: center; /* Center vertically */ }

CSS Grid: Two-Dimensional Layouts

CSS Grid is ideal when you need to arrange items in both rows and columns simultaneously. Grid creates a two-dimensional layout system.

Best for:

  • Page layouts with multiple sections (header, sidebar, main, footer)
  • Card grids that need to align in rows and columns
  • Complex layouts requiring precise control over both dimensions
  • Overlapping elements
/* Grid example: page layout */ .page { display: grid; grid-template-columns: 200px 1fr; /* Sidebar | Main */ grid-template-rows: auto 1fr auto; /* Header | Content | Footer */ grid-template-areas: "header header" "sidebar main" "footer footer"; }

Combining Grid and Flexbox

You can and should use both! Grid for the overall page structure, flexbox for components within grid areas.

/* Grid creates the page structure */ .container { display: grid; grid-template-columns: 1fr 1fr 1fr; /* Three columns */ gap: 2rem; } /* Flexbox arranges content within each grid cell */ .card { display: flex; flex-direction: column; justify-content: space-between; /* Space content vertically */ }

Visual Grid Example: Understanding Grid Lines and Tracks

CSS Grid creates a network of horizontal and vertical lines called grid lines. The spaces between lines are called tracks (rows or columns).

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6

This grid has 3 columns (created by 4 vertical grid lines) and 2 rows (created by 3 horizontal grid lines). Each dashed border represents a grid line.

/* This creates the grid above */ .grid-container { display: grid; grid-template-columns: 1fr 1fr 1fr; /* 3 equal columns */ gap: 10px; /* Space between tracks */ } /* Grid lines are numbered starting from 1 */ /* You can place items using line numbers */ .item { grid-column: 1 / 3; /* Span from line 1 to line 3 (2 columns) */ grid-row: 1 / 2; /* Span from line 1 to line 2 (1 row) */ }

Responsive Grid Patterns

The repeat(auto-fit, minmax()) pattern creates responsive grids that automatically adjust:

/* Responsive grid: items minimum 250px, maximum flexible */ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 2rem; } /* How it works: - repeat() creates multiple columns - auto-fit fills available space - minmax(250px, 1fr) means: * Minimum: 250px per column * Maximum: 1fr (equal share of remaining space) - When screen is too narrow, items wrap to new row - This creates a responsive grid without media queries! */

When to use auto-fit vs auto-fill:

  • auto-fit: Collapses empty tracks, centers items when there's extra space
  • auto-fill: Keeps empty tracks, maintains fixed number of columns
  • Most of the time, auto-fit is what you want

Practice Opportunity

Create a simple page layout with a header, main content area, and footer. Use flexbox to create a navigation bar in the header with links that are evenly distributed. In the main content area, create a card layout with three cards arranged horizontally using flexbox. Make the cards equal height and ensure they wrap to a new row if the screen becomes too narrow. Style the footer to be centered at the bottom of the page.

Experiment with different flexbox properties. Try changing justify-content values to see how items redistribute. Adjust flex properties on individual cards to make some larger than others. Practice combining flexbox with other CSS properties like padding, margin, and borders to create visually appealing layouts.

Summary of Key Concepts

CSS layout involves understanding the box model, which explains how content, padding, border, and margin work together to determine an element's size and spacing. The display property controls how elements flow and interact, with block, inline, and inline-block being fundamental display types. Flexbox provides a powerful method for creating flexible, responsive layouts by distributing space and aligning items within containers.

Positioning offers precise control over element placement, but flexbox often provides better solutions for most layout needs. Understanding these layout methods gives you the tools to create complex page structures, from simple navigation bars to multi-column layouts that adapt to different screen sizes. The key is choosing the right method for each situation and understanding how different techniques work together.

Next Steps

Now that you understand CSS layout fundamentals, Lesson 05 covers responsive design. You'll learn how to make your layouts adapt to different screen sizes using media queries, ensuring your websites work well on phones, tablets, and desktop computers.

Bibliography

Mozilla Developer Network. "CSS Layout." MDN Web Docs. https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout

Mozilla Developer Network. "Flexbox." MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout

CSS-Tricks. "A Complete Guide to Flexbox." CSS-Tricks. https://css-tricks.com/snippets/css/a-guide-to-flexbox/

W3Schools. "CSS Layout." W3Schools. https://www.w3schools.com/css/css_positioning.asp