One of the challenges we face when implementing class-based atomic styling is that it often depends on a specific breakpoint for context.
<div class="span-12"></div> <!-- we want this for small screens -->
<div class="span-6"></div> <!-- we want this for medium screens -->
<div class="span-4"></div> <!-- we want this for large screens -->
It’s common to use a prefix to target each breakpoint:
<div class="sm-span-12 md-span-6 lg-span-4"></div>
This works well until we start adding multiple classes. That’s when it becomes difficult to keep a track what relates to what and where to add, remove. or change stuff.
<div class="
sm-span-12
md-span-6
lg-span-4
sm-font-size-xl
md-font-size-xl
lg-font-size-xl
md-font-weight-500
lg-font-weight-700">
</div>
We can try to make it more readable by re-grouping:
<div class="
sm-span-12
sm-font-size-xl
md-span-6
md-font-size-xl
md-font-weight-500
lg-span-4
lg-font-size-xl
lg-font-weight-700">
</div>
We can add funky separators (invalid class names will be ignored):
<div class="
[
sm-span-12
sm-font-size-xl
],[
md-span-6
md-font-size-xl
md-font-weight-500
],[
lg-span-4
lg-font-size-xl
lg-font-weight-700
]">
</div>
But this still feels messy and hard to grasp, at least to me.
We can get a better overview and avoid implementation prefixes by grouping attribute selectors instead of actual classes:
<div
data-sm="span-12 font-size-lg"
data-md="span-6 font-size-xl font-weight-500"
data-lg="span-4 font-size-xl font-weight-700"
>
</div>
These aren’t lost of classes but a whitespace-separated list of attributes we can select using [attribute~="value"]
, where ~=
requires the exact word to be found in the attribute value in order to match.
@media (min-width: 0) {
[data-sm~="span-1"] { /*...*/ }
[data-sm~="span-2"] { /*...*/ }
/* etc. */
}
@media (min-width: 30rem) {
[data-md~="span-1"] { /*...*/ }
[data-md~="span-2"] { /*...*/ }
/* etc. */
}
@media (min-width: 60rem) {
[data-lg~="span-1"] { /*...*/ }
[data-lg~="span-2"] { /*...*/ }
/* etc. */
}
It may be a bit odd-looking but I think translating atomic classes to attributes is fairly straightforward (e.g. .sm-span-1
becomes [data-sm~="span-1"]
). Plus, attribute selectors have the same specificity as classes, so we lose nothing there. And, unlike classes, attributes can be written without escaping special characters, like /+.:?
.
That’s all! Again, this is merely an idea that aims to make switching declarations in media queries easier to write, read and manage. It’s definitely not a proposal to do away with classes or anything like that.