Great overview. I'm always excited by newer features to CSS that make older JS-only methods obsolete. I've also grown CSS-tooling fatigued after using SASS and PostCSS plugins for years. I've recently gone back to only using vanilla CSS on personal projects and while there are niceties I do miss (nesting) it's refreshing not having to deal with config files or waiting for stuff to compile.
:is() exclusively reduces nesting if your nest produces a single rule, which is the least common situation and is generally dealt with by just duplicating the selector rather than nesting.
:is also has tighter specificity then a nested selector. which is a footgun for sure. However you can use :where instead, which is basically just :is without this footgun.
there's a subtlety missing: :is() selects the highest specificity from the selector list while :where() sets specificity to 0 for anything in the selector list. this leaves out the (admittedly narrow) case where you want the lowest matching specificity (in case 2+ selectors match) rather than just 0, which is probably what most folks would expect, just as we would tend to expect selector lists to be forgiving (following the principle of least surprise).
But what Vite didn't have to do anything because CSS already comes with nesting? CSS nesting was proposed over eleven years ago, and is only today finally making it into a single browser, behind an experimental flag. Three major preprocessing languages were invented and two of those (mostly) died off again in the mean time. We shouldn't need preprocessing here, we should have had nesting ten years ago =)
Right, but the only reason they shine is because they do something we all want but isn't in the spec. So getting it into the spec should absolutely be the goal here =D
I'm always excited by newer features to CSS that make older JS-only methods obsolete.
I wonder if it's just about how some people's brains are wired.
I grok CSS. I won't claim to know everything about it, but I'd say I'm 90% proficient and prefer it to JavaScript.
But I think this is because JavaScript somehow never fully made sense to me. I can read it and figure out what it's doing, but it was never intuitive to me the way CSS is.
I read comments on HN frequently from people who are good a JS, but can't deal with CSS.
I think it's just how some languages "click" with different people. Some are comfortable in Lisp, while others are AP/L, or Rust, or something else.
Perhaps it's good to have multiple ways to achieving the same thing, rather than obsessing about one perfect/standard/preferred/"best practice" way of doing things.
No. If you have to write styling in JS I can guarantee that it will be far more brittle, less performant, and way more susceptible to FOUCs, reflows, jank, and potentially deadlocks of conflicting resizing elements than the equivalent in CSS.
There has been some movement to handle CSS layout in JavaScript (running in a service worker, so that it cannot have state, but otherwise fully in sync with the layout), as part of the “Houdini” effort: https://www.w3.org/TR/css-layout-api-1/
(Disclosure: I work on the style team in Chromium)
I don't understand either one. I use React (while technically pure JS, I assume this isn't what you mean) and calculate most of the sizes manually, just passing width and height as props into my elements. People tell me that's dumb, but it's always worked, and I don't have to keep up with this topic of CSS that doesn't really interest me. I've tried the "correct" flexbox way too, and it wasn't easier.
One particular thing about CSS... <img> seems to never behave in any kind of auto-sizing container the same way a regular div would; it seems to need pixel dimensions to work as expected in all scenarios, especially when things are resizing dynamically. Idk how other people deal with that. That alone was my motivation for trying things my own way.
I did something similar developing an app long ago for the iPhone 4. Calculated all my dimensions in C macros cause AutoLayout made no sense. Tons of apps using AutoLayout broke anyway when the new screen sizes came out, but my app was fine. "Math is math."
For img you set one of width/height attributes on the image or the aspect ratio CSS property (for page stability during early loading, actual dimensions are preferred), then max-width: 100%; height: auto to scale according to horizontal
space, or max-height:100%; width:auto to scale according to vertical space.
The additional complexity of images is that you nearly always want to maintain the aspect ratio, whereas a p or a div can be a radically different shape depending on the amount of content and viewport size and only have issues at the extremes (like very long lines at 4k@1x, or one word per line at high zoom)
I'll have to set up my sandbox in React again to find the exact problem. I wanted it to do what most would expect: img should size like a flexbox'd div and display the image with the original aspect ratio, either zooming or adding blank area to fit, depending on the use case. This div's width and height might be resized as the outer divs respond to changes. Should be easy.
Naturally I first tried making an outer flexbox'd div then putting a {width: 100%, height: 100%} img inside that with whatever fit option. And several variations on that, including the "width: auto" or "width: 0" tricks. Somehow it'd always either go outside the div boundaries or exhibit some other glitchy behavior. On top of that, there's the issue you mentioned where the image isn't loaded yet, causing funky resizing beforehand. You're simply better off with exact pixel dimensions.
There are tons of SO questions from confused individuals in my same situation, all with different answers that only work in certain scenarios. For example https://stackoverflow.com/a/21103679 which only works for auto-resizing the width, not the height. I think your suggestion has a similar caveat.
Meanwhile for me CSS is like the MS Word memes. Things that worked just break one day, certain options make other seemingly compatible options do nothing, and some settings just don't do what you'd guess from their name.
Almost everything can be made to look correctly but somehow the right solution is the last one I'd ever think of.
I used CSS tooling like LessCSS and SASS for years before switching back to regular CSS because I too wanted to simplify the build process (i.e. by not having one), and I found I didn't really miss the nesting so much. Mostly I solved it by writing things fairly concisely as:
A bit of an unconventional way to write it, but I found it really helps keeping a bit of overview because so much more fits on your screen, and because CSS is fairly simple the extra density doesn't hurt readability all that much IMO.
The biggest thing I missed was variables; but that's been solved now.
Now I just want line comments (// ..). I dislike /* .. */ comments with a passion.
I feel like the more typical reality is an exec looking at the site on some random browser or device, that then has to be in the support matrix, e.g. an enterprise business web app that supports the most recent 2 versions of modern desktop browsers...and the Silk browser for Kindle Fire because that's what's on the CEO's coffee table.
As a person who had to make some custom newsletter compatible with IE8 few years ago, for the 1% who still used it but among of them some were the most important investors, I feel this.
I mean, I get what you're saying, but for a company with critical branding needs, they will absolutely be concerned by this. In many instances they might even notice themselves. Sure, your average software company CEO won't care, but if you're in the food and bev business, or a design firm, or a game developer, the execs are keenly aware that micromanaging their public image is essential. That's why they spend millions of dollars for logo redesigns, or in a more extreme case, spend a huge chunk of change to make their own sliiiightly different version of Helvetica like Target did.
I was not possible to use a CSS variable to change the highlight colour of a checkbox, as far as I'm aware. You can use a CSS variable to set the accent-color, though.
(The workaround was creating a fake element that looked like a checkbox that overlapped the actual checkbox.)
Right, my point is, we've now introduced this new attribute for "browser elements" instead of saying now checkboxes support background-color, color, etc. And let the designer do the work.
Lean on the primitives we already have, enable flexibility, and if someone wants to make a SaSS wrapper or CSS function to do it, enable that vs. more random places for browsers to diverge on "standards".
It plays out like this:
"Oh, I wanna change the UI element style, thats a new feature! Accent-color! Nice. Oh wait, browsers are doing different things. Dang. Am I okay with that? vs. "I wanna change a UI element style, Oh, browsers now support classic CSS styling attributes on these elements! Nice! Designers sets colors, all browsers just read the designer's palette.
Changing the behavior of existing attributes isn't backwards compatible. Websites that currently use background-color & color assuming that it won't affect the accent color will suddenly look different when new browser versions make it affect the accent color.
i believe the problem with form elements like checkboxes is that they are 'replaced elements', which the browser defers to the underlying operating system, and that's why it requires a "hack" like accent-color rather than direct styling. this is also why you can't use ::before and ::after on form elements (to do things like add a 'required' indicator using css only).
IIRC they used to, but not anymore. They're implemented with a special Shadow DOM that's not accessible by the page but you can style some elements if the browser exposes them as psuedoelements.
are OG form elements actually reimplemented in shadow DOM, like they're doing with open UI (https://open-ui.org/) custom elements?
i've seen safari and chrome (but not firefox) expose some form input components as shadow DOM (e.g., slots), but wasn't sure if it was actually reimplemented.
Yep, there are settings to show them in the devtools for both Chrome and Firefox. You can't access them with JS though, you can only see them in the devtools.
> The workaround was creating a fake element that looked like a checkbox that overlapped the actual checkbox
There is also a newer workaround by styling the input element it self by using appearance: none. You can do some clever stuff with the :checked selector, multiple backgrounds, clip-paths, masks, etc.
I don't know if a single addition is enough reason to claim that the entire language has jumped the shark - but I was also wondering how this is different than a variable.
For this? No. Years ago we were working on a project and the default color of the form elements was a real sticking point. For some of them we ended up rolling our own, but others we just suffered with the default. Accent-color would have solved a problem we spent months working on and agonizing over.
If you were able to style the element with "classic" CSS primitives like border/background/color would that not have also solved the problem without introducing new syntax with new quirks?
I've done this before. The problem is a lot of elements will change to a different (standard?) appearance when you add styles like that, so you'd need to recreate the original look if you wanted to just change the color. Also, each browser has different psuedoelements so you have to support firefox and webkit separately, which is made worse by the fact that webkit doesn't support targeting multiple elements with your psuedoelement selector, ex. you can't do this:
For what it’s worth, having forms work the same across browsers is something Apple, Google and Mozilla are working on for Interop 2022: https://wpt.fyi/interop-2022
Looks like they're mostly working on making the appearance property work the same across browsers, they aren't actually standardizing the shadow dom used to render the elements.
I guess all these additions are incentivized by google etc loving the fact that it makes the moat to make competing browsers wider and wider. Imagine trying to make a new browser from scratch in 2022 and supporting the 20+ years of bloat like this (not to mention future plans).
I write complex web apps and hit the limits of CSS every day. My apps are written in a way that allows easy changing of themes and `accent-color` particularly can greatly simplify my theme management system.
I'm super excited for some of these additions. Perhaps they are meant for designer-developers such as myself and not for the casual CSS developer who doesn't already reach for existing advanced features.
Make no mistake: dialog element is there only because browsers (and Chrome, first and formost) want to remove alert/prompt.
dialog was so problematic that the same people that are now promoting it were in favor of removing it entirely. Literally none of the issues were solved, but now it's a great new element that we all should use.
Dialog is fine, but what I’m most excited is the upcoming Popup API. The finest part is that “the most recent popup gets the top-most layer”. You never have to fight z-index again because popups now live in a compositing layer outside the document itself (even though they’re still part of it), akin to position:fixed but without the conflicts.
I think I don't need the 2022 version, but the 2021 version. Or even the 2012 version, lol!
I still prefer to use tables to layout my websites.
Question: Say I want a layout that has a top row, a middle row and a bottom row. Each row gets 33% of the screen space. Unless the content does not fit. Then the row should expand to the content.
Hey there, I thought about this for a little bit because I find table layouts more pain than they are worth and the secret sauce that's missing from the examples above is nesting!
Just like Tables have <table> and then <tr> - your div's need a similar parent-child relationship to work.
CSS Grid. It’s a mostly simple spec that allows for what you’re asking for and a whole bunch more (including different grids for different screen sizes, which tables definitely don’t do). Probably start with https://css-tricks.com/snippets/css/complete-guide-grid/
Grid tracks (rows and columns) can be content sized. You just have to set the dimensions to something other than a concrete size (you have used `33vh` here). See the auto, min-content, max-content and fit-content values for height/width (https://developer.mozilla.org/en-US/docs/Web/CSS/height). You can get close to table-like behaviour by setting the height to `fit-content(33vh)`. There is also a minmax function which allows you to set minimums and maximums and have it content size between that.
One of the nice things about grid is that you can size the tracks on the parent element, and all you have to do on the children is specify which rows/columns they span. It works much better when you want to do the sort of things you use rowspan and colspan for with tables.
EDIT: Setting height: 100% was also preventing the grid from expanding. Try this JSFiddle https://jsfiddle.net/c3m2194b/
This is an issue I've run into a lot. Well the opposite, when I want overflowing grid cells to gain a scroll bar instead of expanding the parent. Turns out this is only doable if the grid element has an explicitly defined height, which means hard-coding a height like `height: 50vh` or ensuring every ancestor of the grid has `height: 100%` defined, which is pretty gross.
Having `height: 100%` (or `flex: 1` or grid equivalent) on every ancestor is just what you have to do for CSS (it applies to all layout modes, not just grid). My way to make this less painful is generally to remove any extraneous divs and try to keep the trees as shallow as possible.
Absolutely perplexed by the other answers that think CSS grid is a hammer for every nail. In your example without a table, you can just drop `display grid` and set `div {min-height: 33vh}`.
Also they both break pretty badly if you put some content so long that would require an automatic line-break (make sure you scroll to the right to see) With flexbox the content overflows outside of the container, but it preserves the sizing of the other elements. Table expands the whole container but in doing so ruins the other two rows.
But now I'm on a wide screen and want the lower two containers side-by-side with the top element spanning across the top. You can't do that with tables.
CSS keeps getting larger and larger which I think on its face is actually fine, since all of the standards are extended modules. So if you think about it that way, as an implementor you can choose which standards you want to incorporate and have total coverage for particular parts of the spec.
But the state of CSS for implementors is still abysmal, in my opinion, and I'd like to see more of the spec formally defined for some of the most fundamental parts of it.
It would be nice if the spec matured for implementors, too.
Like, could we please get a formal definition of the CSS processing model? The lack of one means that particular events MAY OR MAY NOT exist in user agents.
Those events may exist in large implementations--and when a CSS standard eventually pops up to utilize those vendor specific events, some implementations may not even have them, because they process CSS in an entirely different way!
As someone who's recently been working on an implementation of CSS Grid, and reading through a lot of CSS specs, I completely agree. There's a lot that isn't in the specs. The CSS Grid one isn't even that bad, but the spec for "flow layout" (block and inline) looks like a complete mess.
I'm hysterical about the state of affairs for these exact sorts of things, but comparatively almost no one is an implementor, so most people have no idea how bad it can be.
Yes, but the fact that someone had to do this makes it clear that the spec isn't complete. A complete spec would state the algorithm unambiguously. You might still need to fix bugs based on tests, but you shouldn't need to be working about behaviour because it's unspecified.
Not my experience at all. It doesn't matter how well written a spec is. No tests = no conformance. End of story. Most people can't hold an entire spec in their head or think through all the ramifications of the edge cases. Even the spec writers. I work on several specs. I work with people who work on specs. They're all mortal. No test = divergence. Always and without fail.
There may be layout tests for flexbox (I haven't looked into them, because I don't care about them as much as normal flow) but there are basically no layout tests for CSS 2.1 that aren't fully manual.
So basically for 25 years, as far as I understand, no one said, hey given a set of known layout constraints and rasterization parameters, let's create automated tests.
For 25 years.
Maybe I'm wrong, but I keep looking for these tests and the ones that exist for normal flow are a nonstarter.
This is why, I can only assert I can do "fullstack" for native applications on Windows and Android, for web development I am certainly on backend side, no way I can keep track of what CSS works where, and which incantations to make divs behave like native controls.
It's also nearly 100% guaranteed that while people say they're a master at CSS, there are probably only a miniscule amount of people who have read how CSS rasterizers actually work.
I'd almost bet there are probably more people who have reimplemented OpenGL in software than people who have read and understand how CSS compositors work.
For example, if you asked someone how user agents create backing tiles for CSS, they'd look at you like you spoke in a foreign language.
You totally don't need to know this stuff, but if you were doing say, high-perf UIs in WebKit (iOS), you'd probably at least want to know how to hint to WebKit that something needs its own render target or how to minimize subtree redraw.
I built massively performant large UIs for payroll systems on iPad years ago and found that if you optimized your UI just right, you could get smooth scroll performance that showed cracks in how fast the iPad was able to draw backing tiles at the time.
You'd get whole squares black scrolled into view while WebKit asynchronously drew in elements.
From recent(-ish) additions, the vh unit and flexbox were enormous help to me when I was designing a photography section for my personal website. From something older, which nonetheless helped and was new to me, were "display: inline-block" and "display: inline-block" (the concept of separated inside and outside display styles in general). Also "box-sizing: border-box", but at this point probably everybody uses it.
Feels like we only need this because cascading works less and less well once you start to include multiple frameworks or pieces thereof. At some point people find themselves in a jungle of !important. If you keep the cascade small and clean, you'll most likely not need that.
> Container queries
Probably the designs I have to implement are not complicated enough, but I could work very well with media queries so far.
Also this blurs the lines between markup and styling furthermore. Now you are defining IDs/classes in CSS which will make the code harder to debug.
> accent-color
Yeah, this is kind of nice. On the other hand we should not forget where the "this always gets styled by the system" comes from: Accessibility. With accent-color I can now totally easy screw up various kinds of inputs in the name of corporate design.
> Color level 4 and 5 & hwb()
Oh come on, this must be a joke. Color management is VERY hard to do, now we put more of that into CSS. But yes, advertisements can then be delivered with a wide gamut colorspace for more impact. Great.
> inert
What? This is just as bad as highjacking the scrollbar behaviour. Now you can make your website behave modal although there's no modal. Feels like another "right clicks are forbidden"-level when your paragraphs are set to inert and you can't interact with those anymore.
> Viewport units
More units of measurement is totally what CSS was missing. /s
> :has()
The parent selector looks like the only useful thing to me from that list. It will (theoretically) help clearing up the markup mess because you need less containers etc. if you want to style surrounding elements differently depending on their child content.
Container queries is a big deal in my opinion! This has always been an obstacle for designing responsive components - they only respond to the size of the screen so designing them for use in different places in your app is difficult.
But the implementation they’ve chosen with named containers is not my favorite. I’d prefer one that is simply based on the parent component or the closest component with a container attribute set; this would work better alongside tools like Tailwind and CSS-in-JS.
Edit: Nvm after reading more, it looks like the container name is optional and the default behavior is what I described - excellent!
Yeah container queries are what I'm most excited about looking at this list. I was pretty bummed out to see they're only supported on 63.75% of browsers, and notably missing on most mobile browsers, where they'd be most useful.
Container queries allow devs to step away from the classic small, medium, large breakpoints for screen sizes and consider the best look for a certain component at different widths. This is much better because a component on screen can be affected by many different parent element’s breakpoints, so it’s hard to define when a screen size should affect a component. With containers, it’s very clear.
> [re: layers] If you keep the cascade small and clean, you'll most likely not need that.
Many of us are not in that state due to piles of tech debt. One of my work projects is modernizing a 20ish year old, 300 page php app, and the css tech debt is awful. We're all looking forward to layers for some sanity.
Inert is nothing new, you could already use pointer-events: none or tabindex or put a transparent div on top. This is just a better way to hint to the browser your intent, and for it to behave properly.
I recently implemented layers on my site https://daniel.do/ and honestly found it really helpful in terms of explicitly organizing specificity.
It also gives you a much clearer idea of where in your styling stack something is coming from.
> Container queries
Have you ever built a piece of functionality that goes on pages you don't control? For instance, I built software that displayed a map on people's pages. but I don't know the width of the map itself. They could be displaying it on the full width of their page or in a container. Media queries don't work in this scenario. Making the map correctly responsive forced me to use JavaScript to get the element's width.
The other solution people have for this is iframes, which suck too.
Just because you don't have a need for something doesn't mean nobody does.
10 years ago people said the same about the CSS3 changes.
I find most of this useless/overcomplicated. Who needs rounded corners? I like my png slicing. And what are box shadows anyway? There's nothing flexbox can do that I can't achieve with tables. Transitions are bad, transparency is for Apple fanbois, animations the devil's farts, and don't get me started on media queries. Phones should remain Nokia bricks.
This isn't even a straw man. Further down we're still having the tables vs CSS debate. I'm so happy we got all of the above and more and can't wait to see what's next.
I can only remember that we applauded CSS3. Rounded corners and shadows were crucial to implement the design of the day. Animations and transitions were lovely. It was an exiting time to make stuff.
:has() is my most anticipated as well. it has the biggest potential to not only simplify our html (e.g., divitis) but also remove the need for js compensations in many content-oriented sites. come on firefox, let's get :has() across the finish line!
container queries are also neat, but still rely on having a wrapper container, which isn't ideal--why can't i style the component itself based on its own calculated height/width rather than having to involve a parent element?
i'm still waiting for chrome to implement subgrid, which will simplify any kind of card-type layout.
i also wish we had native "mixins" (@apply had this potential, but it was removed from the spec), so we could have a bundle of styles we could inject into different declarations as a group. then you could have different sets of styles in orthogonal groups (layout, spacing, border, text, inline) that you could apply in any combination. this is especially useful if you want to style a base html element a certain way and then also have a utility class with the same style later in the stylesheet (with maybe a slight tweak) that can be applied to more than just that type of element (like <div>s, <article>s, and <section>s).
edit: oh, and lch/oklch for more perceptually uniform and expanded colorspaces, combined with the new color functions (e.g., color-mix) is exciting too.
The majority of items mentioned in the article are still in the earliest stages of the standardisation process and haven't even had their specifications finalised yet (see overview at https://www.w3.org/Style/CSS/current-work).
Having access to these cool new features so early on is nice, of course, but be ready and willing to deal with possible breaking changes or even future removal.
Here's a recent example of once such breaking API change in the `:has()` selector spec being discussed on the Firefox tracker: https://bugzilla.mozilla.org/show_bug.cgi?id=418039#c44. It will be interesting to see how the other browsers that have already released the outdated implementation to production deal with this.
The reality is that W3C and Mozilla do not matter anymore. I'm not saying this because I like it, I'm saying this because it's the obvious state of things. Google controls the standards and protocols for the Web.
Sure, as standalone new CSS features look very useful, but when you start combining everything into one stylesheet it might quickly become hardly readable spaghetti code.
Can't believe paged media isn't really supported yet. Trying to do anything like line numbers for legal documents or page numbers is an absolute nightmare.
Page media has been supported for decades. Line numbers aren’t strictly related to page media. It’s hard to complain about the lack of in-depth support for a media that isn’t meant to display “the web”.
I do agree that it could be better. They have been adding print-related features though, at least I remember some in CSS3. CSS Colors Level 4 includes cmyk functions.
I don't think "it isn't meant" is accurate anymore. The browser has become meant for all things including document creation and styling. The @page counter feature although documented isn't supported by any browser from what I can tell at this point.
I only knew 13 of 54 (24%) which is a huge surprise, I've been writing CSS for 26 years. I guess I have fallen further behind on modern CSS than I thought. Seems like there's some other cool stuff to learn!
I recently tried the new Layer feature and I really like it. We're finally getting stuff that has been needed for years, like custom scoping support. I think it will take CSS out of JS.
i, for one, am most looking forward to full support of subgrid - pure css masonry/isotope layouts with no JS needed when your cell requires images to retain a certain aspect ratio, as well as span multiple rows/columns, but has accompanying text that can vary in height. am aware that's a very specific thing, but will be nice to not need a JS crutch for height calculation
Is there any work on updating CSS browser defaults? Even if it must be opt-in to keep backwards compat, having the possibility of starting any css file with 'use-defaults: 2022;' or something like that would be great.
I would love an option to opt into something like "reader mode" but maybe not quite so restrictive. (I can use some custom CSS to highlight code and some JS for interactive examples.
Right now I need to worry about the user's contrast preferences, light/dark preferences. Decide if I want to force a decent font or end up with the user's default (which probably sucks). I need to decide the text size (because their default probably sucks) and decide how wide the reading area should be.
What a mess to try and just pick something that the user wants.
As CSS gets bigger and more needlessly complex, I wonder if people start writing compile-to-CSS languages that aren't just supersets of the status quo.
I could imagine (and I think I am possibly observing) CSS going a similar direction to JavaScript; we might soon see the CoffeeScript of CSS, and then eventually something more sophisticated and well-designed like the Elm of CSS.
CSS — like JavaScript — might become the styling bytecode of the web.
Is it really "needlessly" complex if this is enabling styling that wasn't possible before?
Re your second point that CSS might become a compilation target for styling... have you never heard of Sass, Less, Tailwind, or any of a million UI frameworks that provide alternative ways to write CSS, or even avoid writing it directly altogether? This isn't exactly new.
> Is it really "needlessly" complex if this is enabling styling that wasn't possible before?
Many newer features that have been added over the years don't actually enable anything new. Not that I'm arguing in favour of table-based layouts either.
> have you never heard of Sass, Less, Tailwind, or any of a million UI frameworks that provide alternative ways to write CSS, or even avoid writing it directly altogether? This isn't exactly new.
I have written CSS in a serious capacity for several years. I am more than familiar with Sass, Less, etc., which is exactly why I wrote "languages that aren't just supersets of the status quo".
How do you propose we get to such a language that is more than a superset of the status quo if CSS, the compilation target itself, is severely limited?
I'm guessing you aren't writing binary in your day to day work, are you? I'm fairly certain whichever language you're working with is more featureful and ergonomic than working directly in binary.
Similarly, Elm has a different surface area from JavaScript, and yet JavaScript is the compilation target.
CSS doesn't need to be featureful to be a compilation target.
The fragment identifier links in the table of contents need to have parenthesis () removed because right now they're not matching the ids in the section headings.
:has() basically removes the need for us to use JS to attach classes to parent elements as we can essentially look ahead now, e.g. ".some-component:has(.input-select-all:checked) { background: blue }" whereas we would have to use JS to query the input, then query the parent and attach some css class as a styling hook.
Container queries will allow us to fine-tune the not-so-predictable gaps between our predictable breakpoints. Breakpoints will probably still be used for larger-picture layout, but container queries will help with the smaller parts especially in UI that have many moving dynamic parts.
The rest are just icing and honestly I wouldn't be surprised if it takes a while for many of them to become mainstream.
Interesting to see a lot of negative responses here. I'm quite excited for a large amount of these items.
@container queries are going to help a ton in making components more reusable - components that react to their own size rather than the browser size have been needed for a long time, and currently the only way to really do it is with the javascript observer api, which comes with huge performance tradeoffs.
Color-mix() is another item I've been wanting for some time, not because I need to mix things like red + blue, but because we've needed a native way to add opacity to css variables for a long time now. Having opacity be independent means we can have a robust design system that doesn't expand exponentially, while still providing opacity levels when needed.
Masonry layouts will greatly simplify a very common use case, color level 4 and 5 will make the web more dynamic and beautiful, and loosely typed properties will help add fallbacks. Definitely excited for these changes.
AFAICT a lot of the negativity comes from developers who want to work at a component UI Kit level you can find in native dev but don't find libs/kits that accommodate this well.
I don't think this is a failure of CSS -- I think CSS has turned out to be brilliant with some blind spots and part of the most spectacularly flexible UI layer that's ever been created. But it works at a lower level and leaks easily and that plus some cultural factors has generally pulled people towards a below-component development focus lots of devs would rather have abstracted away.
Container queries are one of several things that can move the dev culture more towards component level.
I'm only negative that some of these, especially flexbox/grid, weren't in the standard from the start. Especially after the committee crapped on HTML tables so hard. Viewport units are another part of the standard that's about 24 years overdue at this point.
233 comments
[ 3.5 ms ] story [ 260 ms ] thread[0]: https://blog.openreplay.com/modern-css-selectors/
[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/:is
Vite takes care of the boring stuff, I can write vanilla CSS with nested declarations in it, and it just works.
edit: don't get me wrong, i'd love to be 100% native CSS, but there are some things where preprocessors shine
I wonder if it's just about how some people's brains are wired.
I grok CSS. I won't claim to know everything about it, but I'd say I'm 90% proficient and prefer it to JavaScript.
But I think this is because JavaScript somehow never fully made sense to me. I can read it and figure out what it's doing, but it was never intuitive to me the way CSS is.
I read comments on HN frequently from people who are good a JS, but can't deal with CSS.
I think it's just how some languages "click" with different people. Some are comfortable in Lisp, while others are AP/L, or Rust, or something else.
Perhaps it's good to have multiple ways to achieving the same thing, rather than obsessing about one perfect/standard/preferred/"best practice" way of doing things.
https://vanilla-extract.style
https://tamagui.dev
(Disclosure: I work on the style team in Chromium)
One particular thing about CSS... <img> seems to never behave in any kind of auto-sizing container the same way a regular div would; it seems to need pixel dimensions to work as expected in all scenarios, especially when things are resizing dynamically. Idk how other people deal with that. That alone was my motivation for trying things my own way.
I did something similar developing an app long ago for the iPhone 4. Calculated all my dimensions in C macros cause AutoLayout made no sense. Tons of apps using AutoLayout broke anyway when the new screen sizes came out, but my app was fine. "Math is math."
CSS handles it just fine. That's how they deal with it.
The additional complexity of images is that you nearly always want to maintain the aspect ratio, whereas a p or a div can be a radically different shape depending on the amount of content and viewport size and only have issues at the extremes (like very long lines at 4k@1x, or one word per line at high zoom)
Naturally I first tried making an outer flexbox'd div then putting a {width: 100%, height: 100%} img inside that with whatever fit option. And several variations on that, including the "width: auto" or "width: 0" tricks. Somehow it'd always either go outside the div boundaries or exhibit some other glitchy behavior. On top of that, there's the issue you mentioned where the image isn't loaded yet, causing funky resizing beforehand. You're simply better off with exact pixel dimensions.
There are tons of SO questions from confused individuals in my same situation, all with different answers that only work in certain scenarios. For example https://stackoverflow.com/a/21103679 which only works for auto-resizing the width, not the height. I think your suggestion has a similar caveat.
Almost everything can be made to look correctly but somehow the right solution is the last one I'd ever think of.
A bit of an unconventional way to write it, but I found it really helps keeping a bit of overview because so much more fits on your screen, and because CSS is fairly simple the extra density doesn't hurt readability all that much IMO.
The biggest thing I missed was variables; but that's been solved now.
Now I just want line comments (// ..). I dislike /* .. */ comments with a passion.
https://web.dev/state-of-css-2022/#accent-color
Sure it's a "nice to have" but it bloats the spec? Look at the current actual implementation:
https://web.dev/accent-color/#guaranteeing-contrast
chrome and firefox already tint differently...
How is this better than a good ol CSS variable and leaving it up to the designer to manage?
Sure http://dowebsitesneedtolookexactlythesameineverybrowser.com/ but when the exec is like "why is our brand color slightly different on ff vs. chrome... we are back to square one.
"Disregard logic, acquire funds" - Ducreux
(The workaround was creating a fake element that looked like a checkbox that overlapped the actual checkbox.)
Lean on the primitives we already have, enable flexibility, and if someone wants to make a SaSS wrapper or CSS function to do it, enable that vs. more random places for browsers to diverge on "standards".
It plays out like this:
"Oh, I wanna change the UI element style, thats a new feature! Accent-color! Nice. Oh wait, browsers are doing different things. Dang. Am I okay with that? vs. "I wanna change a UI element style, Oh, browsers now support classic CSS styling attributes on these elements! Nice! Designers sets colors, all browsers just read the designer's palette.
i've seen safari and chrome (but not firefox) expose some form input components as shadow DOM (e.g., slots), but wasn't sure if it was actually reimplemented.
There is also a newer workaround by styling the input element it self by using appearance: none. You can do some clever stuff with the :checked selector, multiple backgrounds, clip-paths, masks, etc.
If you were able to style the element with "classic" CSS primitives like border/background/color would that not have also solved the problem without introducing new syntax with new quirks?
I'm super excited for some of these additions. Perhaps they are meant for designer-developers such as myself and not for the casual CSS developer who doesn't already reach for existing advanced features.
dialog was so problematic that the same people that are now promoting it were in favor of removing it entirely. Literally none of the issues were solved, but now it's a great new element that we all should use.
I still prefer to use tables to layout my websites.
Question: Say I want a layout that has a top row, a middle row and a bottom row. Each row gets 33% of the screen space. Unless the content does not fit. Then the row should expand to the content.
Here is the table version:
https://jsfiddle.net/vg2ey8r9/
How do you do that without a table?
https://jsfiddle.net/3hfosn5k/
Scroll down and you will see that the blue color of the bottom row ends and the text overflows it.
But I want what table cells do: Expand if their content is too large to fi.
https://jsfiddle.net/y15qszjp/
Just like Tables have <table> and then <tr> - your div's need a similar parent-child relationship to work.
Here's a working fiddle: https://jsfiddle.net/0389jsca/
When I try, I don't get the nice behavior of tables, but a stiff layout that does not adapt to its content. Instead the content overflows the rows:
https://jsfiddle.net/3hfosn5k/
The nice thing about tables is that I know the table cells will always surround their content. Nothing will flow out of the cells.
One of the nice things about grid is that you can size the tracks on the parent element, and all you have to do on the children is specify which rows/columns they span. It works much better when you want to do the sort of things you use rowspan and colspan for with tables.
EDIT: Setting height: 100% was also preventing the grid from expanding. Try this JSFiddle https://jsfiddle.net/c3m2194b/
Yep, it's nice to have an alternative to flex (where children determine their own size with flex-grow / flex-shrink / flex-basis).
> Setting height: 100% was also preventing the grid from expanding. Try this JSFiddle https://jsfiddle.net/c3m2194b/
This is an issue I've run into a lot. Well the opposite, when I want overflowing grid cells to gain a scroll bar instead of expanding the parent. Turns out this is only doable if the grid element has an explicitly defined height, which means hard-coding a height like `height: 50vh` or ensuring every ancestor of the grid has `height: 100%` defined, which is pretty gross.
https://jsfiddle.net/36k1079x/
The border still kind of looks better on the table one, it's like the flexbox border is not the same size vertically and horizontally.
Once you add enough text that they need to re-shape, they both behave differently. I kind of like the look of the flexbox one better though.
Table https://jsfiddle.net/gs73eyd5/1/
Flexbox https://jsfiddle.net/g4qv2dr6/2/
Also they both break pretty badly if you put some content so long that would require an automatic line-break (make sure you scroll to the right to see) With flexbox the content overflows outside of the container, but it preserves the sizing of the other elements. Table expands the whole container but in doing so ruins the other two rows.
https://jsfiddle.net/ysu7fgk1/ vs https://jsfiddle.net/q6dcph0x/
And that request will come.
https://i.imgur.com/K1gOKGL.png
But the state of CSS for implementors is still abysmal, in my opinion, and I'd like to see more of the spec formally defined for some of the most fundamental parts of it.
It would be nice if the spec matured for implementors, too.
Like, could we please get a formal definition of the CSS processing model? The lack of one means that particular events MAY OR MAY NOT exist in user agents.
Those events may exist in large implementations--and when a CSS standard eventually pops up to utilize those vendor specific events, some implementations may not even have them, because they process CSS in an entirely different way!
An HTML5 moment for CSS would be very welcome.
I'm hysterical about the state of affairs for these exact sorts of things, but comparatively almost no one is an implementor, so most people have no idea how bad it can be.
https://yogalayout.com/
So basically for 25 years, as far as I understand, no one said, hey given a set of known layout constraints and rasterization parameters, let's create automated tests.
For 25 years.
Maybe I'm wrong, but I keep looking for these tests and the ones that exist for normal flow are a nonstarter.
I'd almost bet there are probably more people who have reimplemented OpenGL in software than people who have read and understand how CSS compositors work.
For example, if you asked someone how user agents create backing tiles for CSS, they'd look at you like you spoke in a foreign language.
You totally don't need to know this stuff, but if you were doing say, high-perf UIs in WebKit (iOS), you'd probably at least want to know how to hint to WebKit that something needs its own render target or how to minimize subtree redraw.
I built massively performant large UIs for payroll systems on iPad years ago and found that if you optimized your UI just right, you could get smooth scroll performance that showed cracks in how fast the iPad was able to draw backing tiles at the time.
You'd get whole squares black scrolled into view while WebKit asynchronously drew in elements.
https://www.w3.org/Style/CSS/Test/Overview.en.html
https://web-platform-tests.org/
better specs are great, but tests will actually find the edge cases and lead to more convergence.
> Cascade layers
Feels like we only need this because cascading works less and less well once you start to include multiple frameworks or pieces thereof. At some point people find themselves in a jungle of !important. If you keep the cascade small and clean, you'll most likely not need that.
> Container queries
Probably the designs I have to implement are not complicated enough, but I could work very well with media queries so far.
Also this blurs the lines between markup and styling furthermore. Now you are defining IDs/classes in CSS which will make the code harder to debug.
> accent-color
Yeah, this is kind of nice. On the other hand we should not forget where the "this always gets styled by the system" comes from: Accessibility. With accent-color I can now totally easy screw up various kinds of inputs in the name of corporate design.
> Color level 4 and 5 & hwb()
Oh come on, this must be a joke. Color management is VERY hard to do, now we put more of that into CSS. But yes, advertisements can then be delivered with a wide gamut colorspace for more impact. Great.
> inert
What? This is just as bad as highjacking the scrollbar behaviour. Now you can make your website behave modal although there's no modal. Feels like another "right clicks are forbidden"-level when your paragraphs are set to inert and you can't interact with those anymore.
> Viewport units
More units of measurement is totally what CSS was missing. /s
> :has()
The parent selector looks like the only useful thing to me from that list. It will (theoretically) help clearing up the markup mess because you need less containers etc. if you want to style surrounding elements differently depending on their child content.
But the implementation they’ve chosen with named containers is not my favorite. I’d prefer one that is simply based on the parent component or the closest component with a container attribute set; this would work better alongside tools like Tailwind and CSS-in-JS.
Edit: Nvm after reading more, it looks like the container name is optional and the default behavior is what I described - excellent!
Many of us are not in that state due to piles of tech debt. One of my work projects is modernizing a 20ish year old, 300 page php app, and the css tech debt is awful. We're all looking forward to layers for some sanity.
(strong agree on your other points)
It also gives you a much clearer idea of where in your styling stack something is coming from.
> Container queries
Have you ever built a piece of functionality that goes on pages you don't control? For instance, I built software that displayed a map on people's pages. but I don't know the width of the map itself. They could be displaying it on the full width of their page or in a container. Media queries don't work in this scenario. Making the map correctly responsive forced me to use JavaScript to get the element's width.
The other solution people have for this is iframes, which suck too.
Just because you don't have a need for something doesn't mean nobody does.
I find most of this useless/overcomplicated. Who needs rounded corners? I like my png slicing. And what are box shadows anyway? There's nothing flexbox can do that I can't achieve with tables. Transitions are bad, transparency is for Apple fanbois, animations the devil's farts, and don't get me started on media queries. Phones should remain Nokia bricks.
This isn't even a straw man. Further down we're still having the tables vs CSS debate. I'm so happy we got all of the above and more and can't wait to see what's next.
In OP's defense, I still say those things about the CSS3 changes.
container queries are also neat, but still rely on having a wrapper container, which isn't ideal--why can't i style the component itself based on its own calculated height/width rather than having to involve a parent element?
i'm still waiting for chrome to implement subgrid, which will simplify any kind of card-type layout.
i also wish we had native "mixins" (@apply had this potential, but it was removed from the spec), so we could have a bundle of styles we could inject into different declarations as a group. then you could have different sets of styles in orthogonal groups (layout, spacing, border, text, inline) that you could apply in any combination. this is especially useful if you want to style a base html element a certain way and then also have a utility class with the same style later in the stylesheet (with maybe a slight tweak) that can be applied to more than just that type of element (like <div>s, <article>s, and <section>s).
edit: oh, and lch/oklch for more perceptually uniform and expanded colorspaces, combined with the new color functions (e.g., color-mix) is exciting too.
You’re complaining about the mere availability of color functions, that alone kills the rest of the comment.
Letting the world's largest advertising corporation be in charge of browser standards is probably not the best idea.
Having access to these cool new features so early on is nice, of course, but be ready and willing to deal with possible breaking changes or even future removal.
Here's a recent example of once such breaking API change in the `:has()` selector spec being discussed on the Firefox tracker: https://bugzilla.mozilla.org/show_bug.cgi?id=418039#c44. It will be interesting to see how the other browsers that have already released the outdated implementation to production deal with this.
If only for some presentational aspect of an internal design system I’m building, it’s a dream come true.
I think only Firefox is without.
I do agree that it could be better. They have been adding print-related features though, at least I remember some in CSS3. CSS Colors Level 4 includes cmyk functions.
Feels like we’re stuck in a “yes, it meant to be a universal platform” / “no, it meant to be a document viewer” loop.
(and was posted a number of times then)
What might be more interesting if it's your area is the currently running State of CSS Survey https://stateofcss.com
Right now I need to worry about the user's contrast preferences, light/dark preferences. Decide if I want to force a decent font or end up with the user's default (which probably sucks). I need to decide the text size (because their default probably sucks) and decide how wide the reading area should be.
What a mess to try and just pick something that the user wants.
I could imagine (and I think I am possibly observing) CSS going a similar direction to JavaScript; we might soon see the CoffeeScript of CSS, and then eventually something more sophisticated and well-designed like the Elm of CSS.
CSS — like JavaScript — might become the styling bytecode of the web.
Re your second point that CSS might become a compilation target for styling... have you never heard of Sass, Less, Tailwind, or any of a million UI frameworks that provide alternative ways to write CSS, or even avoid writing it directly altogether? This isn't exactly new.
Many newer features that have been added over the years don't actually enable anything new. Not that I'm arguing in favour of table-based layouts either.
> have you never heard of Sass, Less, Tailwind, or any of a million UI frameworks that provide alternative ways to write CSS, or even avoid writing it directly altogether? This isn't exactly new.
I have written CSS in a serious capacity for several years. I am more than familiar with Sass, Less, etc., which is exactly why I wrote "languages that aren't just supersets of the status quo".
I'm guessing you aren't writing binary in your day to day work, are you? I'm fairly certain whichever language you're working with is more featureful and ergonomic than working directly in binary.
Similarly, Elm has a different surface area from JavaScript, and yet JavaScript is the compilation target.
CSS doesn't need to be featureful to be a compilation target.
Container queries will allow us to fine-tune the not-so-predictable gaps between our predictable breakpoints. Breakpoints will probably still be used for larger-picture layout, but container queries will help with the smaller parts especially in UI that have many moving dynamic parts.
The rest are just icing and honestly I wouldn't be surprised if it takes a while for many of them to become mainstream.
The major browsers (Chrome, Edge, Safari, Opera) support it except for Firefox, which has it behind a flag still. ~76% of users are covered.
:has() CSS relational pseudo-class - https://caniuse.com/css-has
- 4 months ago Chromium enabled :has() selector by default
- 3 months ago, CCS Working Group made a small design decision ("resolution") which may affect how Firefox implements it
- 22 days ago: "has() implementation is experimental, that's why it's not enabled anywhere by default."
I think the good news is that it's in active development, and seems fairly close to release.
Bugzilla: Implement the :has() pseudo class - https://bugzilla.mozilla.org/show_bug.cgi?id=418039
So basically not supported, and you have to go back to div hell.
There should be some future.js file that you can import to make all this stuff just work in older browsers.
I've been using if for months with no issues in cross-browser testing, and I haven't enabled any experimental flags.
@container queries are going to help a ton in making components more reusable - components that react to their own size rather than the browser size have been needed for a long time, and currently the only way to really do it is with the javascript observer api, which comes with huge performance tradeoffs.
Color-mix() is another item I've been wanting for some time, not because I need to mix things like red + blue, but because we've needed a native way to add opacity to css variables for a long time now. Having opacity be independent means we can have a robust design system that doesn't expand exponentially, while still providing opacity levels when needed.
Masonry layouts will greatly simplify a very common use case, color level 4 and 5 will make the web more dynamic and beautiful, and loosely typed properties will help add fallbacks. Definitely excited for these changes.
I don't think this is a failure of CSS -- I think CSS has turned out to be brilliant with some blind spots and part of the most spectacularly flexible UI layer that's ever been created. But it works at a lower level and leaks easily and that plus some cultural factors has generally pulled people towards a below-component development focus lots of devs would rather have abstracted away.
Container queries are one of several things that can move the dev culture more towards component level.
Don't forget, the core of HTML and CSS until this day basically relies on "we can lay everything and display it in a single pass".
Double pass (for tables) didn't appear in standards until 2001 if I remember correctly (but won't be able to find).
And then you have the IE-era draught of no features.
- mixins. Like SCSS and SASS has had for a decade now. 'apply' was supposed to add mixins but 'apply' was cancelled in favour of 'part', and 'part' doesn't work. https://stackoverflow.com/questions/74097950/how-do-i-create...
That's actually it. We already have aspect-box, adding gradients for borders would be nice but I can live without them.