Implementation: A Better CSS
Even developers can’t understand it
A 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 ablock
that can be positioned asinline
.
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 acontainer
;inline
is acontent
(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 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 acontainer-margin
;padding
(the space between the border and the nested content) as acontent-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 arelative
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
orfixed
are actually container-relative positioning.relative
orstatic
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 becontainer
orcontent
(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 contentcontainer-margin
clarifies that that margin is outside the contentposition
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 theunchanged
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!