Implementation: A Better CSS

Even developers can’t understand it

This is a too common pattern among developers. Why is that?

few months ago I wrote an article mentioning the sad rejection of CSS by developers. There are several reasons for that, such as the difficulty to find good tutorials for beginners, but let’s face it: the primary reason for all that is the difficulty to understand the language itself.

Let’s look at the major blockers and how we could fix them.

Containers and contents

Let’s start by one of the most common source of confusions: the display property:

  • block defines a box whose space (size and position) can be controlled. By default, it allocates all the available width (the width of its container, or the viewport if at root level) but its height is still governed by its contents. Also by default, they are positioned below the previous element, in a vertical fashion.
  • inline defines a box that will be inserted in the horizontal reading flow (including line feed mechanism). Its space will be automatically allocated to suit its contents (so it is useless to try to set its size or position).
  • inline-block is a block that can be positioned as inline.

As if it was not complex enough, each HTML tag can have its own default display (<div> is displayed as block, <b> is displayed inline, etc.) which means that developers need to have a knowledge of those defaults.

From those descriptions, we can infer a more simple typing:

  • block is a container ;
  • inline is a content (strictly speaking, an inline element can still contain other inline elements, but those won’t be allowed to be blocks, and so will not be positionable as such) ;
  • inline-block is a content that can act as a container.

Container and content look like central but unspoken concepts in CSS, and as such are good candidates to refactor it. Along this article, we will try to stick on them, and them only.

What’s in a box?

CSS layout boxes, and defines a “box model” which basically nests 4 sub-boxes one in each other: content inside padding inside border inside margin.

The CSS box model

The thing is, events on the styled element (click, hover…) will occur only when you visually interact with any of them but the margin. So the « content» you care about most of the time when styling, is the box that starts with the border.

That way, we could reinterpret:

  • margin (the space between that actual content and its container) as a container-margin;
  • padding (the space between the border and the nested content) as a content-margin.

Positioning

One another source of confusion is positioning, as some positioning properties may have no effect depending on your display setting.

In CSS a box position can be set to:

  • absolute to render it at a position relative to its containing box (provided it itself set an absolute or relative postioning).
  • fixed is just a special case of absolute, that actually positions relatively to the viewport (so scrolling viewport contents won’t affect that position).
  • relative to move the box relatively to its current position (10px to from its left bound, 2em above its top bound, etc.)
  • static is the default, which is actually (almost) the same as a relative with no offset. This is probably the most confusing name, as it doesn’t relate to some fixed positioning but actually “no move”, i.e. no offset from its default position.

Here again, we can see that — as Einstein and other wise men said before — everything is relative to something. That way, we can reinterpret the settings above according to our container and content concepts:

  • absolute or fixed are actually container-relative positioning.
  • relative or static is actually content-relative positioning.

Conclusion

We defined some kind of “better” CSS (BCSS) language by reducing its number of concepts (container and content) and normalizing its properties around those:

  • a box type which can either be container or content (orcontent-container)
  • the content-color explicitly tells that the color is the one of the content ;
  • content-margin clarifies that that margin is inside the content
  • container-margin clarifies that that margin is outside the content
  • position now clearly states being relative to the container through the <offset> from container-<top|right|bottom|left> syntax and (implicitly but more simply) relative to the content current position through the <offset> <up|forward|down|backward> syntax. Default behavior can be stated explicitly using the unchanged value.

However this attempt only scratches the surface of the problem, actually. A real refactoring would require a lot more work, including in reviewing the above terms (which apply in most cases but not all edge ones).

Other approaches could have been attempted, such as focusing on the vertical vs horizontal concepts, or inner vs outer for instance.

Anyway, the goal here was not to replace CSS but, paradoxically, to get you more familiar with it. Did it work? If not sure, feel to play with the BCSS prototype below ; guess what the generated CSS is, then check it out!

Software engineer for three decades, I would like to share my memory. https://javarome.com