Grid system
Inspired by Bootstrap, the grid system is the
heart of a responsive website layout. The m-grid.css
file contains all the setup you need for it, it’s completely standalone.
Besides that, in order to have devices recognize your website properly as
responsive and not zoom it out all the way to an unreadable mess, don’t forget
to add this to your <head>
:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
Overview
If you have never heard of it, it all boils down to a few breakpoints that define how the website is wide on various screen sizes. For every one of them you can define how your page and content layout will look like. In every case you have 12 columns and it’s completely up to you how you use them. Let’s start with an example.
<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>
In the above code, the outer <div class="m-container">
is taking care
of limiting the website layout width. On very narrow devices, the whole screen
width is used, on wider screens fixed sizes are used in order to make the
content layouting manageable. The .m-container
usually has .m-row
items directly inside, but that’s not a requirement — you can put anything
there, if you just want to have some predictable width limitation to your
content.
The <div class="m-row">
denotes a row. The row is little more than
a delimiter for columns — it just makes sure that two neighboring rows don’t
interact with each other in a bad way.
The actual magic is done by the row elements denoted by .m-col-B-N
. The
B
is one of four breakpoints — t
for tiny, s
for small, m
for
medium and l
for large — based on screen width. The N
is number of
columns that given element will span. So, looking at the code above,
.m-col-m-3
will span three columns out of twelve on medium-sized screen.
This setting is inherited upwards — if you specify a column span for a
smaller screen width, it will get applied on larger width as well, unless you
override it with a setting for larger screen width. On the other hand, if given
screen width has no column width specified, the element will span the whole
row. So, again from above, the .m-col-s-4 .m-col-m-6
element will span
the whole row on tiny screen sizes, four columns on small screen sizes and six
columns on medium and large screen sizes.
Detailed grid properties
Breakpoint | Screen width range (inclusive) | .m-container width |
Classes applied, ordered by priority |
---|---|---|---|
t , “tiny”,
portrait phones |
less than 576px | full screen width | .m-col-t-* |
s , “small”,
landscape phones |
576px - 767px | 560px | .m-col-s-* ,
.m-col-t-* |
m , “medium”,
tablets, small
desktops |
768px - 991px | 750px | .m-col-m-* ,
.m-col-s-* ,
.m-col-t-* |
l , “large”,
desktops, very
large tablets |
992px and up | 960px | .m-col-l-* ,
.m-col-m-* ,
.m-col-s-* ,
.m-col-t-* |
Wrapping around
Besides the above “all or nothing” scenario, where all the elements either form
a single row or are laid out one after another in separate rows, it’s possible
to wrap the items around so they for example take four columns in a large
screen width and two rows of two columns in a small screen width. In such case
it’s important to account for elements with different heights using a
.m-clearfix-*
for given breakpoint:
<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>
...
...
...
...
Pushing and pulling
It’s possible to push and pull the elements around using .m-push-*
and
.m-pull-*
and even use this functionality to horizontally reorder
content based on screen width. Learn by example:
<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>
first
second
Floating around
It’s also possible to responsively float or align the elements around using
.m-left-*
, .m-right-*
and .m-center-*
if you put the
.m-col-*
elements directly into text flow without wrapping them in a
.m-row
element. The following example will float the contents to the
right on medium-size screens, center them on small and put them full-width
on tiny screens.
Perhaps even more important than in the wrapping case mentioned above
is adding a .m-clearfix-*
element after, to avoid the floating element
cutting into unrelated content that follows.
<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>
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 floating blocks additionally have 1rem
padding on the right
and right-aligned blocks on the left. All of them have implicitly padding on bottom, except if the element is a last child. Add a .m-nopadb
class to
them to disable bottom padding, if you want to preserve it even for a last
child, add an empty <div></div>
element after.
Grid padding
The .m-container
element pads its contents from left and right by
1rem
; the .m-row
adds a negative -1rem
margin on left and
right to reset it. Finally, the .m-col-*
elements have 1rem
padding on all sides to separate the contents. It’s possible to override this
on the .m-container
and/or on .m-col-*
elements using
.m-nopad
, .m-nopadx
, m-nopady
, .m-nopadt
,
.m-nopadb
, .m-nopadl
, .m-nopadr
which remove all, just
horizontal or vertical padding, or padding on the top/bottom/left/right,
respectively.
Grid nesting
It’s possible to nest the grid. Just place a .m-row
element inside an
.m-col-*
(it doesn’t need to be a direct child) and put your
.m-col-*
elements inside. The inner grid will also have 12 columns, but
smaller ones.
Removing the grid on larger screen sizes
The usual behavior is to add the grid for larger screen sizes, but sometimes
you might want to do the opposite. It’s possible to do that just by specifying
.m-col-*-12
for given breakpoint, but sometimes the CSS float
property might cause problems. The .m-col-*-none
classes completely
remove all grid-related CSS styling for given screen size and up so the element
behaves like in its initial 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>
Hiding elements based on screen size
The .m-show-*
and .m-hide-*
classes hide or show the element on
given screen size and up. Useful for example to show a different kind of
navigation on different 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>
shown on M and up
Inflatable nested grid
It’s usual that the content area of the page doesn’t span the full 12-column width in order to avoid long unreadable lines. But sometimes one might want to use the full available width — for example to show big pictures or to fit many things next to each other.
If you have a ten-column content area with one column space on each side, mark
your .m-container
element with .m-container-inflatable
and then
put your nested content in elements 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>
The .m-container-inflate
block has implicitly a 1rem
padding
after (but not on other sides and also not if it’s the last child). Add a
.m-nopadb
class to it to disable that, if you want to preserve the
padding even for a last child, add an empty <div></div>
element after.
It’s also possible to tuck floating content out of the page flow by combining
.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>
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.
Debug CSS
It’s sometimes hard to see why the layout isn’t working as expected. Including
the m-debug.css file will highlight the most usual
mistakes — such as .m-row
not directly containing .m-col-*
or
two .m-container
s nested together — with bright red background for
you to spot the problems better:
<link rel="stylesheet" href="m-dark.css" />
Other than highlighting problems, this file doesn’t alter your website appearance in any way. To save unnecessary requests and bandwidth, I recommend that you remove the reference again when publishing the website.