"The text content in the third box is longer than the available space, so rather than maintaining the aspect ratio, the element expands vertically to fit the content... If we set an explicit height instead, the element doesn’t expand, but instead we get overflow"
Why? Why would you have different default behaviours if you have one of the dimensions set but not the other? Why would you not have this specified in another property, the overflow property perhaps? Oh look, lets define a new property and call it aspect ratio, and then lets ensure it doesn't maintain an element's aspect ratio if you have content that is going to overflow if you specify a width. This is what drives me mad about css, it's gotchas all the way down.
> Why would you have different default behaviours if you have one of the dimensions set but not the other?
Basically: be there or be square (fill up the space or not, your choice), but if you show up there’s a dress code (you can only fill up the space as specified).
> Oh look, lets define a new property and call it aspect ratio, and then lets ensure it doesn't maintain an element's aspect ratio if you have content that is going to overflow if you specify a width. This is what drives me mad about css, it's gotchas all the way down.
There’s a lot I don’t like about CSS, but this is just the spec avoiding undefined behavior. No one is using aspect ratio for unbounded text in practice, they’re using it for media or a design system. Knowing how it behaves for edge cases is much better than having a protracted battle for years while vendors sort it out, with different assumptions in the wild.
To emphasize this point, the alternatives would be ridiculed:
- overflow is assumed by default and constraining it is a whole bunch of necessary compromises, so my element maintains an aspect ratio but its content is overlapping siblings with the same aspect ratio. What the hell were they thinking?
- my element with 16:9 aspect ratio and the full text content of Moby Dick serialized as JSON was so wide my browser ate all my memory and swap, locked my computer up forcing a hard reboot
> full text content of Moby Dick serialized as JSON
Reminds me of when YouTube added a new comment system, but didn't specify a max length, and rendered the full text by default. People were spamming the Bible in comments.
You could instead just define the edge case behaviour so it is sane and consistent, e.g Text always overflows unless otherwise specified, or text is always clipped, rather than "lets stop the thing doing what it says it's doing". I swear the CSS spec considers "insane by default" To be a feature.
The problem is that CSS is not (and continues not to be) designed to minimize such conflicting specifications, and does not provide a unified, explicit and systematic way to control conflict resolution.
It’s because there are 2 conflicting properties here: width and aspect-ratio. The user has set both. So when the content overflows, which one should be nullified? In this case they chose width to be maintained, and aspect ratio to be ignored.
If you want to maintain the aspect-ratio, just remove the explicit width. Then the box will be extremely wide and tall and will move to its own line. Probably not what the developer wants to achieve.
You could say that the default behaviour should be to clip the content, like overflow: hidden does. But in CSS, the content always has priority. And it will be (overflow:) visible by default. But as a user you can still choose to clip it (overflow: hidden), or make it scroll (overflow: scroll).
CSS has all the tools for you to choose the behaviour you want. And I think this aspect-ratio property is going to save me a lot of trouble.
I don't entirely understand this, but I think horizontal and vertical are often treated differently in CSS, yes? Like an item without width or height set will in some cases have width constrained by it's parent element, but height will not be (and can even cause parent element to grow). And I feel like it would end up weird and not what you wanted if it wasn't that way.
I may not have this exactly right, but i have an intuition that width and height are treated differently by CSS, and the aspect-ratio example is a consequence of some other fundamental rule/principle, not something unique to aspect-ratio.
Maybe someone else can explain this more specifically.
Because the convention is to scroll vertically and not horizontally, width is constrained but height is limitless in such a setup. Hence the differing treatment of width and height
> This is what drives me mad about css, it's gotchas all the way down.
And don't forget, every time a new half-baked shitty piece of the spec is added to poorly address something people have been complaining about for 15 years, tons of people will write articles (and these days go on Twitter) gushing over how amazing CSS is for granting these gifts from the gods.
Front-end really doesn't need to be as difficult to do day-to-day as back-end (concern balancing, i.e. perf vs storage vs cost vs fault tolerance vs maintainability vs monitoring vs etc, is the extremely difficult fundamental problem you always face in back-end/SRE/DevOps, but that's all mostly trivial in front-end, which is why being a React guru isn't anywhere near as rare as being able to scale a legacy PHP app to 1M DAU), it just has a lot of pointless complexity because these technologies are designed like absolute ass, and only inch forward by committee.
What you're overlooking is that CSS has to be backwards compatible to as great an extent as possible. It's not an option to abandon existing paradigms and what you perceive as "pointless complexity", because it would break the web. These things inch forward because they have huge ramifications for the internet.
Your rant about back-end/SRE/DevOps being inherently more difficult comes off as ill-informed. Where do you get the idea that balancing performance, cost, maintainability and monitoring are trivial on the front-end?
„my static blog and I cant get the text centered, damn css!“
instead of
„basically a full blown native application but written using browser APIs, with live collaboration features, GPU-using code where performance matters, oh and did i mention it must also work and look good on a mobile screen?“
Re: your second paragraph, I should have said "at scale".
I don't think I'm ill-informed, I've spent at least 5 years in each of front-end, back-end, and SRE/devops...I won't deny that there are some things that are really difficult on front-end (and in fact I don't like doing it because I don't find the challenges it offers very rewarding, though they take a lot of time), but in my experience, back-end is much, much harder at scale.
But the big distinction is that whereas frontend design/architecture/concerns are roughly the same no matter how many users you have, difficulty of back-end scales (about logarithmically) with traffic - 1k DAU is trivial, 100k is easy, 1M is "interesting", 10M is starting to get hard, 100M+ and you need to be top of your damn game (with a team to match) or you fail hard. Most projects don't have to ever reach the difficult regions, but to be perfectly honest my (non-side-project) backend work has all been in the large scale regime, so maybe for the average project across the industry the relative difficulty is about the same.
If you're in "git push heroku main" territory, then sure, frontend is probably a lot harder than backend.
To the first point, that's all fine and good, I think you're actually correct, I'm just tired of the fanboy-ism around CSS, and maybe I'm bitter because of how obnoxious the fanboys we're back when it was truly unusable. 10+ years ago there were people arguing vehemently that things like flexbox were completely pointless and in fact DANGEROUS because CSS was already perfect and could do anything as long as you weren't a noob, which was just ridiculous and wrong. I'll accept that things have gotten a lot better now and the stakes really are much higher w.r.t. changes.
CSS has always felt like a game of Q*bert to me, where you can't toggle one expected behavior without also affecting another unexpected behavior, and it's infuriating that this sort of thing persists into new specs.
The old answer, for those curious, was a padding-bottom with the aspect ratio expressed as a percentage: https://jsfiddle.net/9yLkm0tu/
This works because padding percentages are calculated based on width – making this, at the time, the only practical way to form a relationship between an element's height and width. Thierry Koblentz coined this "intrinsic ratios" back in '09: https://alistapart.com/article/creating-intrinsic-ratios-for...
Some people call it a hack – it's just a narrow application of the spec.
Oh, it has loads of issues, aspect-ratio is a gift from on high. Flexbox (and really non-block elements in general) is the least of intrinsic ratios' woes – requiring a wrapping element is likely the biggest.
This is really amazing. The last CSS thing I learned about was flex-box and it so vastly improved my side projects. I'm sure this will come quite handy too.
What are more such things which you love about CSS but only learned about recently? Can greatly benefit CSS dinosaurs like me who know CSS but haven't really kept up on the recent developments.
Personally I think the most useful 'new' things in CSS that hardly anyone uses yet are the min, max, and Clamp functions.
I wrote about them here https://blog.logrocket.com/min-max-clamp-css-functions/ - there are some real embarrassments in that article (probably due to me being busy with other things at the time of writing, and being outside my comfort zone [dealing with design]) - example silly statement: "these functions can accept anything that is a number or a calculable value, like the length of a variable, as an input." length of a variable? WTF did I write that for!?!
I could also probably have saved my time because the day after I finished writing it I found this post https://ishadeed.com/article/css-min-max-clamp/ which makes a lot of the same points, less verbosely, and better, with much nicer looking examples because I guess this guy has a design sense.
on edit: I mean I am just jealous of the examples he made, I sweated trying to make something up to show the power of the functions and explain their use and I don't think I did a good job of it, didactically, and his examples were really good. Probably he sweated to, but they look effortless.
Do these functions make min-width and min-height obsolete? Or is there still any reason to use those instead of min()/max()/clamp()?
Edit: just noticed the articles you linked have nice examples of combining the two (should've read first), and it makes perfect sense since min-width/min-height deal with how elements grow to fit their contents, while something like `width: clamp(...)` would be declaring the width instead.
they don't make them obsolete, but they do make them less important.
Without these functions people probably have more media queries with min-width min-height max-width max-height, with them maybe one or two without media queries is needed.
The reason to use `hover`, instead of `pointer` like a sibling comment mentioned, is for accessibility purposes:
> For accessibility reasons, even on devices that do support hovering, the UA may give a value of hover: none to this media query, to opt into layouts that work well without hovering.
no i mean that touch devices with a dedicated mouse can be detected as no-hover devices (usually laptops with touch screens)… which is often not desirable
Ah – I err on the other side (keeping things usable for touch input). Two sides to a coin! That is a useful thing to keep in mind when writing this though, good point.
I view this not as "unreliable for detecting touch screen laptops" but reliably detecting touch screens.
I think you're reading the comments backwards, maybe. A laptop that has a mouse and a touch-screen will in some cases NOT be detected as a touch screen. When you say that is "reliably detecting touch screens", I'm not sure if you're following. If that results in delivering your "not as usable for touch screens" UI, that is not "erring on the side of keeping things usable for touch input"
> A laptop that has a mouse and a touch-screen will in some cases NOT be detected as a touch screen
What you are saying here is the opposite of the comment that I'm replying to, and is the opposite of the W3 spec. Are you sure? micromacrofoot correctly said:
> touch devices with a dedicated mouse can be detected as no-hover devices
"no-hover devices" are AKA touch input devices, and will therefore satisfy the query `hover: none`. The spec says as such:
For example, on a touch screen device that can also be controlled by an optional mouse, the `hover` media feature should match `hover: none`, as the primary pointing device (the touch screen) does not allow the user to hover.
However, despite this, the optional mouse does allow users to hover. Authors should therefore be careful not to assume that the ':hover' pseudo class will never match on a device where 'hover:none' is true, but they should design layouts that do not depend on hovering to be fully usable.
I believe what I'm saying is the same thing and you are mis-reading.
> A laptop that has a mouse and a touch-screen will in some cases NOT be detected as a touch screen
You see the "NOT" in all capitals? "NOT be detected as a touch screen".
I said:
> A laptop that has a mouse and a touch-screen will in some cases NOT be detected as a touch screen.
That is the same thing, is it not?
Which is the same thing as you quoted from the spec.
> For example, on a touch screen device that can also be controlled by an optional mouse, the `hover` media feature should match `hover: none`, as the primary pointing device (the touch screen) does not allow the user to hover.
Right, so such devices will be detected as "NOT a touch screen".
I feel like I'm agreeing with the spec and agreeing with micromacrofoot, but you are for some reason still reading it in reverse.
If you detect something with both touch and a mouse as "NOT touch", and then deliver a UI optimized for "NOT touch", this is NOT "erring on the side of keeping things usable for touch input".
But this is now a super boring conversation! If this super boring pedantic explication doesn't get us anywhere else, nothing will, I give up!
Hey, no worries, it's not boring! Specs are just hard to parse. Pedantic is the name of the game with W3 :)
> Right, so such devices will be detected as "NOT a touch screen".
`hover: none` means it's a touch screen.
The idea being that the device shouldn't expect hover inputs. Hence "touch devices with a dedicated mouse can be detected as no-hover devices"
Paraphrased, the bit of the spec I quoted says "even if a touch laptop has a mouse, `hover: none` will still match". Here's a quick fiddle to show: https://jsfiddle.net/b2f69uya/
Ultimately: if you have a touch control as a device's primary input, there's a guarantee that `hover: none` will be satisfied.
> This media query has not yet been implemented and is currently only a proposed spec. I've written this post to raise awareness of it and get general thoughts about it.
Great to be aware of what might come, but.. it's not an option if it's literally just proposed.
CSS grids are a layout revolution. Quite difficult to learn, but very powerful. It may take years before the community understands all that it has to offer.
Container queries are a game changer, although not fully ready across browsers yet.
CSS variables have been around for a while now, but still considered fairly new. CSS nesting is also around the corner. When you combine these two things, you can start considering to drop CSS preprocessors like SCSS.
CSS layers is brand new and may be useful when working with design language systems.
And as an unimportant but fun last one: you can now address colors outside the RGB color space.
i guarantee the next thing you want to learn is `grid`. It takes a bit of time to get your head around, then you realize you can do just about anything, fluid-responsively.
I've stopped working on web projects about ten years ago and it's still shocking how much was missing from even the most basic things compared to other UI frameworks that often had it for decades.
It's quite sad that there's apparently no other direction than "JavaScript and the web will replace every type of application eventually". I mean look how well Microsoft Word (native) works compared to Microsoft Teams (some JS hodgepodge). And not just the day by day use, but also stuff like AppleScript support. Especially highlighted by the stand still we used to have on mobile computer CPU's until recently. Everything just got slower and slower.
Thank you for this comment. It's scary to think that majority of the tech-savvy people in the world never question sanity of web stack and don't see how badly it is unfit for making UI apps.
I switched to Flutter few years ago, and now making all apps with it (which gives web version out of the box along with native ios/android/linux/windows/mac). Hard to believe people still wasting their time on CSS/JS/HTML for new projects and call hacks like this "amazing".
aspect-ratio is actually a great mistake - it breaks CSS box model again (after flexbox).
What should be the dimensions of this
div {
width:100px; height:100px;
aspect-ratio: 3 / 2;
}
?
Instead, there should be "functions" width(N%) and height(N%) and so
div {
width:100px;
height: width(66%);
}
div {
height:100px;
width: height(150%);
}
div {
height:40px;
line-height: height(100%);
}
div {
width:100px;
margin: width(10%);
}
Therefore, instead of one more property that "solves" only one particular problem we will have bunch of solutions by adding just two pseudo-functions. And without breaking box model in very nasty way.
For that matter, Sciter (https://sciter.com) has these width()/height() functions 10 or so years already.
div {
width:100px; height:100px;
aspect-ratio: 3 / 2;
}
This is all well specified and doesn't "break" the box-model in anyway. Anytime there is a definite width/height specified the box well respect that width/height. The aspect-ratio is lowest on the constraint priority list if you like.
Internally in browser engines there was already an aspect-ratio for replaced elements, and these elements already had to (in a slightly different way) deal with width/height/min-width/min-height/etc. aspect-ratio was exposing and slightly generalizing what engines had already.
The example you give with allowing the width() function for margin, raises a lot of questions. E.g. you could have something like:
div {
width: auto;
margin: width(10%);
}
This gets into "difficult" territory very quickly (even more complex with calc/min/max/clamp/etc) as you'd need to try and solve a multi-variable equation. (Width depends on the size of the margins, and margins depends on the width).
`aspect-ratio` specifies the preferred ratio. It gets used in cases where sizing values are intrinsic.
In your first example, it would be overruled by the defined sizing values. I think that's fine, personally. Further, I don't see how it breaks the box model – esp. given that the spec that defines box model also defines `aspect-ratio`
Don't expose your CSS classes to spooky action at a distance. Use a build system or CSS in JS library to hash your class names and keep them private.
It's a terrible shame that CSS relies so heavily on globals (I'm looking at you, `@keyframes`), but as programmers we should all recognize them when we see it and avoid them by any means possible.
> Use a build system or CSS in JS library to hash your class names and keep them private.
Please don't. Human-readable and rarely changing class names are one of the few things keeping customization on the Web still possible.
Just add an application name class selector to the beginning of each style block (perhaps as part of your build so you can do it for dependencies too) and put those classes on your body. For bonus points, put those classes as deep in the tree as reasonable and you have yourself scoped styles - all with zero JS and compiler fuckery.
I've used this method to mix Bootstrap versions on one page as well as two completely different CSS frameworks. Obviously not something you want to do, but you might need to once in a while.
> instead of two properties that define box dimensions you now have now who knows how many props changing dimensions
For border-box block elements, height and width are still absolutes (notwithstanding min-/max- values of the same). Protesting other box models is absolutely doable: just don't use 'em. Principle of least astonishment accomplished.
Your "should be functions" suggestion is far more problematic than aspect-ratio.
div {
width:100px;
height:100px;
aspect-ratio: 3 / 2;
}
In your first example (shown above), aspect-ratio has a clear way to solve conflicts: aspect-ratio does not overwrite explicitly defined dimensions, it can only affect implicit dimensions.
Your suggested replacement does not. What happens in the case below?
div {
width: height(100%);
height: width(66%);
}
Problems with the function approach that I can think of off the top of my head:
1. There is no logical way to say that one function should override another in the case of circular constraints.
2. It relies on percentages instead of fractions, this leads to developers having to either needing to nest an extra calc function within to deal with a fraction, or rely on precomputed magic numbers which are never a good thing. The new aspect-ratio rule means new developers will never need to commit the fact that a height of 56.25% the width results in a 16:9 ratio. If we're using a fraction instead, why create two functions that fall prey to the other problems listed instead of just putting it on `aspect-ratio`.
3. Naming collisions. Something perhaps best avoided, lest we encounter strange lines like: `height: height(var(--height));
4. It relies on percentages for widths and heights. This is just going to add more even confusion about the conditions and gotchas pertaining to percentage units on the width and height properties. For example: `height: 56.25%;` sets its height based on the width of the element (unlike `width: 56.25%` which sets it width based on the width of its containing element) except in the cases of various `position: absolute;` and `position: relative;` caveats on the element in question and its parents.
5. It relies on using widths and heights instead of focusing on lengths along inline and block axes. What happens when the writing direction changes to vertical? Do the widths and heights switch or not?
The aspect-ratio approach is fine. In fact I'd go out of my way to say it's better than fine. All the problems of different approaches presented and debates held during the formation of the standard have resulted in a great css addition that removes many annoyances that developers have had with no additional downsides.
Of course it has spec. Just one more property in 200+ of them.
That is no-brainer to add new property ... Problem is that each property introduced that way ads new dimension in compatibility matrix.
Exactly. The aspect-ratio property works the same way as the padding hack does. It calculates the height based on the rendered width. You can't do it the other way around, even if using a different axis inside a flex or grid element.
You still can't have a div in the middle of the screen, which will have a maximum (intrinsic) width/height, a set aspect ratio, and which will respond to resizing the window vertically. It will simply overflow.
You have to be very careful around doing this. If the unit assigned to length variable changed from pixels to percentage, you may end up with unintended and hard to debug behaviour.
Look at points: 2, 4 & 5 on my comment here: https://news.ycombinator.com/item?id=30282458. Point 4 in particular since there are so many gotchas with percentage units. Someone else could change the styles for a different element and it would break your element's styles in a hard to debug way.
This has been one of my absolute favorite CSS improvements in recent years. Upon first seeing it people don't typically pick up on the magnitude of benefit that the feature offers. Once it sets in, however, you start seeing it everywhere. Image dimension management had been an enduring problem throughout CSS history but now aspect ratio is supported across the board https://caniuse.com/mdn-css_properties_aspect-ratio.
I have used aspect-ration in production and I concur. Say you want to display a user avatar, but the user might not have uploaded their avatar, so you fallback with a colored box (basically a div) with the user’s initials instead (or—in practice—your best guess of their initials). aspect-ratio will cover both of these. So you can you don’t need to set a different weight or padding depending of if you have an image or a div.
I'm so happy to see directives like these making it into css! It's great to have super granular control of every dimension and stuff, but in terms of creating layouts etc it really needs higher abstraction properties like this. I think this is why css was always so frustrating for me: caring about the technical side of things instead of the actual design implementation, which I now realize is not entirely my fault, but rather by design of the sepcs. (I still need to learn about layout fundamentals etc, but this certainly helps getting a grasp of things)
Not really. It's still tied to the element's width and will overflow vertically. Even if using a flex/grid container with a different axis, it will only constraint the aspect ratio to its width.
Which means that if you want to have something like a video player in the viewport like YouTube does, or lightbox-style previews which keep the entire media element in viewport you'll still have to use JS to limit the element's height, or if the design allows for it, use viewport height units + calc.
I was under the impression that this has been a thing for a long while, but I checked and it's actually been available in mainstream browser versions only since January 2021 (September for Safari, and just nine days ago for Chrome on Android). Combined global usage for supported platforms is around 84%.
I really want to use aspect-ratio, but a recent thread on HN, that now I can't find, has me worried that I shouldn't be counting on CSS until its been supported by the browsers for a couple years.
The recent thread was about all the reasons that even "evergreen" browsers might still have plenty of people using old versions, and was on a thread about a Chromebox still in use that could not have it's version of Chrome updated.
You should generally make these decisions based on the usage stats of your own visitors. Caniuse.com for example lets you import Google Analytics data.
That makes sense, but I'm still cautious of just automatically doing it.
1) it can be a bit circular; if the site doesn't work with a browser, people on that browser are probably not going to spend much time there
2) Depending on what you are doing and your goals/mission (I generally work in academic/non-profit/public sector), you may have a mission that encourages you to be accessible to people on "old technology" regardless of the % of visitors.
I've been thinking maybe a standard of 1-2 year old version of popular "evergreen" browsers might make more sense, than what many people default to "latest version".
Which would put aspect-ratio not quite over the finish line, alas.
Articles like that always make me smile, because I imagine like 20 years ago someone would write a lenghty blog post about GtkAspectFrame or GtkHBox and its “expand” and “fill” child properties. Or about GtkSizeGroup (which css still can’t figure out). Gtk is awesome, so amazing!
this is great, but what sticks out to me is how quickly this seems to have been rolled out. Unless I'm misreading something, this went from first public draft [1] to full support [2] in less than two years?
Maybe I just haven't been paying attention to the rate new CSS features, but from my perspective this totally just dropped out of the sky. Here's hoping we can continue this pace.
If you just want this to avoid layout shift, you're still better off using explicit width and height attributes (on the img tag), because it is per-image in the HTML itself, not in a common CSS declaration. Is that right?
Regardless of whether you use this CSS rule or not, it's a best practice to ALWAYS set the width and height attributes of any image.
So even if you use this CSS rule, you should also set those width and height attributes. This allows the browsers to draw the correctly sized box whilst the image is still loading and whilst CSS hasn't kicked in yet.
It’s kinda funny that, on a CSS focused site, the position of the “latest” article label on the homepage is set above that of the site logo and navigation bar.
It’s nice to know even CSS experts make mistakes ¯\_(ツ)_/¯.
Why? Why would you have different default behaviours if you have one of the dimensions set but not the other? Why would you not have this specified in another property, the overflow property perhaps? Oh look, lets define a new property and call it aspect ratio, and then lets ensure it doesn't maintain an element's aspect ratio if you have content that is going to overflow if you specify a width. This is what drives me mad about css, it's gotchas all the way down.