Implementation: A Better CSS
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
blockdefines 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.
inlinedefines 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).
blockthat can be positioned as
As if it was not complex enough, each HTML tag can have its own default
<div> is displayed as
<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:
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-blockis 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:
The thing is, events on the styled element (
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
padding(the space between the border and the nested content) as a
One another source of confusion is positioning, as some positioning properties may have no effect depending on your
In CSS a box
position can be set to:
absoluteto render it at a position relative to its containing box (provided it itself set an absolute or relative postioning).
fixedis just a special case of absolute, that actually positions relatively to the viewport (so scrolling viewport contents won’t affect that position).
relativeto move the box relatively to its current position (10px to from its left bound, 2em above its top bound, etc.)
staticis the default, which is actually (almost) the same as a
relativewith 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:
fixedare actually container-relative positioning.
staticis actually content-relative positioning.
We defined some kind of “better” CSS (BCSS) language by reducing its number of concepts (
content) and normalizing its properties around those:
- a box
typewhich can either be
content-colorexplicitly tells that the color is the one of the content ;
content-marginclarifies that that margin is inside the content
container-marginclarifies that that margin is outside the content
positionnow 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
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!