CSS » Grid system

In­spired by Boot­strap, the grid sys­tem is the heart of a re­spons­ive web­site lay­out. The m-grid.css file con­tains all the setup you need for it, it’s com­pletely stan­dalone. Be­sides that, in or­der to have devices re­cog­nize your web­site prop­erly as re­spons­ive and not zoom it out all the way to an un­read­able mess, don’t for­get to add this to your <head>:

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

Over­view

If you have nev­er heard of it, it all boils down to a few break­points that define how the web­site is wide on vari­ous screen sizes. For every one of them you can define how your page and con­tent lay­out will look like. In every case you have 12 columns and it’s com­pletely up to you how you use them. Let’s start with an ex­ample.

<div class="m-container">
  <div class="m-row">
    <div class="m-col-t-6">.m-col-t-6</div>
    <div class="m-col-t-6">.m-col-t-6</div>
  </div>
  <div class="m-row">
    <div class="m-col-s-4 m-col-m-6">.m-col-s-4 .m-col-m-6</div>
    <div class="m-col-s-4 m-col-m-3">.m-col-s-4 .m-col-m-3</div>
    <div class="m-col-s-4 m-col-m-3">.m-col-s-4 .m-col-m-3</div>
  </div>
  <div class="m-row">
    <div class="m-col-l-7"><div class="m-frame m-center">.m-col-l-7</div></div>
    <div class="m-col-l-5"><div class="m-frame m-center">.m-col-l-5</div></div>
  </div>
</div>
.m-col-t-6
.m-col-t-6
.m-col-s-4 .m-col-m-6
.m-col-s-4 .m-col-m-3
.m-col-s-4 .m-col-m-3
.m-col-l-7
.m-col-l-5

In the above code, the out­er <div class="m-container"> is tak­ing care of lim­it­ing the web­site lay­out width. On very nar­row devices, the whole screen width is used, on wider screens fixed sizes are used in or­der to make the con­tent lay­out­ing man­age­able. The .m-container usu­ally has .m-row items dir­ectly in­side, but that’s not a re­quire­ment — you can put any­thing there, if you just want to have some pre­dict­able width lim­it­a­tion to your con­tent.

The <div class="m-row"> de­notes a row. The row is little more than a de­lim­iter for columns — it just makes sure that two neigh­bor­ing rows don’t in­ter­act with each oth­er in a bad way.

The ac­tu­al ma­gic is done by the row ele­ments de­noted by .m-col-B-N. The B is one of four break­points — t for tiny, s for small, m for me­di­um and l for large — based on screen width. The N is num­ber of columns that giv­en ele­ment will span. So, look­ing at the code above, .m-col-m-3 will span three columns out of twelve on me­di­um-sized screen.

This set­ting is in­her­ited up­wards — if you spe­cify a column span for a smal­ler screen width, it will get ap­plied on lar­ger width as well, un­less you over­ride it with a set­ting for lar­ger screen width. On the oth­er hand, if giv­en screen width has no column width spe­cified, the ele­ment will span the whole row. So, again from above, the .m-col-s-4 .m-col-m-6 ele­ment will span the whole row on tiny screen sizes, four columns on small screen sizes and six columns on me­di­um and large screen sizes.

De­tailed grid prop­er­ties

Break­point Screen width range (in­clus­ive) .m-container width Classes ap­plied, ordered by pri­or­ity
t, “tiny”, por­trait phones less than 576px full screen width .m-col-t-*
s, “small”, land­scape phones 576px - 767px 560px .m-col-s-*, .m-col-t-*
m, “me­di­um”, tab­lets, small desktops 768px - 991px 750px .m-col-m-*, .m-col-s-*, .m-col-t-*
l, “large”, desktops, very large tab­lets 992px and up 960px .m-col-l-*, .m-col-m-*, .m-col-s-*, .m-col-t-*

Wrap­ping around

Be­sides the above “all or noth­ing” scen­ario, where all the ele­ments either form a single row or are laid out one after an­oth­er in sep­ar­ate rows, it’s pos­sible to wrap the items around so they for ex­ample take four columns in a large screen width and two rows of two columns in a small screen width. In such case it’s im­port­ant to ac­count for ele­ments with dif­fer­ent heights us­ing a .m-clearfix-* for giv­en break­point:

<div class="m-container">
  <div class="m-row">
    <div class="m-col-s-6 m-col-m-3">.m-col-s-6 .m-col-m-3<br/>...<br/>...</div>
    <div class="m-col-s-6 m-col-m-3">.m-col-s-6 .m-col-m-3</div>
    <div class="m-clearfix-s"></div>
    <div class="m-col-s-6 m-col-m-3">.m-col-s-6 .m-col-m-3<br/>...</div>
    <div class="m-col-s-6 m-col-m-3">.m-col-s-6 .m-col-m-3<br/>...</div>
  </div>
</div>
.m-col-s-6 .m-col-m-3
...
...
.m-col-s-6 .m-col-m-3
.m-col-s-6 .m-col-m-3
...
.m-col-s-6 .m-col-m-3
...

Push­ing and pulling

It’s pos­sible to push and pull the ele­ments around us­ing .m-push-* and .m-pull-* and even use this func­tion­al­ity to ho­ri­zont­ally re­order con­tent based on screen width. Learn by ex­ample:

<div class="m-container">
  <div class="m-row">
    <div class="m-col-l-6 m-push-l-3">.m-col-l-6 .m-push-l-3</div>
  </div>
  <div class="m-row">
    <div class="m-col-s-8 m-push-s-4">.m-col-s-8 .m-push-s-4<br/>first</div>
    <div class="m-col-s-4 m-pull-s-8">.m-col-s-4 .m-pull-s-8<br/>second</div>
  </div>
</div>
.m-col-l-6 .m-push-l-3
.m-col-s-8 .m-push-s-4
first
.m-col-s-4 .m-pull-s-8
second

Float­ing around

It’s also pos­sible to re­spons­ively float or align the ele­ments around us­ing .m-left-*, .m-right-* and .m-center-* if you put the .m-col-* ele­ments dir­ectly in­to text flow without wrap­ping them in a .m-row ele­ment. The fol­low­ing ex­ample will float the con­tents to the right on me­di­um-size screens, cen­ter them on small and put them full-width on tiny screens.

Per­haps even more im­port­ant than in the wrap­ping case men­tioned above is adding a .m-clearfix-* ele­ment after, to avoid the float­ing ele­ment cut­ting in­to un­re­lated con­tent that fol­lows.

<div class="m-col-s-6 m-center-s m-col-m-4 m-right-m">
  .m-col-s-6 .m-center-s .m-col-m-4 .m-right-m
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
<div class="m-clearfix-m"></div>
.m-col-s-6 .m-center-s .m-col-m-4 .m-right-m

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Left-aligned float­ing blocks ad­di­tion­ally have 1rem pad­ding on the right and right-aligned blocks on the left. All of them have im­pli­citly pad­ding on bot­tom, ex­cept if the ele­ment is a last child. Add a .m-nopadb class to them to dis­able bot­tom pad­ding, if you want to pre­serve it even for a last child, add an empty <div></div> ele­ment after.

Grid pad­ding

The .m-container ele­ment pads its con­tents from left and right by 1rem; the .m-row adds a neg­at­ive -1rem mar­gin on left and right to re­set it. Fi­nally, the .m-col-* ele­ments have 1rem pad­ding on all sides to sep­ar­ate the con­tents. It’s pos­sible to over­ride this on the .m-container and/or on .m-col-* ele­ments us­ing .m-nopad, .m-nopadx, m-nopady, .m-nopadt, .m-nopadb, .m-nopadl, .m-nopadr which re­move all, just ho­ri­zont­al or ver­tic­al pad­ding, or pad­ding on the top/bot­tom/left/right, re­spect­ively.

Grid nest­ing

It’s pos­sible to nest the grid. Just place a .m-row ele­ment in­side an .m-col-* (it doesn’t need to be a dir­ect child) and put your .m-col-* ele­ments in­side. The in­ner grid will also have 12 columns, but smal­ler ones.

Re­mov­ing the grid on lar­ger screen sizes

The usu­al be­ha­vi­or is to add the grid for lar­ger screen sizes, but some­times you might want to do the op­pos­ite. It’s pos­sible to do that just by spe­cify­ing .m-col-*-12 for giv­en break­point, but some­times the CSS float prop­erty might cause prob­lems. The .m-col-*-none classes com­pletely re­move all grid-re­lated CSS styl­ing for giv­en screen size and up so the ele­ment be­haves like in its ini­tial state.

<div class="m-container">
  <div class="m-row">
    <div class="m-col-s-8 m-col-l-none">.m-col-s-8 .m-col-l-none</div>
    <div class="m-col-s-4 m-col-l-none">.m-col-s-4 .m-col-l-none</div>
  </div>
</div>
.m-col-s-8 .m-col-l-none
.m-col-s-4 .m-col-l-none

Hid­ing ele­ments based on screen size

The .m-show-* and .m-hide-* classes hide or show the ele­ment on giv­en screen size and up. Use­ful for ex­ample to show a dif­fer­ent kind of nav­ig­a­tion on dif­fer­ent devices.

<div class="m-show-m">.m-show-m<br/>shown on M and up</div>
<div class="m-hide-l">.m-hide-l<br/>hidden on L and up</div>
.m-show-m
shown on M and up
.m-hide-l
hidden on L and up

In­flat­able nes­ted grid

It’s usu­al that the con­tent area of the page doesn’t span the full 12-column width in or­der to avoid long un­read­able lines. But some­times one might want to use the full avail­able width — for ex­ample to show big pic­tures or to fit many things next to each oth­er.

If you have a ten-column con­tent area with one column space on each side, mark your .m-container ele­ment with .m-container-inflatable and then put your nes­ted con­tent in ele­ments marked with .m-container-inflate.

<div class="m-container m-container-inflatable">
  <div class="m-row">
    <div class="m-col-l-10 m-push-l-1">
      <div class="m-container-inflate">.m-container-inflate</div>
    </div>
  </div>
</div>
.m-container-inflate

The .m-container-inflate block has im­pli­citly a 1rem pad­ding after (but not on oth­er sides and also not if it’s the last child). Add a .m-nopadb class to it to dis­able that, if you want to pre­serve the pad­ding even for a last child, add an empty <div></div> ele­ment after.

It’s also pos­sible to tuck float­ing con­tent out of the page flow by com­bin­ing .m-left-* with .m-container-inflate:

<div class="m-container m-container-inflatable">
  <div class="m-row">
    <div class="m-col-l-10 m-push-l-1">
      <div class="m-container-inflate m-col-l-6 m-right-l">
        .m-container-inflate .m-col-l-6 .m-right-l
      </div>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id
      elit posuere, consectetur magna congue, sagittis est. Pellentesque
      est neque, aliquet nec consectetur in, mattis ac diam.</p>
    </div>
  </div>
</div>
.m-container-inflate .m-col-l-6 m-right-l

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id elit posuere, consectetur magna congue, sagittis est. Pellentesque est neque, aliquet nec consectetur in, mattis ac diam.

De­bug CSS

It’s some­times hard to see why the lay­out isn’t work­ing as ex­pec­ted. In­clud­ing the m-de­bug.css file will high­light the most usu­al mis­takes — such as .m-row not dir­ectly con­tain­ing .m-col-* or two .m-containers nes­ted to­geth­er — with bright red back­ground for you to spot the prob­lems bet­ter:

<link rel="stylesheet" href="m-dark.css" />

Oth­er than high­light­ing prob­lems, this file doesn’t al­ter your web­site ap­pear­ance in any way. To save un­ne­ces­sary re­quests and band­width, I re­com­mend that you re­move the ref­er­ence again when pub­lish­ing the web­site.