Old dogs, new CSS tricks
mxb.dev
mxb.dev
A number of things are in play here.
1) when people ask for something it's because they need it now. The client wants it to look like x. Providing it a year later doesn't mean I'll retro-fit it, I'm working for another client now.
2) the new features on offer are (mostly) not low-hanging fruit. 20 years ago we were asking for the basics - not-table layout (flex, grid), variables (var --), conditionals (@media) and so on. The low hanging fruit stuff. Now "most people" aren't really asking for anything. (The sliver of a minority attending css conferences naturally are dreaming up new edge cases.)
3) most of the websites that exist (aka have been styled) are older than these features. Since redesigns are typically multiple years apart it takes years for them to filter in. As a proportion the number of sites built, or updated, in the last year is small. And the proportion of those needing these features is smaller.
4) most sites are not styled from an empty notepad. Most use (reuse) a framework - either personal or public.
CSS is starting to move from mid-stage to late-stage development. We're well passed the "terrible to work with" stage, well passed the "good enough" stage, and now into the "what can we dream up stage".
That said I can see myself using some of these things - sub-grid and :has being the obvious ones for me.
I will however definitely rely on the has: selector next time I encounter that situation (it had to do with markdown output putting img tags inside paragraphs, so I needed css that treats a paragraph that has a img inside differently than other paragraphs).
Here is a blog post outlining what can be done using :has https://webkit.org/blog/13096/css-has-pseudo-class/
Also, as someone who started doing web dev professionally nearly 20 years ago where if it didn't work in IE 6 then you just couldn't use it at all, I just instinctually don't even bother with new (as in 3-4 years old) CSS or JS features most of the time. It's pretty deeply ingrained in me and I suspect many other devs who were around in that time. That said, 5-year-old CSS and JS specs at this point are pretty damn good and you can do a whole lot of cool stuff with them, so this is not nearly as painful now as it was back then.
Good enough is good enough.
I'm also a web dev with nearly 20 years and do exactly this as well. Old versions (or any version of) IE crushed our dreams too many times to feel comfortable delivering anything modern, let alone cutting edge.
I’ve definitely used :has() though to replace the need for certain CSS combinators—for example, being able to style a label that wraps a checkbox based on the checkbox being checked, rather than relying on the next-sibling combinator while placing the label after the checkbox input. That’s pretty cool and solves some limitations that existed previously.
Should we be cautious about relying on non-standard features or trusting the perma-beta culture that Google never seems to have grown out of? Of course. But there have been many recent developments that are useful and already widely supported, and not using those when they provide a good solution to an immediate problem seems counterproductive.
We'll almost certainly see more container queries used on new website/app development projects going forward, but any that started prior to their integration into most browsers are likely going to remain using the old design philosophy with media queries instead.
“Granted some things are relatively new, and others might be sort of niche-y.”
And once other browsers starts supporting it, the experience will automatically work in those browsers too without you needing to touch a single line of code :)
Quite the opposite. The alternative to "no view transitions" isn't "clunky hard-refresh page-by-page experience," it's single-page view transitions orchestrated by JavaScript (instead of by Chrome). View transitions require you to fundamentally change the architecture of not just a page, but your entire website/app.
And that’s not necessarily a bad thing.
As I commented a few days ago, nowadays devs don’t seem to care too much about backwards compatibility. I like to hold onto my devices longer than most people and it’s a bit frustrating to see that most sites nowadays expect you to be in the latest and greatest. It didn’t use to be like this.
We recently had a user email us that our app stopped working for them. After we dug into it it was because their Chromebook was last updated in 2021 and didn't have Object.hasOwn (which a third-party library uses) and it's not even included in most common polyfills either. We fixed it, because I hate these sorts of compatibility issues.
Nevertheless, I left a bit concerned that they hadn't updated their Chrome in 3 years. Software decays much quicker than hardware in a real way, especially with the never ending list of security vulnerabilities found every year. Theres definitely a case to be made that forcing software upgrades is good for the end user too.
[1] https://support.google.com/chrome/thread/185534985/sunsettin....
—⁂—
¹ When I say “depend” I mean “break if it’s not present”. A degraded but still functional experience is acceptable.
² I don’t use Apple stuff, so correct me if I’m wrong, but I believe that this used to be the case for macOS but may be fixed since macOS 12 <https://en.wikipedia.org/wiki/Safari_(web_browser)#Version_c...>, and is still the case with iOS et al. I believe iOS/Safari 15 is still the current version on some actively supported devices.
I suspect that many people who use old Safari versions are either used to sites being broken, or they use Chrome and don't care. I wish we had more data to verify those assumptions.
I find it silly how some people tack on "just ship a fallback stylesheet" as a legitimate answer (not accusing you) because we all know that it's never that simple.
@container style(color: green) and style(background-color: transparent),
not style(background-color: red),
style(--themeBackground),
style(--themeColor: blue) or style(--themeColor: purple),
(max-width: 100vw) and style(max-width: 600px) {
/* <stylesheet> */
}
It is useful as a selector for people. Best not let that guy anywhere near my code.What's the connection to security vulns? How does that impact devs not using "a separate stylesheet to support everyone." or ignoring "progressive enhancement"?
Or what's the vulnerability explanation of hasOwn?
It seems it mostly decays quicker on some webby platforms that culturally don't care much about backwards compatibility
Firefox has an LTS version which can be a baseline for features, but which receives security updates at the very least.
I don't know about, say, Chrome 80 line that would receive security fixes but not new features. I also think that would be against Google's interests to have such an LTS line, it would decrease the moat between it an other browsers.
With Firefox (ESRs are at 102 and even 52) and, to an extent, Safari (tied to iOS releases) there are non-arbitrary baselines, where you know what kind and size of the audience you additionally cover by staying away from newer features.
Also don't you have stats by version number, what is extra non-arbitrary about LTS?
Browsers are updated to fix the security vulnerabilities.
People upgrade to the latest version to get the security fixes.
If a person is using a browser that is years out of date, they are subject to a lot of security vulnerabilities in a piece of software that is constantly exposed to untrusted code.
Using an old browser is unsafe. If you encounter people using old browsers, you should strongly encourage them to do whatever they can to update their browser for their own good. If they do this, a nice side-effect is that you don’t have to support their older browser version.
It seems very easy to understand the logic here. What part don’t you grasp? Don’t support older versions => this pressures them to upgrade => upgrading is good for their security.
Now, some streaming services do not work anymore, because the website doesn't work. Why? There is no real technical reason for this. For some streaming services I have a collection of the real streaming URL. That still works fine. The problem is not the streaming itself, it's the website to choose the right stream.
Any time someone says this it's important to add a caveat of "and I want my site to look the same everywhere". Using @supports means you can feature detect what CSS the user's browser supports and enhance where possible. A user with an older browser might see a less pretty, simpler design with somewhat worse UX, but that's often ok if it's a tiny minority and you can give the users on new browsers a much better experience. The two versions might look a bit different but that's fine.
If your css is a mess in 2024 (2016 really) it is all on the developer and not the language.
There's nothing wrong with those solutions and I've used those and similar plenty, but they are fragile. Those are conventions that have to be maintained and stuck with, and often for scoped style solutions you're also left with a hard dependency on a build step (BEM is an exception there). That may not be a problem at all, if you're using react you almost certainly already have a build and bundle step, but not every project is that way.
What I'd really like is more intellisense for css so I could take a css file and get sensible code complete and class suggestions for elements.
If you use the inspections, it can also make dead code removal really easy.
Even though MDN lists most of these features as "baseline" supported, the reality is that a small but still meaningful share of our users are using old iOS devices – especially iPads – and they can't or won't update their operating system to update Safari. Our oldest supported browser is Safari 14 because of Flexbox gap support.
None of the other platforms are a problem, as basically everyone else is using an automatically updating evergreen browser.
When people say Safari is the new Internet Explorer, replies always mention how Safari just adopted such and such bleeding edge CSS feature (while ignoring much older features, though), but the truth is many Apple users won't see those features for years, until their devices break.
Apple is stopping both users and developers from enjoying these very same new features they so happily announce. The web is stuck in time, waiting for enough people to update their devices. Just like in the age of Internet Explorer. At least back then people had the option of installing a different browser. So maybe Safari and the apple ecosystem is actually worse than IE and Windows used to be.
Yet another case of iPads being held back by their software. IIRC, iPads have slower replacement cycles than either iPhones or Macs.
:has() and :is() are awesome.
One issue I’ve had with any of the newer CSS features is that, most of the people I work with don’t know what they do, because nobody use them. So, I have to explain myself in each pull request - but I guess that’s ok, because then people learn.
> And while support for Container Queries is green in all modern browsers, people still seem reluctant to go all-in, fearing they could break something as fundamental as site layout in older browsers.
Don't you know there are still a fuck ton of people that are still using the old iOS versions with their old phones? I have plenty of them, and they are long term supporters that I just can't shut them off.
There are new css features that are almost harmless and do not affect the usability, some css features on the other hand...
Most of us just decide to ignore them, because a significant portion of our userbase stills stuck with old devices. People who agree with this article probably never get accessed to any website statistic dashboard.
I don't want to argue for Tailwind, but as someone who's used it for ~4 years now, it strikes me that I've forgotten what it's like to have to think about sets of CSS rules and how they collide.
Utility class systems completely remove the need to even consider conflicting rules.
That doesn't mean CSS shouldn't continue to grow though, and I welcome these new features.
This should be one of those articles one can click around in for considerable time.
Having to select and search made me wonder at what point in time we lost the ability to click on the bullet to select the list item text? Does anyone remember that feature?
> Container Queries
I haven't used this, but it looks super useful.
> Style Queries
Eh, I'm sure this is useful for situations that don't come up very often.
> CSS Layers
Ugh, I'm not going to use this overly-complex silliness, and I'm not looking forward to debugging this when other people use this.
> Subgrid
Again, overly complex. Grid could already do everything this can do, more simply.
> Native Selector Nesting
I'm already using this.
> Anchor Positioning
Eh, I already had solutions to this problem, but this seems like it probably communicates intent a bit better. I guess I'll pick that up.
> :has, :is, :where
:has is useful
:is... okay, fine, syntactic sugar.
:where I don't believe in hell. If I did, I'd be against it because burning someone for eternity is inhumane. But I might be willing to make an exception for people who write CSS that requires you to read the MDN article on Specificity to understand it.
> Logical Properties
Perhaps useful for situations that don't come up very often. Seems complex, but that might be because the thing it's representing is inherently complex.
> Scroll-Linked Animations
Okay, someone who isn't me will probably do really cool things with this.
> View Transitions
Another thing that seems complex, but possibly because the thing it's representing is inherently complex.
if you wanted to use grid template areas, and you had something that looked like
<div id="my parent grid">
<h1>Title</h1>
<ul>
<li />
<li />
</ul>
</div>
There isn't a great way to make the <li> adhere to the grid template areas, because without subgrids only direct children (the ul) have coordinate attributes.Subgrid lets you do it for anything more involved or deeper though.
It's a neat hack, but it's still a hack.
The first thing I do when I see an acronym or word I don't understand is go to Google and type `what is a11y webdev` or whatever. I think you get the idea.
This has been a part of my life for almost 2 decades now so I'm curious how others handle the situation! What made you wait so long to find the answer? Did you eventually search for it, or did you finally read some document that spelled it out explicitly?
Again, genuinely curious! I assume many people operate like I do and there is a line between explaining too little and too much. Understanding how others approach these problems hopefully will help me improve my own communication in the long run.
It was the parent comment mentioning a11y and screen-reader in conjunction that made me make the connection, I just found it hilarious that the term a11y itself is so inaccessible if you don't already know what it means!
May I ask you, are you a front-end developer?
How else do you really keep up on all the crazy new stuff
Pretty much everyone in the field knows about MDN (https://developer.mozilla.org/en-US/ )
and https://web.dev
but the Interop project is newer and maybe flying under the radar:
https://webkit.org/blog/14955/the-web-just-gets-better-with-...
Enjoy!
--
Now, if your domain ends in .dev you can just assume that your users are up-to-date techies, but otherwise I avoid anything newer than flexbox (which is just so useful).
> You’d need a separate stylesheet to support everyone.
Are we going to add an entirely new testing suite and workflow tools to save 5 lines of legacy CSS in favor of the new version? Probably not in a lot of teams.
You also need to write and maintain code to conditionally load that fallback stylesheet and hope your users aren't using some weird user agent hacks (looking at you instagram in-app browser).
All of these problems can be solved, but obviously nobody wants to because the juice is not worth the squeeze. This is not our first rodeo. I'm gonna wait another 18-24 months and then start using most of the features released this year. It's fine.
Safari has supported CSS nesting since v16.5. The specification was updated to remove the earlier requirement to use & though, and support for that was introduced in v17.2. As long as you include the &, you can support everything back to v16.5.
Not sure what you are referring to regarding Windows < 10, but Windows 10 was released nine years ago. Only a tiny fraction of web developers need to support decade-old clients.
If you do need to support browsers that don’t understand CSS nesting, use PostCSS or Lightning CSS. They will transcode your nested CSS to older syntax browsers support. Then, when you drop support and remove those browsers from your browserslist, they will stop transcoding it and the CSS you deploy will get smaller. But you’ll have been writing standard nested CSS all along.
I am referring to the fact that there are no browsers with native CSS nesting that support Windows < 10.
Non-& is not “the normal syntax”. It was a late addition to the specification. Both with and without & are normal, but with & has better compatibility.
Even if you don’t use the &, you can still write nested CSS and support older versions of Safari, like I said. Use PostCSS or Lightning CSS. There are normally several areas where you can start writing modern CSS today and fill in the backwards compatibility with these tools. It’s not just nesting.
Obviously I'm talking here about direct serving of CSS assets without precompiling.
Sass and BEM methodology works fantastically well. Naming things isn't that hard, but Tailwind/utility approach is also extremely useful.
Those new features, besides container queries is just gibberish. Layer? WTF? The cascade is bad enough as it is, most devs can't even deal with the cascade it's why Tailwind become so popular. And we should dive even deeper into the cascade BS with layers and scoping and whatnpt? Again, this all looks like it was made to be output by some CSS compilers, not written by a developer.
At the end of the day these are all more tools in our toolbelt. If you want you can keep writing CSS the same way you always have.
I don't really stand by GP's comment but I also don't think their concern can be dismissed this easily. We generally write CSS as teams. You'll have to read as much CSS as you'll have to write. Ideally you actually read more than you write so you can reuse existing rules and follow established patterns
Anyone writing CSS for a day-job, an OS project, or even just following a tutorial will have to at least familiarize themselves with these concepts
on edit: just to note I'm generally the old guy who is pushing for people to use 'new' stuff like clamp, min, and max functions and lab color profiles, to no effect.
I understand that feeling to some degree. At the same time, I think this is just how CSS has always been. Originally we had to style pages with tables and when flexbox/grid came out there were oodles of devs who refused to use them for a while. CSS is an ever-evolving toolset and I like that, but I do understand that change can feel unwarranted to some.
I think the syntax is good (getting better with nested selectors)
Maybe in 10 years time we’ll finally get to what sass can already do today.
An ideal version of CSS would remove the need for SASS, BEM, and any non-thematic framework. That we have to use those right now is a problem to be fixed.
Are there selectors for this anchor relationship? e.g. style anchored element when anchor is on :hover
> Container Queries
They aren't useful yet because:
1. Using them requires a wrapper element which can dirty up the HTML
2. While we were waiting for container queries to arrive, we also got new rules that made fluid layouts easier to implement which handle a chunk of container queries use cases.
Container queries will become more useful when elements can query their own size, rather than their size inside a designated parent.
> Style Queries
A solution in search of a problem. Current selectors are acceptable for most current use cases. May be useful for customizable widget/dashboard style layouts.
> CSS Layers
Nice, but they currently place too many demands on the developer to understand what layers currently exist. These will become more useful as browser dev tools make debugging them easier to reduce the burden on the developer to keep the layers in their mind while coding/debugging.
> Subgrid
Very useful when you need things aligned, especially in things like card layouts. The only thing holding this back is developers who are too reliant on 3rd party framework/libraries, e.g. bootstrap developers relying on grid column classes and tailwind developers building things with margin/padding everywhere. This will take time for developers to shift to, but those developer who limit themselves inside their own framework/library bubbles may never use them.
> Native Selector Nesting
Very nice quality-of-life improvement.
> Anchor Positioning
Only supported by one browser. I have no idea why this was even in the article to begin with. But it will completely remove the need for some JS placement/layout logic that keeps getting reimplemented all the time with pop-ups (pave the desire paths and all that). It also has the potential to make margin notes easier.
> :has, :is, :where
:has is super powerful as a parent selector
:where is great for simplifying repetitive css
> Logical Properties
If you maintain the discipline required to use these aliases over {top/left/down/right}, or if you have a linter to remind you, all of a sudden you're now able to support RTL languages without needing to spend time and money to make a different site for them.
> Scroll-Linked Animations > View Transitions
Both will be abused by marketers and "designers" who don't understand accessibility, but both will also greatly simplify micro-interactions on proper websites that aren't trying to be a "marketing experience".
@property (not mentioned) is only in Firefox Nightly; hopefully it makes it for 128 ...
@property will be nice, but almost every initial use-case will be animation related. That said, I'm happy it's reaching baseline support since more powerful features can be built on top of it.
New paradigm (container queries): You make layout changes based on the width / height of the containing element.
This lets you layout a component so that it looks good in any sized container. Picture a component that might be in the main section or in the sidebar - you can now just style directly based on width of the container instead of having to know the total width of sidebar + main section and do the calculation using viewport width.
media queries are still useful, and since a media query may hide/remove entire containers in the view then the remaining containers may have widths that are no longer a simple proportion of the viewport width (or other property being selected for).
So container queries can also enhance styles with media queries, not just replace them.