-
Notifications
You must be signed in to change notification settings - Fork 689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-conditional] Applying styles based on an elements size (@media for elements, container queries) #3852
Comments
Thanks for the issue! Container queries / element queries have been discussed in this group for quite a while. The fundamental issue with them is that they're selectors that depend on layout, and so they're fundamentally cyclical in a way that can't be supported without complicated hacky business. ResizeObserver, by placing itself outside of the CSS layout engine and putting the responsibility of handling cyclic changes on the author, is the current best solution to this sort of thing. |
@tabatkins I understand this, can we possibly use this issue to take our twitter thread and start thinking of a way to make this happen. Especially since I'm digging further into components - this will be needed (eg: just look at the video element in Chromium 😉). I think there are a few approaches to potentially solving this (there may be more, haven't thought this aspect through too far). Feel free to correct me where I may have things wrong.
Thoughts? ccing: @dbaron @FremyCompany |
An issue with (2) is how to do the cycle detection. If you separate the |
The best explanation of RO’s depth-based loop-breaking is probably here: WICG/resize-observer#7 Note that it successfully breaks out of loops within frames, but not across sequences of successive frames. So while it does prevent you from bricking a thread/never painting again, it does not prevent flickering between a cycle of states. (Also interesting to note that it’s basically what @ausi implemented in his cq-prollyfill library https://mobile.twitter.com/ausi/status/873464855843524608) |
Yeah, and it's very concerning that this kind of loop might be so subtle you would not notice it on the screen but it would basically kill the performance of your site and drain your user's battery by causing a new layout and a new paint every frame at 60fps. That's why I would not recommend to standardize the RO-based pipeline. (Especially concerning is that this might only happen in a specific scenario which might not happen on the developer's device and might be very difficult to diagnose after the fact, because it might need the resize to happen at a certain pair of points between two frames, which might only happen when you rotate the screen of a specific device, or resize your window quickly, or when the touch keyboard appears on certain OSes depending on the screen height, etc etc etc you got the idea) |
Three thoughts: 1. Element can not Resize Some thoughts though, obviously this works for items that have box-sizing: border-box; but not for the standard box model. ~ sibling selectors couldn't be supported by this 2. Secondary Layout is last and only occurs once For example, lets say you have the box and below 900px you are going to apply a border: 2px solid pink; After the element drops to 899px, a 2px border is applied increasing size to 901px breaking the condition but because condition on the first run through it does not then do a third run through. The reason I'm not sure about this particular method is that if you have multiple conditional css based on size on nested children. 3. Ranges |
@FremyCompany While I get the worry, I'm not sure if this is something that should block on - especially since it is already available in JS, not only in RO but also using Finally, a synchonous version - which we had in msElementResize cause us numerous performance issues, as you know, so I think having the flash is a solid trade off to keeping async. I'm personally kind of tired (as you know since we worked right next to each other for so long) of this being punted on, especially since we have this in JS and it's effectively syntactic sugar at this point if you put this in CSS and build it on top of |
Matthew Dean has a very nicely written proposal which touches on a lot of interesting points: WICG/container-queries#12 |
It is not because it was synchronous that it was causing issues, it is because the only way to use this was to trash layout, and you need to trash layout O(n^2) for the amount of breaks you have in your code, so with just two nested layers of observation you already make layout 4 times slower. Plus it is linear to the amount of observations you have, and many used this for children of a list so layout was thrashed dozens of times as all the items would get notifications and trash the layout before the next one did. So, sure, if you trash layout dozens of times, synchronicity is then problematic because layout then blocked the main thread. Async doesn't make things more performant, tough, it actually makes things way slower (now you are also trashing paint on top of layout), but at least the page stays responsive because the main thread isn't busy looping: it has some breath of fresh air between the layout wastes. This isn't a solution, the solution is to not waste layout, and we have all the tools needed to accomplish that goal cleanly today, so I see no reason why we would settle for less.
This very thread is a testimony that this is not true. I'm quoting here:
Using the same pipeline as RO to achieve the desired results will not solve any of the problems people are facing with RO today and which make them say this isn't the solution they want (while still admitting it is the solution they need, because there isn't any better yet). |
Yes, I know that, but the synchronous version made this a terrible end user experience, thus compounding the issue of doing layout numerous times.
Again, I am not opposed with a longer term solution that is both synchronous and avoids the layout thrashing. Assuming that can be done and I also stated that I was for having an Finally, as denoted above - and I just want to repeat for emphasis, if you (or anyone) have any suggestions on how we can both solve web developer's use cases while also avoiding layout thrashing and thus allowing it to be synchronous; I happily welcome them. |
A large portion of use cases, for which web developers want container queries for, can be solved – I think – by CSS conditions that work with custom properties (aka CSS variables). I proposed such a feature on WICG Discourse two years ago and wrote a short article about how I believe this can be a solution to most container query use cases. It doesn’t require layout thrashing and cannot result in endless loops. This year I discovered that CSS animations can be (mis)used to build something very similar. It is far away from being useful in production, but it shows that browsers and their CSS engines are capable of handling such a feature (in contrast to container queries). A short demo of this technique is available on CodePen and shows that CSS conditions are perfectly suitable for the main use case described in https://wicg.github.io/cq-usecases/ UPDATE: @gregwhitworth I just saw that you’ve already read my proposal in WICG/container-queries#5 (comment) |
As I understand, cycling issue can be resolved with adding |
@imkremen my understanding is that there are two proposals that just might work:
This lets you query any element without restricting or modifying its layout, but is, I think, harder for authors to "see," and reason about. There may be other fundamental issues with how this strategy would restrict layout performance, which @bfgeek discussed in the Twitter thread, and which I won't pretend to understand. Basically: an author writes a potentially-circular container query. Do we want that query to change (or require changes to) the actual layout of the queried element, to remove the potential of infinite loops? Or do we want to query something other than the element's size, in order to remove that potential? |
I think we can safely close this issue, now that a Container Query spec is officially in Working Draft, and development is underway in multiple browsers? |
Container Queries thoroughly solves all the issues in this ticket. Thank you. |
For: https://drafts.csswg.org/css-conditional-3/
Although it's possible this might need to be applied to a different part of the specification.
PROBLEM:
It is possible to apply styles to an element based on the viewports size, but not to the elements size.
Take the following example:
Using a media query I can change it so that as the width of the viewport shrinks we can reduce the size of the text so that it fits like so:
but if the we expand or contract the menu (i.e. if the user presses a button and we use javascript to change the width of the menu), there is no way currently in CSS to change the style based on an elements size.
Currently we have to use ResizeObserver (or mutation observer in browsers that don't support it) to monitor the size of the element and then remove and add a CSS class which we can then use to apply the style.
POSSIBLE SOLUTIONS:
A possible solution would be to add a CSS selector like:
As a minimum viable spec, it would be nice to support max-width, min-width, max-height, min-height but it could be expanded to include all the current media options.. for example:
CONSIDERATIONS:
The widths and heights of each element would need to be calculated first. Then the conditional arguments would need to be run through altering the widths and heights of the elements.
The issue with running it in javascript, is that you can get a flickering as the ResizeObserver will get triggered on every change and the css you are applying can break the condition (i.e. by changing the width).
By moving this into CSS it's not longer an issue because the resizing only happens once.
USAGE:
I've discussed this in depth with a large group of web-developers and we think this would be very useful, however the syntax and mechanics are not quite obvious.
The text was updated successfully, but these errors were encountered: