CSS philosophy

Original author: Keith J. Grant
  • Transfer
Hello to all! The time has come to inform that we expect to release a new book on CSS before the end of February , which is recommended to everyone who has already mastered MacFarland (so far available, we expect to make the next reprint in January).

Today, you are invited to translate the article by China Grant (published in June), in which the author presents his point of view on CSS and actually explains what he wanted to say in his book. We read and comment!

I spent a lot of time thinking about what “CSS-oriented thinking” is. It seems that some manage to "learn" him, and others - no. I think that if I could articulate clearly what this worldview consists of, maybe the CSS itself would become clearer for those who are torn with them. This is partly why I sat down and wrote the book "CSS for Professionals."

Today I want to once again approach this problem. Consider the three key characteristics of CSS that distinguish this language from traditional programming languages. CSS is robust, declarative, and context sensitive. I think understanding these aspects of a language is a key prerequisite for becoming a CSS master.

CSS resistant

If you accidentally delete a piece of code in a JavaScript file, the application or web page where it is used will almost certainly crash or hang, and the script (or even the whole page) will fail. If you do the same in CSS, then maybe you won't notice anything. Practically all the rest of the code except the deleted fragment will continue to work as it should.

This property is called “ resilience ”. HTML and CSS were specifically designed for fault tolerance. If a problem occurs, the browser throws an error; otherwise, it simply ignores this part of the code and proceeds.

From the point of view of debugging, this may seem absurd: if the program does not throw out errors, how can we know that something has gone wrong? But this is the most important aspect of the CSS device. It is woven into the fabric of the tongue itself. I admit it takes time to get used to it. However, once you understand this, you can safely move on to using the features not supported in all browsers. This is what ensures the progressive development of the site or application.

Consider this example with a grid layout. It works in both browsers that support the grid, and in browsers that do not support the grid. In browsers where the grid is not supported, the layout will be slightly uneven (the exact dimensions of the elements may vary), but the page will still be laid out just like it should:

.portfolio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
.portfolio__item {
  display: inline-block;
  max-width: 600px;

A browser that does not understand the two grid declarations will ignore them, and the work will be completed thanks to other rules. In turn, the browser that understands the grid uses a grid layout and will ignore the inline-block declaration (since this is how the grid is designed). Jen Simmons, half in jest, calls this phenomenon “ Quantum CSS ”. You take some CSS capability and “both use and not use at the same time. But it both works and does not work. ”

Such a phenomenon of "safeguarding" behavior is an integral part of working with CSS, but it is alien to most traditional programming languages.

CSS is declarative

In JavaScript, we write specific step-by-step instructions that describe how a program should come to some result. In CSS, you tell the browser exactly what you want to see on the screen, and the browser finds a way to do it. To understand this is very important. If you learn it, CSS will do all the hard work for you , and if you don’t learn it, you will be up to the very core of the CSS language, and you will be disappointed over and over again.

When you write CSS, you actually set the constraint system. We do not indicate to the browser where each specific element on the page should be, but we inform you what indents between them should be, after which the browser puts everything in its place. You do not indicate to the browser (at a minimum, should not indicate) what height the container should be. You allow the browser to determine this for itself during the display, when it knows the contents of the container, knows what other styles are used in this context, and what is the available width of the viewing area.

You have to consider too many variables. The essence of CSS is to organize the process so that you can not worry about all these variables. Set a system of constraints. The language itself will take care of the details.

Simple example

Let's look at an example of the CSS: font-size: 2em. What does this code do? “Increases font size,” you say. But that's not all. It also corrects text line breaks inside the container, since now there are fewer words in each line. Accordingly, this often increases the number of text lines, and also increases the height of the container so that these new lines fit in it. When you change the height of the container, all the text located on the page under this container will move accordingly. Finally, the above code also sets a local value em. The values ​​of all other properties, in the determination of which units were used em, will have to be recalculated.

This announcement alone generates a whole plume of changes on the page. And all of them are designed to achieve exactly what you must strive for: the content always fits on the page, the elements do not overlap each other at random, and all the properties that depend on the font size (say, internal indents) are adjusted. You do not have to think about all these details. The browser itself performs all the listed calculations, and does it by default.

If you want none of this to happen, this can also be done. You can severely limit the height of the container properties max-heightand overflow: auto. You can override the indentation so that they are measured in units remorpxThat is, they were not counted following the font size. This opens up an interesting aspect of working with CSS: sometimes you don’t tell the browser what it should do, and, in fact, prohibit it from doing something.

The merits of the grid

However, in CSS there are new features that are even cooler. The most typical examples are Flexbox and Grid. Just a few ads - and you have an exceptionally flexible mesh layout that just works. Do not have to worry about numerous special cases. In fact, you order the browser: “put these blocks in columns of 400 pixels wide each”, and the browser does it for you. All about everything requires about three lines of code.

If you tried to do it imperatively, you would have to deal with a lot of strange scenarios. What if a word gets too long in one of the blocks? What if the viewport is too narrow? And if very wide? What if there is a whole sheet of content in one element, and just a few words in another? True, it is likely that in CSS you will not have to think about any of this. Everything is thought out for you and laid down in the specifications, and the browser follows the rules for you. This is the power of declarative language.

Of course, there is no cost without compromise. If the declarative language does not support any necessary opportunity for you (say, “to tile”), it is necessary to rely on grandfathers tricks or on JavaScript. Moreover, the development of CSS was largely devoted to the struggle with such things for many years. Fortunately, with the development of Flexbox and Grid, we can do much more, and without any hacks (yes, loose elements are a hack). If in this situation you are still missing something, I recommend reading about CSS Houdini , which are just starting to take root in browsers.

CSS is context sensitive

In the React era, we adopted an exceptionally practical approach: modular, component-based development. It is well in line with recommended CSS practices, along with BEM, SMACSS, and CSS-in-JS. I do not want to downplay the values ​​of all these possibilities, since they play a key role in the creation of large-scale applications. But I think it’s equally important to recognize that CSS is not 100% modular, and should not be.
There are two reasons for this. The first and most obvious one is that the application should be designed in global styles. Almost always you need to set the headset and font size at the page level, which will be used by default. After that, these values ​​will be inherited by all descendant elements, which will not explicitly override them. You also need some aspects of your design to be systematically applied across the entire page: color theme, rounding radii for blocks, block shading, and overall margins. More local styles that operate in parts of the page are applied in the context of these global styles.

The second, more subtle reason is that the work of CSS and your design decisions depend on the context of the page. Suppose we apply the following CSS styles to an element on the page:

.the-thing {
  position: absolute;
  top: 10px;
  left: 10px;

What will this code do? Not knowing exactly where this element is located within the DOM, and what styles are applied on the rest of the page, we cannot answer this question. Absolute placement is done relative to the nearest ancestor element, and such positioning will be different depending on which ancestor we are talking about and which placement was applied to it.

Moreover, your ability (or inability) to overlap elements will largely depend on where these two elements are located in the DOM. Mixing elements in a DOM can drastically affect the layout of elements and how they overlap each other. That is why document flow and overlay contexts are fundamental (although sometimes complex) topics.

The contextual nature of CSS has developed in part because of the design. If an engineer is designing a bridge, then you cannot just look at the drawing and say: “everything is fine, only I do not like this beam; take her away. ” If you remove one beam, it will affect the structural unity of the entire bridge. Similarly, it is enough to change any design element - and all other elements on the screen will be perceived differently. Often it is necessary to arrange several elements at once in close unity with each other.

For example, if you increase the heading on one of the tiles, it will become more visible to the user, and because of this, other elements on the screen will seem less important. Here the restrictions do not lie in the plane of physics, as in the construction of a bridge; it's about more “humanitarian” laws affecting human perception. Elements of the page are reflected on the screen, which has its own physical characteristics, and when working, it is necessary to take into account the realities of the physical world and how we perceive it.

As you know, the software architecture is subject to the principles of modularity and encapsulation. This approach is also justified at the code level, since the code is complicated, and the described method allows to break the problem into digestible fragments. However, it should be noted that this approach is imperfect. In CSS, you can never completely abstract from what happens in a particular module.


Three aspects described distinguish CSS from traditional programming languages. These differences may not immediately fit in the head, but they are the most strengths of CSS. I would venture to suggest that developers who will be able to grasp and how these principles should be learned will be achieved in CSS real heights.

Also popular now: