Skip to content
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-4] inherit() function: like var() for parent value, for any property #2864

Open
LeaVerou opened this issue Jul 3, 2018 · 98 comments

Comments

@LeaVerou
Copy link
Member

LeaVerou commented Jul 3, 2018

[Edit: We've now defined 'inherit()', but only for custom properties. The issue is left open to track the fuller feature.]


We've declined numerous author requests to extend var() to arbitrary properties, due to the potential for cycles and how expensive cycle detection would be in the general case. However, providing a way to get the parent or inherited value of any property does not cause cycles and still helps with a ton of use cases.

Use cases

Custom property value that depends on parent value

Generic --depth (1, 2)

* {
	--depth: calc(inherit(--depth, 0) + 1);
}

See also: #1962

Font metrics relative to parent

strong {
	font-weight: clamp(600, 1.2 * inherit(font-weight), 999);
}

And any other numerical typographic metric that can be specified in CSS, e.g. font-stretch, font-style (for variable fonts) etc

Many of the currentBackgroundColor use cases

#5292

While this does not address all use cases (since it would only provide an ancestor background color), it does address quite a few, and offers a workaround for others.

Matching nested radii

#7707

inherit inherit() + calc
Screen Shot 2022-09-07 at 9 15 06 AM Screen Shot 2022-09-07 at 9 15 11 AM
.child {
	padding: 1em;
	border-radius: calc(inherit(border-radius) - 1em);
}

Swapping foreground and background colors

.button {
	color: inherit(background-color);
	background: inherit(color);
}

Decorations visually extending the background

https://twitter.com/HugoGiraudel/status/1350496044681990147

blockquote::before {
	content: "❝";
	color: inherit(background-color);
	font-size: 300%;
}

Override parent margins (bleed)

.card > header {
	margin-top: calc(-1 * inherit(padding-top));
	margin-left: calc(-1 * inherit(padding-left));
	margin-right: calc(-1 * inherit(padding-right));
}

Inherit grandparent value

https://twitter.com/cjw0/status/1350499207648583683

.foo {
	--font-size: inherit(font-size);
	font-size: 0; /* for animation */
}

.foo > * {
	font-size: var(--font-size);
}

@property does provide a workaround for this particular case (just register a <length> custom property and set it on .foo’s parent), but not in the general case where no suitable registration synstax exists.

More use cases

@LeaVerou LeaVerou added the css-values-4 Current Work label Jul 3, 2018
@upsuper
Copy link
Member

upsuper commented Jul 3, 2018

We probably don't want it to be a function, or at least not a function accepting arbitrary property. Different properties may have different underlying storage / handling, so it could be hard if it uses arbitrary property in arbitrary property.

It might be fine to restrict it to properties with only a single numeric value, but I believe in the past we occasionally extend single-value properties into multi-values, so a general mechanism like this may not be future-proofing.

@upsuper
Copy link
Member

upsuper commented Jul 3, 2018

Also it sounds like a dupe of #2764.

@jonjohnjohnson
Copy link

@FremyCompany mentioned the cascade proposal and I imagine this playing into that? #1594 (comment)

@LeaVerou
Copy link
Member Author

LeaVerou commented Jul 3, 2018

@upsuper Not a dupe of #2764, which is about a special case of this.

Could you elaborate a bit on the underlying storage/handling issue? How could it get in the way? Is it theoretical or are there existing examples of properties that would have issues?

Also, by future-proofing, are you referring to implementation issues or author code?

@upsuper
Copy link
Member

upsuper commented Jul 3, 2018

Could you elaborate a bit on the underlying storage/handling issue? How could it get in the way? Is it theoretical or are there existing examples of properties that would have issues?

I wrote that mostly concerning the implementation difficulties in mind, since we (in Stylo) use lots of different types to handle subtle differences between properties. But I realized that it is actually not a problem of types, but the differences themselves. For example, word-spacing and letter-spacing is almost the same except that the former accepts <percentage> in addition to normal | <length>. If any property can be referenced to any property, we would need a mechanism to extract only certain type of value, with either a fallback or just treating as invalid at computed-value time.

Such mechanism has its own issue, that supported type at a value position may depend on the context, and can change as CSS evolves. For example, there is plan to allow division between two dimensions, which may enable <percentage> being used in a property accepting only <dimension> as far as you divide it with another percentage. Also there is some idea about allowing auto in calc for some properties. Those kind of changes may affect above-mentioned mechanism.

Also, by future-proofing, are you referring to implementation issues or author code?

For spec about how to handle it. Actually the above has something related to future-proofing already.

@LeaVerou
Copy link
Member Author

LeaVerou commented Jul 3, 2018

It doesn't need to retain anything about the type, just serialize the value and use it the same as when var() is used.

@upsuper
Copy link
Member

upsuper commented Jul 3, 2018

OK, so I misunderstood the approach you are proposing. This approach is probably better to some extent, although I'm a bit concerned that serialization of computed value of properties may not be as well-defined and interoperable as token stream used by custom properties.

@tabatkins
Copy link
Member

Discussion with dbaron suggested that the effect would be that you basically just sub in the serialization of the computed value (probably per the well-specified serialization in Typed OM).

If the property you're subbing in doesn't work for the property you're subbing into, it would follow the same rules as var(), and make it invalid at computed-value time.

@CyberAP
Copy link

CyberAP commented Oct 29, 2018

Shouldn't it be called computed() then, instead of inherit()? Makes more sense to me and it is more declarative, than an imperative inherit.
Or just simply prop() as it's a direct CSS property reference here.

@LeaVerou
Copy link
Member Author

LeaVerou commented Jan 17, 2021

I just came across this issue again looking for something else and was reminded of how useful this would be.

@tabatkins wrote

Discussion with @dbaron suggested that the effect would be that you basically just sub in the serialization of the computed value (probably per the well-specified serialization in Typed OM).

If the property you're subbing in doesn't work for the property you're subbing into, it would follow the same rules as var(), and make it invalid at computed-value time.

It sounds like there is a clear implementation path, but the discussion just stalled 2 years ago.
Can we move it forwards?

I promised in the first post that if this is feasible, I could try and collect a list of use cases. Here are a few:

Edit: Added these to OP, for convenience.

In terms of how it should behave, a few more thoughts:

  • Does it return the parent value regardless of what it is, or walk up ancestors until it finds a value or hit the root? This is especially relevant for non inherited properties. It seems like it could be more useful if it returned the closest non-initial value, rather than the direct parent, but then there are no guarantees about what element you're actually getting a value from. E.g. consider the "swap background and text colors in children" above. What if the parent ends up not having a color set at all, and inherit(background-color) ends up walking up the ancestors and returning e.g. the page's background? OTOH, that might actually be the background you're seeing...
  • It should probably have a fallback, just like var(). The fallback would apply when the returned value is initial.
  • As @upsuper and @tabatkins pointed out above, if after subbing the value, the resulting declaration doesn't make sense, the whole thing just becomes IACVT.
  • Can shorthands be referenced? If so, what do they return? If they cannot be referenced, this means that when we turn a property into a shorthand, code starts breaking (this was already a risk, it was just limited to JS). Also this would mean that even fairly "obvious" use cases would become complicated (e.g. inherit(border-color) cannot be used).
  • Some potential names: inherit(), inherited(), parent(), ancestor(), closest()

@Loirooriol
Copy link
Contributor

Does it return the parent value regardless of what it is, or walk up ancestors until it finds a value or hit the root?

In general I don't think walking ancestors makes much sense for non-inherited properties. Even for inherited ones it may be undesirable. So I would just return the parent value.

It should probably have a fallback, just like var(). The fallback would apply when the returned value is initial.

But using the fallback for initial values would be inconsistent with var() and env(). I think the fallback should be used when the serialization of the computed value is the empty string (like a guaranteed-invalid value, or a shorthand that can't represent the values of its longhands). IMO custom behaviors for specific values should be achieved with conditionals (#5624).

Can shorthands be referenced? If so, what do they return?

If this feature is based on serializations, then it doesn't seem problematic to me. Just try to serialize the shorthand, and return that in case of success, or empty string otherwise. When reparsed, empty string can be treated as a guaranteed-invalid value, and use the fallback value if provided, or become IACVT otherwise.

@LeaVerou
Copy link
Member Author

LeaVerou commented Jan 18, 2021

@Loirooriol

Does it return the parent value regardless of what it is, or walk up ancestors until it finds a value or hit the root?

In general I don't think walking ancestors makes much sense for non-inherited properties. Even for inherited ones it may be undesirable. So I would just return the parent value.

I suppose that's more predictable (and probably more performant and easier to implement). After all, if one wants the value from a specific ancestor, there's an easy workaround:

/* Swap background & foreground in descendants use case: */
.container > * {
	--container-background: inherit(background-color);
}

.container * {
	color: var(--container-background);
	background: inherit(color);
}

It should probably have a fallback, just like var(). The fallback would apply when the returned value is initial.

But using the fallback for initial values would be inconsistent with var() and env(). I think the fallback should be used when the serialization of the computed value is the empty string (like a guaranteed-invalid value, or a shorthand that can't represent the values of its longhands). IMO custom behaviors for specific values should be achieved with conditionals (#5624).

The fallback for var(--foo) is applied when --foo is initial ([demo],(https://dabblet.com/gist/b49604259b2765fec0966ba649dad8c8) spec). I agree with your reasoning however, especially since this allows shorthands to be used, which is really important.

env() has an entirely different fallback mechanism (falls back when the name is not recognized, not depending on the value).

Can shorthands be referenced? If so, what do they return?

If this feature is based on serializations, then it doesn't seem problematic to me. Just try to serialize the shorthand, and return that in case of success, or empty string otherwise. When reparsed, empty string can be treated as a guaranteed-invalid value, and use the fallback value if provided, or become IACVT otherwise.

I really like this. 💯

@Loirooriol
Copy link
Contributor

The fallback for var(--foo) is applied when --foo is initial

Ah, yes, that's because the initial value for unregistered custom properties is the guaranteed-invalid value, which is what triggers the fallback. But if you register the property with some other initial value, then initial doesn't trigger the fallback in var(), so I guess it shouldn't in inherit() either.

@andruud
Copy link
Member

andruud commented Mar 25, 2021

walk up ancestors until it finds a value

Sounds like it's already settled, but I'll emphasize anyway that this is something we should definitely not do.

sub in the serialization of the computed value

We recently (-ish) invented the equivalent token sequence, so we can just re-use that for this.


I've been trying to think about whether or not the new "cross property inheritance" proposed here creates any significant new problems (performance, complexity, etc) for style recalcs. I think it should be fine. It's similar to situations that must anyway be dealt with via var() and explicit inheritance of non-inherited properties.

This looks like a relatively "easy win", so I'm supportive, FWIW. 👍

@LeaVerou
Copy link
Member Author

LeaVerou commented Mar 25, 2021

Since there is implementor interest, I'm adding this to the agenda for the next call so we can resolve about work on it.

@argyleink
Copy link
Contributor

argyleink commented Mar 30, 2021

Here's a rad use case with color-contrast() from Color 5

p {
  color: color-contrast(
    inherit(background-color) 
    vs 
    var(--brand-1), var(--brand-2), var(--brand-3)
    to AA
  );
}

On brand, dynamic and high contrast text color on 🤷🏻

@LeaVerou
Copy link
Member Author

LeaVerou commented Mar 31, 2021

Thinking about this a bit more, I think it should be called parent() or parent-var(), not inherit() which implies action, not value.

A few more use cases (in addition to those in #2864 (comment) ):

  • Ability to use attr() from parents on children (source)
  • Revert to grandparent font size, i.e. font-size: calc(1em * (1em / parent(font-size))). Basically any use case where you want to do math with inherit. 1 2
  • Alternating values, i.e. emulating the old cycle() that never made it, e.g. list-style: if(parent(list-style) = 'disc', 'square'); (assuming if() gets in) (also this)
  • Assign CSS variable based on parent e.g. --nesting-level: calc(parent(--nesting-level) + 1)
  • Using the parent's background-color or accent-color to create derived colors (e.g. a lighter color for the heading), see also @argyleink's example above

@getify
Copy link

getify commented Mar 31, 2021

Here's my use-case:

I regularly will set a CSS variable in a parent element, then use that value for some dimension (like width). Then, in a child element, I'll use that same CSS variable and perform a calc(..) on it to derive a new value for the child element to use for some other dimension (like padding or border width). In this case, I'm only using the CSS variable because of its ability to be inherited down to the child and re-used.

It would be much nicer if, in those cases, I could skip the CSS variable altogether, and just have the child element reference a parent CSS property value, like for example: border-width: calc(parent(width) / 10).

@mirisuzanne
Copy link
Contributor

Working with custom properties, I've wanted this a few times. Here are a few examples (some may duplicate Leas examples above):

.examples {
  /* change a value locally, without losing context */
  --columns: parent(--span);
  --span: 3;
  width: calc(var(--span) / var(--columns) * 100%);

  /* normal properties */
  color: color-contrast(parent(background-color) vs black, white);
  margin: calc(parent(padding) * -1);

  /* more generic patterns */
  --alternate: calc(parent(--alternate) * -1);
  --count: calc(parent(--count) + 1);

  --switch-1: parent(--switch-2);
  --switch-2: parent(--switch-1);
}

@astearns astearns added this to the APAC VF2F-2021-04-08 milestone Apr 2, 2021
@tolmasky
Copy link

I really want this for width and height as a way to finally escape the confusing aspects of using percentages which are locked to one or the other (for example with padding). Please consider adding width and height to the allowed list.

@LeaVerou
Copy link
Member Author

I really want this for width and height as a way to finally escape the confusing aspects of using percentages which are locked to one or the other (for example with padding). Please consider adding width and height to the allowed list.

For width and height, I think container query units will probably work much better for most use cases, and they're already supported eveyrwhere!

@tolmasky
Copy link

For width and height, I think container query units will probably work much better for most use cases, and they're already supported eveyrwhere!

Unless I'm misunderstanding, that first requires me to make a container query though, right? I can't just say padding: calc(10 * cqh) calc(10 * cqw), right? I have to first create an arbitrary container query so that cqw and cqh actually refer to the right thing? This seems way more cumbersome than being able to just refer to your parent's width and height, the way percentages implicitly (but confusingly do), and the way inherits does. I initially came to this bug trying to find if there was anything like pw and ph (to match vw and vh and cqw and cqh), and eventually was led to this bug saying "We don't need that since you can just do inherit(width), only to then scroll to the end and discover those were dropped. So back to square one.

@brandonmcconnell
Copy link

brandonmcconnell commented Dec 29, 2023

That's my understanding as well. Moreover, in some of my container query testing, I've noticed that setting up a container produces some wonky and unexpected results to the element that is declared as a container, causing its height to essentially zero out, if not explicitly set.

Being able to inherit those computed values would be a huge win in this case. Most of the times I've set up a container, I've done so specifically to use its width and height, so this seems like it would be easier to reach for in simpler circumstances like this.

Using container queries

/* Parent Element */
.parent {
  width: 300px;
  height: 200px;
  container-type: size;
}

/* Child Element */
.child {
  width: 50cqw;
  height: 50cqh;
}

Using inherit()

/* Parent Element */
.parent {
  width: 300px;
  height: 200px;
}

/* Child Element */
.child {
  width: calc(inherit(width) / 2);
  height: calc(inherit(height) / 2);
}

Also, I understand it would be easier on the first pass of this feature to only support CSS custom properties with the inherit() function, but in 99% of cases, can't CSS custom properties be naturally inherited without using inherit(), except when a CSS custom property is set to inherits: false using @property?

@LeaVerou
Copy link
Member Author

LeaVerou commented Dec 29, 2023

@tolmasky

For width and height, I think container query units will probably work much better for most use cases, and they're already supported eveyrwhere!

Unless I'm misunderstanding, that first requires me to make a container query though, right? I can't just say padding: calc(10 * cqh) calc(10 * cqw), right? I have to first create an arbitrary container query so that cqw and cqh actually refer to the right thing? This seems way more cumbersome than being able to just refer to your parent's width and height, the way percentages implicitly (but confusingly do), and the way inherits does. I initially came to this bug trying to find if there was anything like pw and ph (to match vw and vh and cqw and cqh), and eventually was led to this bug saying "We don't need that since you can just do inherit(width), only to then scroll to the end and discover those were dropped. So back to square one.

You just need to set appropriate container-* properties, not a container query. And soon (much sooner than inherit() may ship) you'll be able to refer to containers higher than the closest one.
inherit() will not do what you want most of the time, because it would only give you a parent width/height, and only if it's explicitly set, which it usually is not. Whereas cq units will actually be computed based on the used dimensions.

@brandonmcconnell

That's my understanding as well. Moreover, in some of my container query testing, I've noticed that setting up a container produces some wonky and unexpected results to the element that is declared as a container, causing its height to essentially zero out, if not explicitly set.

This sounds like a potential browser bug?

Being able to inherit those computed values would be a huge win in this case. Most of the times I've set up a container, I've done so specifically to use its width and height, so this seems like it would be easier to reach for in simpler circumstances like this.

See above, you wouldn't be inheriting used values with inherit().

Also, I understand it would be easier on the first pass of this feature to only support CSS custom properties with the inherit() function, but in 99% of cases, can't CSS custom properties be naturally inherited without using inherit(), except when a CSS custom property is set to inherits: false using @property?

a) Most use cases for inherit() are around using the inherited value of property A in property B, which is not something you get with regular inheritance.
b) Regular inheritance doesn't allow you to do math. --foo: calc(var(--foo) + 1) is IACVT, whether --foo inherits or not. --foo: inherit is valid, but you can’t do anything with it (though we should probably enable that).

@tolmasky
Copy link

tolmasky commented Dec 29, 2023

You just need to set appropriate container-* properties, not a container query. And soon (much sooner than inherit() may ship) you'll be able to refer to containers higher than the closest one.
inherit() will not do what you want most of the time, because it would only give you a parent width/height, and only if it's explicitly set, which it usually is not. Whereas cq units will actually be computed based on the used dimensions.

I guess there are actually two issues here:

  1. In the specific padding case that I was originally trying to solve, it occurs to me that both this inheritance stuff and the container query approach don't really do what I need, since padding percentages are based off of the current element's size, and not the parent. So what I really want is just new units like %w and %h, to differentiate between the width and height when referring to percentages. That way I could just do something like padding: 10%h 10%w. Should I open a new issue to discuss that specifically? As helpfully pointed out by @Loirooriol, I got this mixed up. Thank you!

  2. When wanting to refer to a parent's size, it still feels like it would be useful to have something like %h and %w, since it seems that specifying the container- properties may sign you up for more behavior than you bargained for, including, potentially, performance implications? I ask because percentages seem to get away with providing access to parent size information (with limitations), without having to formally denote something as a container (in other words, they'll work with "any" parent, when it makes sense), and theoretically without any additional performance implications. In other words, height: 10%h would work in all circumstances that height: 10% works, including when it is effectively ignored.

    EDIT: Perhaps it is useful to clarify that the more interesting case is that height: 10%w would work in all circumstances that width: 10% works, including when it is effectively ignored.

@mirisuzanne
Copy link
Contributor

@brandonmcconnell @LeaVerou

That's my understanding as well. Moreover, in some of my container query testing, I've noticed that setting up a container produces some wonky and unexpected results to the element that is declared as a container, causing its height to essentially zero out, if not explicitly set.

This sounds like a potential browser bug?

That's not a browser bug, it's the result of size containment. In order to create a container for height queries, the height has to be 'contained' and therefor extrinsic. Querying an intrinsic height would result self-referential behavior: the height is based on the contents, which are styled based on the height, etc. So applying a container-type: size will result in zero intrinsic height.

Which gets at a distinction between what these two features would do, which Lea also covered above:

  • Query units are based on the actual used height/width of a container after layout.
  • The inherit() function would give us the computed value of the height/width properties, regardless of layout.

If we want the former, we have to live with the size containment limitation. There's no way to get the actual used dimensions without that limitation. If we want the latter, we can avoid containment… But the examples so far rely on explicit heights anyway.

That's roughly what Lea said. But then:

See above, you wouldn't be inheriting computed values with inherit().

Looking back through the thread, I can't find this stated anywhere. In fact, most of the discussion is about the fact that you would inherit the computed value – which makes sense, because that's how inheritance works.

@kizu
Copy link
Member

kizu commented Dec 29, 2023

So what I really want is just new units like %w and %h, to differentiate between the width and height when referring to percentages. That way I could just do something like padding: 10%h 10%w. Should I open a new issue to discuss that specifically?

I really think those are just container query length units use cases. Exposing them without the containment could lead to circularity.

Some other cases could also be handled by aspect-ratio, like height: 10%w might be expressed as aspect-ratio: 10; (if we know that the width will be 100%).

Can you provide your use cases to look at, so it would be easier to gauge if they can be done with what we have, or if inherit() could help with them? What are you trying to achieve? Not as a reduced solution without a problem, but as a problem itself.

@Loirooriol
Copy link
Contributor

since padding percentages are based off of the current element's size, and not the parent

No. Percentages refer to the inline size of the containing block (which is typically established by the parent, but not necessarily). See https://drafts.csswg.org/css-box-4/#propdef-padding

Should I open a new issue to discuss that specifically?

I think you first need to figure out what you are actually trying to do, and then, if if your usecase would benefit from new functionality, open a new issue.

@tolmasky
Copy link

I really think those are just container query length units use cases. Exposing them without the containment could lead to > > since padding percentages are based off of the current element's size, and not the parent

No. Percentages refer to the inline size of the containing block (which is typically established by the parent, but not necessarily). See https://drafts.csswg.org/css-box-4/#propdef-padding

You're absolutely right on this -- don't know why I mixed these up!

I think you first need to figure out what you are actually trying to do, and then, if if your use case would benefit from new functionality, open a new issue.

Not sure if you are asking for a specific reduction here or what, but in my experience this is generally difficult to do for cases like this (especially since there's always some workaround). I think just referring to the large number of questions around how to get padding to be a percentage of height should demonstrate a need for wanting to have the same existing functionality as we currently get with percentage, but for height as well as width. In a world where padding percentages were based on height instead of width, I'd now be asking for some way to base it off of width. I don't believe there's some "proof" that width-based padding is important enough to bake in, but height-based padding isn't.

@tolmasky
Copy link

So what I really want is just new units like %w and %h, to differentiate between the width and height when referring to percentages. That way I could just do something like padding: 10%h 10%w. Should I open a new issue to discuss that specifically?

I really think those are just container query length units use cases. Exposing them without the containment could lead to circularity.

I certainly haven't thought through all the ramifications, but I would be surprised if this addition is any more circular than the existing percentages we already have access to. One way to look at it is that all geometry-based % units today are already either implicitly %w or %h. In the padding case, % is identical to my proposed %w. In the width case as well. In the height case, % is identical to my proposed %h. It doesn't seem obvious to me that allowing you to be explicit about it would change that, especially if it followed the same rules as % today to avoid any potential circularity.

@kizu
Copy link
Member

kizu commented Dec 29, 2023

I don't believe there's some "proof" that width-based padding is important enough to bake in, but height-based padding isn't.

The key to thinking about this is to think about them not as “width” and “height”, but as “inline” and “block”.

These are very different: predominantly, the inline dimension stays the same, while the block one grows. Adding a padding in the inline direction, in a normal flow, reduces the space available for content and does not change the inline dimension of the parent. Adding a padding in the block direction is not constrained, and makes the element and its container grow in the block direction (thus, can lead to circularity).

And, because block and inline dimensions are so different, the use-cases for the percentage in them are also different! Percentage in the inline dimension usually reflects the available space: we can make the padding bigger when we have a wider screen (or wider container). What will the padding in a block dimension reflect?

@Loirooriol
Copy link
Contributor

@tolmasky Then you should file a new issue, since you want to resolve percentages with the actual size of the containing block, while inherit(height) will be a computed value, and may not be the containing block.

I would be surprised if this addition is any more circular

Yeah it should be fine, in the block axis it's easier for percentages to be cyclic but that can also happen in the inline axis, and the behavior is defined in https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution. In fact, for a while the flexbox spec allowed resolving padding percentages like you want (see #2085), so it's not intrinsically problematic.

@brandonmcconnell
Copy link

@LeaVerou @mirisuzanne Thanks for clarifying the behavior of inheritance here. It sounds like we might still need to discuss whether those values are computed or not.

How would the below example work?

.bordered {
  border: 1px solid #000;
  > .bordered {
    border: inherit;
    border-width: calc(inherit(border-width) + 1px);
  }
}

At first glance, I would expect each .bordered element to have the same border as its parent .bordered element, but increase in width by 1px with each nesting level. Is this accurate?

@Loirooriol
Copy link
Contributor

Loirooriol commented Dec 30, 2023

@brandonmcconnell The computed value of border-*-width is an absolute length, so assuming this is based on the serialization of the specified property:

  • If all the sides have the same thickness, then inherit(border-width) will be a <length> and calc() will work.
  • If some sides have different thicknesses, then calc() will not work. Presumably it will become invalid at computed-value time, and behave as medium (3px).

If you want an example that varies depending on whether this uses the computed vs the used value:

#foo { height: 100px }
#foo > #bar { height: 50% }
#foo > #bar > #baz { height: inherit(height) }

Then I would say that this inherits the computed value:

Element Computed Used
foo 100px 100px
bar 50% 50px
baz 50% 25px

@LeaVerou
Copy link
Member Author

@mirisuzanne

See above, you wouldn't be inheriting computed values with inherit().

Looking back through the thread, I can't find this stated anywhere. In fact, most of the discussion is about the fact that you would inherit the computed value – which makes sense, because that's how inheritance works.

Typo, I meant used values. Have edited now!

@kizu
Copy link
Member

kizu commented Apr 18, 2024

This week I posted two articles: “Alternating Style Queries” and ”Self-Modifying Variables: the inherit() Workaround” that show how we could use the style queries in the future (working in Chrome and in Safari TP for now) to work around some use cases (those that involve custom properties) for inherit(). They could be of use for anyone who would like to prototype how inherit() could look in their code.

@EisenbergEffect
Copy link

I've been using the same technique that @kizu describes to work around the lack of inherit(), particularly in design system scenarios where color layer adaptations are needed for accessibility. I'd love to see inherit() make it into the spec as it's a much cleaner solution than the container query hacks for this type of thing.

@una
Copy link
Contributor

una commented Jun 12, 2024

Another usecase would be essentially enabling #5292 (currentBackgroundColor) and other similar values. Would be highly useful!

i.e. Leveraging background-color to apply border styles:

@fantasai
Copy link
Collaborator

This is now edited in for custom properties as resolved. Leaving the issue open for the more general discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests