Features I look forward to in future CSS
attr()
, :has()
, and a “timeline” for the future
When writing a web page, I try to avoid JavaScript. Relying on a general-purpose programming language for layout doesn't feel right, not to mention that JavaScript can be blocked or unsupported. In a perfect world, HTML describes the content,[1] and CSS takes care of delivery.
CSS has come a long way,
and websites like
css-tricks.com
are full of brilliant examples.
With the coming of variables and calc()
,
and the going of Internet Explorer,
JavaScript and CSS preprocessors are slowly becoming unnecessary
for my simple use cases.[2]
With that in mind,
here are two likely future CSS features that I am looking forward to.
The :has()
pseudo-class
Truth be told,
the
:has()
pseudo-class
(allowing to select a parent by its children)
is probably more of a utility feature to me.
I would use it in places where I would now use classes,
allowing me to focus more on content when writing HTML.
But Jen Simmons shows
some really cool use-cases,
some of which are currently impossible to implement purely in CSS.
WebKit and Blink already support it.
Hopefully, Mozilla will follow suit soon.
The attr()
function
Yes, the
attr()
function,
for referencing the value of an HTML attribute,
is not that new.
In fact, it is widely supported — for use in the content
property.
But I would like to use it in places like this:
<div class=timeline data-from=2000 data-to=3000>
<section data-year=2000>Something happened.</section>
<section data-year=2200>Then this.</section>
<section data-year=2300>Then that.</section>
<section data-year=2400>And such.</section>
<section data-year=2800>And then, after a long time.</section>
<section data-year=3000>Finally.</section>
</div>
<style>
.timeline {
--from: attr(data-from);
--to: attr(data-to);
--span: calc(var(--to) - var(--from));
}
.timeline section {
--year: attr(data-year);
--reltime: calc(calc(var(--year) - var(--from)) / var(--span));
background-color: rgb(255 140 0 / var(--reltime));
padding: .5em;
}
.timeline section::before {
content: var(--year);
margin-right: 1em;
}
A timeline, where the further we go towards the end, the darker the orange background gets, giving a bit of sunset vibes.
This does not work in any current browser.
For a good reason: attr(data-from)
will return 2000
as a string
,
as will all attr(attribute)
calls,
and therefore the calc()
s will fail.
Luckily, the draft specification
allows us to specify the desired type (as well as a fallback value).
The proper code (according to the current draft) becomes:
.timeline {
--from: attr(data-from number); /* specify number type */
--to: attr(data-to number);
--span: calc(var(--to) - var(--from));
}
.timeline section {
--year: attr(data-year number);
--reltime: calc(calc(var(--year) - var(--from)) / var(--span));
background-color: rgb(255 140 0 / var(--reltime));
padding: .5em;
}
.timeline section::before {
content: attr(data-year); /* re-attr() since we need a string */
margin-right: 1em;
}
Sadly, at the time of writing, no browser supports it yet. For use cases like this, we are either bound to a preprocessor (separate class for each timeline, seperate class for each timeline section) or we must fall back to JavaScript.
To show what the above should look like, we can use a tiny bit of JavaScript:
const timelines = document.querySelectorAll(".timeline");
const sections = document.querySelectorAll(".timeline section");
const convert = attr => el =>
el.style.setProperty(`--${attr}`, parseFloat(el.dataset[attr]));
timelines.forEach(convert("to"));
timelines.forEach(convert("from"));
sections.forEach(convert("year"));
If you are from the future, and all is well, you should see the effect below.
If not, press
to let JavaScript do the attr()
s.
Neat, right?
Conclusion
The web is close to the ideal situation where HTML can be used just for content, and all styling can be handled in CSS. JavaScript will still be invaluable for interactive content, as it should be. But for simple websites, the added complexity and performance overhead will become unnecessary — W3C/WHATWG volente.