-
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-values] Introduce self()
function
#9459
Comments
Isn't this basically " Coincidentally, I posted a proposal a few days ago to reduce implementation complexity: #9454 Note that your code above would not work properly even if @property --nested-radius {
syntax: "<length>+"; /* <length>{1,4} not currently supported */
inherits: true;
initial-value: 0;
} This will make the lengths actually resolve and get passed down as lengths. Right now they just get inherited as tokens, and interpreted on the point of usage, so However, your code as specified doesn't even need |
@LeaVerou Thanks for the added context. For the example I included, passing down the nested radius to a child is a simpler example. In many cases, someone would add a border-radius on a great-grandparent and need to pass that several layers down to make it visible. afaik Also, I think it could be possible to use I definitely do not intend to down-play the complexity of a proposal like this. I simply do see significant value-add. One of the primary places I see value is being able to re-use styles more modularly, where styles can work where they are added contextually, without needing to manually create variables every place you want to do something like this. In the border-radius example, you would need to set up all those different variables each time, but with This is just one example. I know there's an issue already open to simply nested radii, which is what initially birthed this proposal, but there are countless other use cases for this. Please know—as tone/intent gets lost so easily online—I'm not trying to be stubborn here. I'm just thinking out loud. Thanks for thinking through this with me. 🙂 |
I think I might be misunderstanding your proposal because I’m not sure how
What do you mean by "long prop-drilling-style implementation"?
It’s not about whether the value is known, if you're specifying the value on an untyped property, it gets passed down as a list of tokens, the same as if you use another known function, e.g.: .parent { --foo: calc(1em + 10px); }
.parent .child { font-size: var(--foo); } If
I was talking about the
Same! |
Ah that makes sense. I was making the case that
Yup! Declarative functions were just a strong use case for this feature, though I also see significant value elsewhere
🙂 |
Nope. As long as the custom property is typed appropriately (and specified inheritable), all you need to pass it down to arbitrarily distant descendants is to set it once on the child of the element you’re querying.
I agree that declarative functions would be immensely useful, but let's try to keep the discussion about each feature in its own issue otherwise it becomes difficult to untangle. |
self()
function [css-values]self()
function
That makes sense. Someone else recommended I include declarative functions as a use case on this ticket, which is why I did. Even without declarative functions in the picture, this code easier to reuse (simple copy & paste, more or less): @property --nested-radius {
syntax: "<length> <length> <length> <length>";
inherits: true;
initial-value: 0px 0px 0px 0px;
}
.parent {
/* we can implicitly use the below values without needing to explicitly
set the border-radius or padding values as CSS custom properties */
--nested-radius:
calc(self(border-top-left-radius) - self(padding-top))
calc(self(border-top-right-radius) - self(padding-right))
calc(self(border-bottom-right-radius) - self(padding-bottom))
calc(self(border-bottom-left-radius) - self(padding-left));
}
.some-descendant {
border-radius: var(--nested-radius);
} …than this: @property --nested-radius {
syntax: "<length> <length> <length> <length>";
inherits: true;
initial-value: 0px 0px 0px 0px;
}
.parent {
/* without self(), we need to explicitly declare padding and border-radius
values as CSS custom properties in order to re-use them, meaning these
types of values couldn't be provided by any 3rd-party lib without
knowing your site and styles, as it can't inherit them */
--br-tl: 30px;
--br-tr: 48px;
--br-br: 82px;
--br-bl: 130px;
--p-t: 20px;
--p-b: 10px;
--p-r: 26px;
--p-l: 44px;
border-radius: var(--br-tl) var(--br-tr) var(--br-br) var(--br-bl);
padding: var(--p-t) var(--p-r) var(--p-b) var(--p-l);
--nested-radius:
calc(var(--br-tl) - var(--p-t))
calc(var(--br-tr) - var(--p-r))
calc(var(--br-br) - var(--p-b))
calc(var(--br-bl) - var(--p-l));
}
.some-descendant {
border-radius: var(--nested-radius);
} I know the circularity may be a huge hurdle to get over if it's even possible. Just trying to further explain the value and use case here. |
@LeaVerou fwiw I believe this
That doesn't mean that this proposal is the solution by any means, but I hope that does a better job of explaining the purpose of this proposal than I did previously.
As you mentioned, this could be the same as " |
Problem Statement
With the increasing complexity of CSS architectures and the push for more modular and declarative designs, there's a clear advantage in allowing styles to be derived based on other computed styles without relying on custom properties alone. This proposal seeks to introduce the
self()
function to fetch and compute styles based on other properties of the same selector.The
self()
functionThe
self()
function will allow designers to fetch a specific computed property value of the same selector in which it is being used. This can reduce the reliance on custom properties for shared values between properties, and streamline the styling process.Use Case
** This is just one use case among countless
Computing the natural nested
border-radius
for a descendant of another rounded element.Current Approach
Using
self()
functionWith declarative functions
With the prospective introduction of declarative functions into CSS, this feature would be even more assistive, as functions could reference other properties without needing to have every related value passed as an argument to that function.
This is how that same example above could look, abstracting the logic away into a custom function so it can be re-used effectively as often as needed, only needing to declare the logic once within the function:
You can think about using
self()
in declarative functions similarly to how one referencesthis
in a prototype method in JavaScript so the function logic can reference the object itself and its other properties, like this:Handling circularity
Addressing circularity risks could be a significant challenge with this proposal. Fetching a property's value from itself or from another property that references the original property could lead to an endless loop, but I think there may be some approaches we could take to combat/prevent that.
Examples of circularity
…or slightly less obviously…
Proposed approaches to preventing circularity issues
Explicit Blocking: If the browser detects a circular reference when computing the
self()
value, it should block the circularity and revert to the initial or default value for that property. This behavior would be similar to the way browsers handle invalid values in CSS.Limit Depth: Implement a depth limit for the number of times
self()
can be used consecutively within a property. If this depth is reached, it defaults to the initial or default value. This can be similar to the stack overflow concept in programming, preventing endless loops.Error Handling: CSS could introduce a new way of handling errors where, if a circular reference is detected, a specific error state is entered for that element, allowing developers to handle it appropriately.
Conclusion
The
self()
function has the potential to streamline CSS development and make it more modular. By allowing property values to be fetched from other properties in the same selector, it reduces the overhead of using custom properties for shared values. However, care needs to be taken to handle potential circular references, ensuring the system remains robust and predictable.The text was updated successfully, but these errors were encountered: