RWD Grid With Percentages

Building a grid with percentage widths instead of fixed pixels makes each column a flexible fraction of its container, so the whole layout scales smoothly as the browser resizes.

Why Use Percentages Instead of Pixels

A column set to width: 300px is always 300px, whether the browser window is 320px or 3200px wide. A column set to width: 33.33% is instead always one third of whatever its parent container happens to be, so it naturally grows and shrinks along with the page. Percentage-based grids were one of the very first techniques used for fluid layouts, well before media queries existed, and they're still the foundation that flexbox and CSS grid build on top of today.

Example

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  .grid {
    display: flex;
  }
  .col {
    width: 33.333%;
    padding: 16px;
    box-sizing: border-box;
    background: #eee;
  }
</style>
</head>
<body>

<div class="grid">
  <div class="col">A</div>
  <div class="col">B</div>
  <div class="col">C</div>
</div>

</body>
</html>

To turn any fixed-width design into percentages, use the simple formula: target width divided by context width, multiplied by 100. The 'target' is the width you want a single element to be, and the 'context' is the width of its direct parent. For example, if a designer's mockup shows a 300px sidebar inside a 900px content area, the percentage is 300 divided by 900 times 100, which is 33.33%. If that same sidebar sits inside a full 1200px page instead, the calculation and the resulting percentage would be different, because the percentage is always relative to the immediate parent, not the whole page.

Target widthContext widthPercentage
300px900px33.33%
600px900px66.66%
240px960px25%
480px960px50%

Percentage Widths and the Box Model

By default, CSS uses content-box sizing, meaning padding and border are added on top of a specified width rather than included inside it. This causes a serious problem with percentage grids: a column at width: 33.33% with 20px of padding on each side actually ends up wider than 33.33% of its parent, which breaks the layout and can force columns to wrap early or overflow. Setting box-sizing: border-box makes the width include padding and border, so a percentage width behaves exactly as expected.

Example

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
  box-sizing: border-box;
}

.grid {
  display: flex;
}
.col {
  width: 25%;
  padding: 20px;
  border: 1px solid #999;
}
</style>
</head>
<body>

</body>
</html>
Note: Without box-sizing: border-box, four columns each set to width: 25% with padding will not fit on one line, they'll be wider than 100% combined and the last one will wrap. Setting box-sizing globally with the * selector, as shown above, is a common and recommended reset.
  • 50% + 50% for a simple two-column halves layout
  • 33.33% x 3 for equal thirds
  • 25% x 4 for equal quarters
  • 70% / 30% for an asymmetric main content / sidebar split
Note: When you need consistent spacing between percentage columns without breaking the math, use CSS calc() to subtract a fixed gap from a percentage width, rather than adding extra margin that pushes the total past 100%.

Example

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.col {
  width: calc(33.333% - 16px);
  margin-right: 16px;
}
.col:last-child {
  margin-right: 0;
}
</style>
</head>
<body>

</body>
</html>

Exercise: RWD Grid View

In a fluid grid system, how are column widths usually defined?