MicrosoftEdge / MSEdgeExplainers

Home for explainer documents originated by the Microsoft Edge team
Creative Commons Attribution 4.0 International
1.29k stars 206 forks source link

[CSS Anchored Positioning] General Feedback #492

Open EisenbergEffect opened 3 years ago

EisenbergEffect commented 3 years ago

Thanks for putting together this proposal for anchored positions in CSS! I'm very excited about what this will enable, especially when combined with the popup work. This is a long-time need for the web 😄

I wanted to provide some general, first-impression feedback on the proposal. My main criticism is of the quantity of new syntax/features and the fact that they are "one-off". Let me explain.

The proposal introduces the concept of an anchor() function in CSS. This references an element's anchor and can be used in calculations. So, if I want to position an element bottom+left of the anchor, I can do this:

top: anchor(bottom);
left: anchor(left);

But why should this be limited to anchors? Why not create a more general function that can reference any element and property? For example:

top: ref(#anchor, bottom);
left: ref(#anchor, left);

This would address the anchored position scenario but open up other scenarios as well. For example, imagine setting the color of an element based on the background of another element, by combining something like ref with calc and various color math functions.

Another example is @position-set. Why not simply have a @set and open up the possibility of using this approach for other scenarios as well? For example, applying different CSS properties to an element based on other factors, such as how much space that particular element has. I believe there's an element query proposal somewhere. I couldn't find the latest with a quick search. It seems to me that the positioning problem could be solved under the larger feature of element queries. Why not align the approaches?

Every new syntax or feature we add to CSS makes the language harder to learn and understand. So, can we find some solutions for anchored positioning where we get re-use out of the features or syntax? That would really help to reduce the cognitive overhead.

Sidebar:

To help put it in perspective, I just looked up "CSS: The Definitive Guide: Visual Presentation for the Web". It's over 1,000 pages, and it doesn't even cover the updates from the last 4 years. Now, I'm looking over at my bookshelf at my collection of books on C, C++, and Rust...and none of them are close to that long. So, I think we should be very honest with ourselves about how complex CSS has become. In my understanding, much of the design was intended to empower non-coders but I often meet seasoned engineers who have trouble understanding non-trivial CSS. Have we succeeded in the goal? Should we try to course correct?

melanierichards commented 3 years ago

Thanks for the feedback, Rob! In the short term we'd like to make sure we can solve the anchored positioning use case (in order to unblock a customizable <select> and other similar use cases), but we should certainly think about extensibility of whatever primitives we generate to meet this set of anchored positioning use cases. Speaking of which, there's a lot of different ideas on syntax, so we're revisiting the use cases and requirements here if you'd like to chime in: https://github.com/openui/open-ui/issues/357#issuecomment-871839171

With regards to extensibility in the current proposal:

But why should this be limited to anchors? Why not create a more general function that can reference any element and property? For example:

top: ref(#anchor, bottom); left: ref(#anchor, left);

Would you be willing to share some practical use cases where these functional references would be applicable?

Another example is @position-set. Why not simply have a @set and open up the possibility of using this approach for other scenarios as well? For example, applying different CSS properties to an element based on other factors, such as how much space that particular element has. I believe there's an element query proposal somewhere. I couldn't find the latest with a quick search. It seems to me that the positioning problem could be solved under the larger feature of element queries. Why not align the approaches?

Would be great to hear your use cases for this too! Particularly, which events trigger the user agent to look at fallback style sets? You can effectively think of changes to the layout viewport as the trigger in the current @position-sets proposal.

Methinks you are referring to container queries. Luckily, we have Miriam (author of that proposal) in Open UI as well, so we can consider if/how the two can be merged. There's (arguably) an inversion of logic, in that container queries enable an author to restyle an element based on a specific known measurement of the container, whereas the anchored positioning schemes enable an author to say "you know what, I don't want to have to track myself whether there's available space to render this element. I want to provide a set of instructions that the browser should run when it knows I've run out of available space with respect to a given element and the layout viewport". That said, there may be other ways of looking at the problem that make the two more cohesive. :)

lukejagodzinski commented 2 years ago

I was thinking the same when I saw anchor function but actually I would propose different API.

--element: querySelector(".some-class");  /* returns HTMLElement by the selector */
--element: anchor(); /* returns HTMLElement that the anchor attr points to */

left: boundRect(--var(element), right);
/* or shorter */
left: boundRect(anchor(), right);

My problem with the anchor function returning CSS size unit is that this name doesn't reflect that. CSS is already hard to understand, where one of the reasons is bad naming (i.e. flexbox).

CSS already became more of a programing language with introduction of vars and functions so let's embrace it and introduce a new type that dev can work with which is HTMLElement. For now it could be just the anchor() function but in the future querySelector() or whatever name you will come up with.

Combining querySelector() with boundRect() or even being able to take other CSS property values would open a door for much more layout possibilities just in pure CSS.

margin-left: prop(querySelector(".class-name"), width); /* if you want to take CSS width value */
margin-left: boundRect(querySelector(".class-name"), width); /* if you want to take computed element's width */
53zulma commented 2 years ago

remove any programm