2022 Layout. Part 1: Theory
“The developer is the person who converts customer’s thoughts into machine language” — @mikita_du
The idea for this article appeared a year ago, I thought of calling it “2021 Layout”, but things delayed a little bit…
In Spring 2021 Microsoft announced that since June 15, 2022 IE11 support will be discontinued (not for all versions of Win 10, but still), which means that by the time the article is published less than six months remain until the landmark moment when you don’t have to make a layout using IE.
And for me, it means that it will be possible to make full use of the new standards of browsers, in particular — css-variables, grid layout.
How does the layout start?
It all starts with the design. More specifically, with these numbers — 16, 32, 24 (the magic sequence).
Not many people know, but these numbers are called rhythm in design.
It’s a multiplicity. In this case it is a multiple of indents of the number 8.
If you take 8px as the basis, then 16, 24 and 32 are 8*2, 8*3 and 8*4 respectively.
Designers usually make all the indents on the page a multiple of some number.
What’s important for us to know is that we perceive information much better this way and that all these indents are calculated from one number with simple multiplication.
Programmers get designs in Figma (like me — see screenshots above), where, in fact, they can see these magic numbers.
Using simple logic, lazy programmers (and I hope the reader is lazy, because this is not the best example of a programmer) write these values into the variables and will use them further.
For example, this can be expressed as offset-1 = 8*1, offset-2 = 8*2, etc. (material-ui style).
However, not everything is so great about this design:
Design of the same page. Everywhere we have eights, but here, you see, it’s a nine.
So, what are we supposed to do with it?
We have to go to a designer…
We come to him asking, “What is this indent? Did you make a mistake and it should be 8 here? Should I write like everywhere else?”.
And I’m just sure he won’t hesitate to answer, “Yes, because it’s 8 everywhere”.
Well, good, because you came to him after thinking about it, and he believes you. The arguments you gave are logical (eights everywhere), everything seems to be great, of course it should be 8.
But there’s a problem…
Designer doesn’t write (with numbers or text) indents between components, sections and other elements on the page. He just moves the pictures around the grid (at best), or simply uses the auto-align of the element.
In the example above, both you and the designer were only looking at a certain place in the design — the indents. And the information about what context the designer had when making the layout was lost.
And the context is as follows.
Block width on the page = 343px (as you can see in the first screenshots).
(343–9) / 2 = 167 (as you know — column width).
It turns out everything is correct. The context is just wrong. Specifically, this indent was not taken from an understanding of the rhythm of the page, but rather from the banal ability to fit content into the page. An even number can’t fit there.
So, let’s go back to our code.
Let’s say we did figure out where this number came from, but then what should the developer do about it?
Create a new indent variable? — But it’s not a multiple of 8.
So, make a new indent group multiple of 9? — That doesn’t sound good, it’s inconvenient and confusing.
Consult the designer once again? — Well, it is clear that he was right, it seems that everything is already solved.
Ugh, I’ll just keep it like this… (and it’s not even a joke, laziness is a scary thing, don’t underestimate it).
So we get this:
How are we supposed to read this? Where is the logic of all the thoughts that we had at the time of writing recorded here?
It turns out that we don’t write down the logic invented by the designer anywhere. We’re just copying what the designer did in the graphic editor.
Our designer acts the same way — he doesn’t write the indent logic anywhere. For example, there is a 32px indent between the header and the form, and half as much indent between the form elements — 16px.
Everything is forgotten as soon as it is made up.
It turns out that we lose important parts of the code at the design stage.
So I faced the question — how do I fix all these things?
How to keep the context, and more importantly, who should do it and where?
2. The idea
I thought for a long time, and then I came across an interesting idea.
What if we introduce special variables that preserve the logic of counting?
What if, instead of copying 9px, we needed to find an indentation based on the total width of the container (343px), assuming the columns are equal (167 from the design)?
I.e., basically write down the equation (343 — x) / 2 = 167.
Or x = 343–167*2.
As a result, we would have an indent of 9px.
It seems that the equation with the numbers did not add any readability.
Then let’s replace the numbers in it with variables:
$betweenColumnOffset = $screenWidth — $columnWidth * 2
There we go, now we’re talking. This makes the correlation clear.
So, you don’t have to go to the designer once again, and the code is now supported. And most importantly, it’s flexible. If we change the screen width, we don’t have to count the indent again.
3. Media queries
The code in the picture above looks a bit chaotic. There are obviously some questions regarding code separation, we can put variables in separate files, etc., but let’s move on.
What if we have an app that is not just for mobile phones? Let’s say we make a version for tablets and different computer screens (from FullHD to Ultra Wide).
Here we have to add media queries, and the code will become even more overwhelmed with variables.
We solve this problem by using css-variables:
Given that our columns take up the entire available screen width (100%), we can remove the — betweenColumnOffset override and replace the fragment with the following one:
This is how we get automatically generated indents based on column widths from the design. The logic can be simply inverted, and the width of the columns can be calculated based on the indent between them and the width of the screen.
Meaning -columnWidth: calc(100% — var( — betweenColumnOffset).
Where -betweenColumnOffset is overridden in media-queries.
You can apply this approach to every element in the project.
You will have dynamic indents between headers and elements.
Between the elements of the form.
Indents inside containers (cards or login forms).
All of this can be dynamically generated based on variables and derived from the customer logic given to you in the design form.
And most importantly, support and writing will take much less time and everything will be smooth because you won’t be doing pixel perfect, but you will be converting the customer’s thoughts into code.
I have already done 4 or 5 projects using this approach.
I even had to use three different designs on one project within two weeks. Of course, partially changing the logic of the variables, but the speed is still great.
It works great, the only problem is that it can’t be included in a library, because if you standardize it, you get something narrowly applicable only to a certain design, in the bootstrap or material ui style.
So I made 3 repositories in which I tried to display options on how you can apply css-variables + scss, or css-variables + styled-components to preserve customer and designer logic.
1) scss — https://github.com/DrBoria/cra-scss
2) styled-components — https://github.com/DrBoria/cra-styled
3) styled-components + a bunch of components — https://github.com/DrBoria/cra-components-library (this is actually an attempt to make a standard, but nothing comes out because the main idea is to adapt to the customer, the project, the designer, rather than produce another library)
In the next article, I will talk about the wonderful experience of making three designs within two weeks to show the line of reasoning and the pros/cons of this approach.
All examples will be based on the scss repository, so I suggest you check it out.