universal grid for all breakpoints, examples and rules

The material is intended for designers and Frontend developers. Designers will understand how to minimize the amount of work for layout designers, and thus get their approval. Coders will learn to save their resources, strength and brains in order to spend them on more useful tasks than calculating incomprehensible grids.

How it all started

In 2018, we switched to reactive frameworks. Our choice fell in favor of Vue. We use it in our projects most often. We liked the time and effort savings due to the component approach (HTML, CSS, JS in one file). Next, we decided to automate everything that could be automated.

Previously, when the company worked on a subcontract basis, we received layouts from various web studios (we still saw the days of layouts in Photoshop). The grids in these layouts were just awful. For example, 12 columns on desktop, 10 on some intermediate resolutions, and 2 columns on mobile. The indents between the columns could be completely different. All this drove us crazy, because each new resolution is like laying out a new layout. No savings, no benefits, constantly having to prove that it really is a lot of work, but no one was going to listen to us, because the layouts and budgets were already agreed.

As it was before

How it works now

Thinking about how you can reduce development costs, make it faster, we thought that when moving from designer to development, most of the errors are entered for layout. We started looking for them, and realized that grids are the biggest evil that can be in our joint work.

For example, it is not clear at what resolutions the designer draws a 1440 px layout and at what resolutions to switch to a 768 px layout. At 1439 px, the tablet layout looks bad. In addition, there are other basic resolutions, such as 1366 px, 1280 px, 1024 px, etc. We’re trying to do things our way. The result is a chain of iterations of alterations and revisions.

We thought: why not make one grid and work with it? After all, this should not greatly harm the designer in his work, but at the same time it will greatly facilitate the work of the layout designer. This is how the idea of ​​standardized rubber elastic nets was born.

Fluid layout is when we shift the work of adapting the layout to the available width of the browser to the browser itself. This is achieved by various CSS properties and units: vw, %. At the same time, the layout is very, very rarely scaled.

Rubber layouts are made only horizontally. If we make fluid layout horizontally and vertically, then most likely we have a layout with a change in scale, the so-called scalable layout, it does not rebuild the content.

That is, when creating a fluid layout, the developer even transfers the rebuilding of the layout to the browser so that all calculations are made on the browser side, so the developer can not waste time on “extra” styles.

  • Adaptive (fixed)

  • scalable

  • Rubber (so called because it stretches, it is liquid, but at the same time returns to its original state)

    Grid examples

    Here is a sample of how grids are usually drawn. At 1920px 12 columns:

    1440px has 10 columns, 768px has 6 columns, 320px has 2 columns

    For us, this is bad. We decided to get away from it.

    We draw a ten-column grid. It is easier to count on the layout

    Next, compress the width

    We see that only the width of the columns is scaled, but not the indents of the columns (gutter) and the margin at the edges. This prevents us from using the grid properly if we just copy the original layout and reduce the width of the layout.

    For maximum scaling, we need both the gutter and margin to change, so we move on to manual scaling. For this we use 10 columns, 40px margin and 30px gutter.

    Let’s calculate the percentage. We take the 1920px layout as a basis.

    margin 40px will take: 40 / 1920 = 0.020833333333 = 2.083333%

    gutter 30px takes: 30 / 1920 = 0.015625 = 1.5625%

    157px column width: 157 / 1920 = 0.08177083333 = 8.177083%

    To check, we can add up all the dimensions:

    10 columns + 9 gutter + 2 margin

    (157 * 10) + (30 * 9) + (40 * 2) = 1920px

    So we have percentages:

    • column 8.177083%

    • edge margin 2.083333%

    • padding between columns 1.5625%

    Calculate dimensions on a 1440px layout:

    • column width: 1440 * 8.177083% = 117.75px

    • margin: 1440 * 2.083333% = 29.99999px

    • padding: 1440 * 1.5625% = 22.5px

    grid at 1440px
    grid at 1440px

    In the same way, you can calculate the dimensions for all layout widths

    grid at 1024px and 768px
    grid at 1024px and 768px
    grid at 320px
    grid at 320px

    As we can see, our mesh has been preserved. It just shrunk relative to the width of the layout, the width of the canvas.

    From all this it follows that for fluid layout, we just need to get percentage sizes. In this case, we do not need to take a calculator and calculate these coefficients. We will transfer this work to the browser.

    Code for rubber layout

    Let’s move on to practice. We use the scss preprocessor and the percentage function to calculate percentages to keep the code short. Let’s write the following in HTML and CSS: https://codepen.io/danilabr/pen/yLpbxPr


    <div class="is-grid"></div>


    : #00f;
    " class="formula inline">grid_margin: percentage(40 / 1920); // 40 / 1920  100%;
    : percentage(157 / (1920 - 40 * 2));
    " class="formula inline">grid_gutter: percentage(30 / (1920 - 40  2));
    body {
       position: relative;
       padding: 50px 0;
       min-height: 100vh;
       &.is-grid::after {
           content: '';
           position: absolute;
           z-index: 1000;
           top: 0;
           bottom: 0;
           opacity: 0.15;
           left: ;
           right: " class="formula inline">grid_margin;
           background: repeating-linear-gradient(90deg,
                   " class="formula inline">grid_color ,
                   transparent " class="formula inline">grid_width,
                   transparent  + " class="formula inline">grid_gutter);
           pointer-events: none;


These styles make it possible to make it so that when a certain key is pressed on the body, the .is-grid class is added and this grid is displayed. This allows you not to waste time on pixelperfect, and at the same time, during the layout process, make sure that the blocks are placed correctly on the grid.

The width of the $grid_width column and the spacing between the $grid_gutter columns will be calculated not relative to the total width of 1920px, but minus the margins on the left and right $grid_margin:

$grid_width: percentage(157 / (1920 - 40 * 2));
$grid_gutter: percentage(30 / (1920 - 40 * 2));

In the styles of the grid, we cut off the left and right margins:

left: " class="formula inline">grid_margin;
right: ;

Using the gradient, we loop the rendering of the columns:

background: repeating-linear-gradient(90deg,
               " class="formula inline">grid_color 0,
                " class="formula inline">grid_width,
               transparent ,
               transparent " class="formula inline">grid_width + );

Next, add a .wrapper wrapper, and put a .column-item element in it https://codepen.io/danilabr/pen/LYeyXba


<body class="is-grid">
    <div class="wrapper">
        <p class="column-item">123</p>


.wrapper {
    margin: 0 " class="formula inline">grid_margin;

Note that the left and right padding value of .wrapper will be correct at all resolutions, we don’t need to write additional media queries and override this value. This is a huge time saver.

Let’s add some decorative styles to .column-item:

.column-item {
   height: 50px;
   background: grey;

Let’s make the width of .column-item equal to five columns. This can be done in several ways:

1. Just measure the width of 5 columns with padding in the layout. Or add the width of the columns by hand:

5 columns * 157px + 4 padding * 30px = 905px.

(do not forget that 1920px minus 2 indents on the right and left of 30px = 1840px).

width: percentage(905 / 1840);

2. The same in pure CSS:

width: calc(905 / 1840  100%);

3. You can count 905 / 1840 on a calculator (it’s better not to write like this):

width: calc(0,4918478261  100%);

4. Or, if we use our variables:

width:  * 5 + " class="formula inline">grid_gutter  4;

The result of all these options will be the same:

Connect mixin mq, or breakpoint error through variables

Often Frontend developers use global variables in the preprocessor as breakpoints. For example, the main resolutions are: 1920px, 1440px, 1024px, 768px, etc. But this drives the developer into a very narrow framework. It happens that situations arise when we have an intermediate resolution: for example, 905px. The text often does not fit on it, for example, a word that is too long.

The fastest solution is to reduce the text size. If for these non-standard points to get additional variables, then this is a bad way. There can be many of these variables. This is also why we don’t use bootstrap.

We want to leave ourselves the freedom to use different break point values. To do this, we use the mq() mixin, which looks like this:

@include@content@mixin mq(, " class="formula inline">to: false) {
   @if  {
       @media (min-width: #{" class="formula inline">from}px) and (max-width: #{}px) {
   } @else {
       @media (max-width: #{" class="formula inline">from}px) {

The mixin takes 2 parameters. The second one is optional. If only one parameter is passed, then the desktop first approach is used, if 2, then mobile first.

Let’s add a mixin mq and a breakpoint of 768px to the previous example.

.column-item {
     @include mq(767) {
       width: calc(#{} * 4 + #{" class="formula inline">grid_gutter} * 3 + 5px);

When the screen width is less than 767px, the .column-item width will become 4 columns + 5px.

Slider with dynamic height


Change the screen width and see how the photos fit into our grid in different ways. The comments provide clues as to where the widths we use come from. Note that these styles allow us to maintain the correct proportions of photos on all screen sizes:

i {
   display: block;
   padding: percentage(9 / 16) 0 0;
   background: none no-repeat 50% 50%;
   background-size: cover;
Screen resolution over 1280px
Screen resolution over 1280px
Screen resolution less than 1280px
Screen resolution less than 1280px
Screen resolution less than 768px
Screen resolution less than 768px

Two blocks in a rubber mesh

Let’s demonstrate three layout options for placing two blocks in a grid. The result will be the same:

Screen resolution over 1024px
Screen resolution over 1024px
Screen resolution less than 1024px
Screen resolution less than 1024px

one. The first way with display: flex; https://codepen.io/danilabr/pen/LYeLWzN

At a resolution of less than 768px, let’s make the padding of the blocks rubber

with padding: percentage(20 / (320 – 7 * 2));

2. The second way is using display: grid; https://codepen.io/danilabr/pen/QWagmxg

Grid basically allows you to write less code. It should also be noted that in this case we can use rubber padding for blocks at all screen resolutions, because grid calculates percentages for padding from the width of the cell, and not from the entire container, as in the previous method.

But, in this case, at very large screen resolutions, padding will be more than on the layout. We at our company decided that this is normal, that it adds liveliness to the layout. Of course, such changes must be coordinated.

3. In the third way, we completely abandon media queries. The modern frontend allows you to do this as well. https://codepen.io/danilabr/pen/wvpejWr

To do this, in html we had to add wrappers above the

tag. The main logic is in the following line:
flex: max(482px, (100% / 2 – #{percentage(30 / 1840)}));

This uses flex-basis and the native css max function. On resolutions where the column size is less than 482px, the second parameter of the function will be used (100% / 2 – #{percentage(30 / 1840)}).

Columns are stretched to full width due to flex-basis, transferred to the next line due to flex-wrap. In this case, we transfer all calculations to the browser side.


In conclusion, I would like to write a list of the main postulates that will allow you to make rubber layout quickly, efficiently and reliably:

  • Use percentages as much as possible.

  • Use automatic sizing formulas as much as possible.

  • Use ratios as much as possible.

  • Use grid as much as possible.

  • Look for ways to write fewer styles in order to offload sizing to the browser.

  • To correctly display all images, use cover or contain.

Similar Posts

Leave a Reply