
Quick answer: The Materialize CSS grid is a 12-column flexbox system. You wrap content in <div class="row">, place items in <div class="col s12 m6 l3"> children, and the number after each size prefix is how many of the 12 columns that item spans at that breakpoint. Offsets shift items right with offset-s2-style classes, and nesting works by putting a new row inside any col. That is 80% of the system — the details below are the other 20%.
The three container rules everything depends on
- A
rowmust wrap your columns. Cols placed without a row parent lose their flex layout and spacing — the #1 beginner bug, and it looks like “the grid is broken.” - Columns must add up to 12 per row. 6 + 6 makes halves; 4 + 4 + 4 makes thirds; 3 × 4 columns of
s12 m6 l3makes the classic four-across card grid. Overflowing columns wrap to the next line instead of squishing. - Always set
sfirst.col s12 m6means full-width on phones, half on everything bigger. A col with onlyl6has undefined mobile behavior.
Breakpoint prefixes and column arithmetic
| You write | Phone (0px+) | Tablet (600px+) | Desktop (992px+) |
|---|---|---|---|
col s12 | full width | full width | full width |
col s12 m6 | full width | half | half |
col s12 m6 l3 | full width | half | quarter |
col s6 | half | half | half |
col s12 m8 offset-m2 | full width | centered 8 cols | centered 8 cols |
Every larger prefix inherits from the smaller one — that is why s12 m6 l3 is the complete responsive recipe in one class string. For the full mental model of where the grid sits in the framework, start with the Materialize CSS tutorial, then come back here.
Offsets, centering, and fixed widths
Three copy-paste recipes cover most layout requests:
<!-- 1. A centered narrow column (login box) -->
<div class="row">
<div class="col s12 m8 offset-m2 l6 offset-l3">
<!-- form here -->
</div>
</div>
<!-- 2. Gaps between columns: offset shifts everything after it -->
<div class="row">
<div class="col s5">Left</div>
<div class="col s5 offset-s2">Right, pushed right by 2 empty cols</div>
</div>
<!-- 3. Push/pull: reorder visually without changing source order -->
<div class="row">
<div class="col s12 m7 push-m5">Visually right on tablet+</div>
<div class="col s12 m5 pull-m7">Visually left on tablet+</div>
</div>Use push/pull when source order matters (the sidebar content should come first on mobile) but the sidebar should sit on the left on desktop. Offset is for centering; push/pull is for reordering.
Nesting rows inside columns
Any col can contain a new row, which restarts the 12-column count inside it:
<div class="row">
<div class="col s12 m8">
Main article
<div class="row">
<div class="col s6">Inner half</div>
<div class="col s6">Inner half</div>
</div>
</div>
<div class="col s12 m4">Sidebar</div>
</div>The inner row’s “full width” is the width of its parent column, not the page. This is how you build card grids inside a layout column, or media-object layouts, without fighting the outer grid.
Common grid bugs and their fixes
| Symptom | Cause | Fix |
|---|---|---|
| Columns stack full-width at every size | Missing size prefix, e.g. class="col 6" | Use col s6 — the number needs its prefix |
| No gap between columns / weird spacing | Cols not inside a row | Wrap them in <div class="row"> |
| Row appears empty | Col content has no height (e.g. floated images) | Add content or a min-height; check for unclosed tags |
| Everything shifts on one breakpoint | Columns sum over 12 at that size | Recount per prefix; each size is an independent 12-column budget |
| Container touches screen edges | Missing container wrapper | Wrap the page in <div class="container"> |
One habit prevents most of these: build mobile-first. Write s classes until the phone layout is right, then add m and l. Debugging a broken desktop layout is far easier when the mobile layout already works.
If you want an instructor to review your layout code and correct these habits in real time, Ampersand Academy teaches front-end development one-to-one, from grid fundamentals to complete responsive sites.
Frequently asked questions
How many columns does the Materialize grid have?
Twelve per row at every breakpoint. Each size prefix (s, m, l, xl) is an independent 12-column budget, so a row of four s12 m6 l3 columns is four stacked on mobile, two on tablet and four across on desktop.
What is the difference between offset and push/pull in Materialize?
Offset-m2 adds 2 empty columns of space before the element, pushing it and everything after it right. Push-m5 and pull-m7 visually swap element positions without changing their order in the HTML source.
Why are my Materialize columns not side by side?
Almost always one of two causes: the columns are missing their size prefix (col 6 instead of col s6) or the columns are not wrapped in a div with class row. The row provides the flex context columns need.
Can I nest rows inside columns in Materialize?
Yes. Place a new div with class row inside any col, and the 12-column system restarts within that column’s width. This is the standard way to build card grids or split layouts inside a layout area.
How do I center a column in Materialize?
Use an offset that leaves equal space: a 6-column box centers with col s12 m8 offset-m2 (2 empty on each side) or col s12 l6 offset-l3 (3 empty on each side). The container class centers the whole page, not individual columns.
