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 row must 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 l3 makes the classic four-across card grid. Overflowing columns wrap to the next line instead of squishing.
  • Always set s first. col s12 m6 means full-width on phones, half on everything bigger. A col with only l6 has undefined mobile behavior.

Breakpoint prefixes and column arithmetic

You writePhone (0px+)Tablet (600px+)Desktop (992px+)
col s12full widthfull widthfull width
col s12 m6full widthhalfhalf
col s12 m6 l3full widthhalfquarter
col s6halfhalfhalf
col s12 m8 offset-m2full widthcentered 8 colscentered 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

SymptomCauseFix
Columns stack full-width at every sizeMissing size prefix, e.g. class="col 6"Use col s6 — the number needs its prefix
No gap between columns / weird spacingCols not inside a rowWrap them in <div class="row">
Row appears emptyCol content has no height (e.g. floated images)Add content or a min-height; check for unclosed tags
Everything shifts on one breakpointColumns sum over 12 at that sizeRecount per prefix; each size is an independent 12-column budget
Container touches screen edgesMissing container wrapperWrap 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.