Skip to content

[css-box] Suggestion: Add "of <property>" syntax for percentage values of padding and margin properties #6814

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

Open
RolandHeinze opened this issue Nov 12, 2021 · 8 comments

Comments

@RolandHeinze
Copy link

RolandHeinze commented Nov 12, 2021

The CSS Box Model Level 3 and CSS Box Model Level 4 Specifications define the properties margin-top, margin-right, margin-bottom, margin-left, margin, padding-top, padding-right, padding-bottom, padding-left, and padding. They are all allowed to have percentage values. Currently, the percentage value always refers to the width of the containing block. This can be an unwanted restriction. In particular, margin-top, margin-bottom, padding-top, and padding-bottom represent vertical lengths, and the percentage values refer to horizontal lenghts. This can be irritating.

I want to suggest a more universal approach:
Please add the syntax of <property> for percentage values of all the mentioned properties. <property> can be any property name of the containing block which has a length value. It would bring much greater flexibility in relating percentages to property values for the end user of CSS. E.g. You can write

margin-top: 10% of height;
padding-left: 50% of padding-left;
padding-bottom: 30% of border-bottom-width;

I hope that this change is technically possible, as I don't know whether it could result in an infinite loop of the underlying algorithms (e.g. an element refers to the height of an ancestor element which depends on the height of exactly that descendant element).

I propose to offer similar extensions for other properties which allow percentage values such as font-size as end users also want to relate the font size to the height or width of the parent element which is currently not possible. Of course, that it out of the scope of the CSS Box Model Specification.

@Loirooriol
Copy link
Contributor

Assuming that the parent is the containing block, and that the desired property computes to a length, then #2864 already resolved to add an inherit() function like

margin-top: calc(0.1 * inherit(height));
padding-left: calc(0.5 * inherit(padding-left));
padding-bottom: calc(0.3 * inherit(border-bottom-width));

But inherit(height) will typically be auto and this won't work. Your proposal would work in that case.

I don't know whether it could result in an infinite loop

I think it's fine, cycles already happen right now and they are handled in https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution

@RolandHeinze
Copy link
Author

@Loirooriol Thank You for the hint to #2864. I didn't know that an inhert() function is planned. I also dont find a specification text for [css-values-5] already, and the [css-values-4] specification text seem not to mention an inherit() function.

As inherit() relates to a parent element and not the containing block, inherit() will solve slightly different positioning and sizing problems in CSS. My suggestion relates percentage values to property values of the containing block. As documented on MDN about Containing Block, the containing block can be a different box than the context box of the the nearest block-level ancestor.

I also thought once again about cycles, especially using expressions like 10% of height, and I realized that relating to the height of the containing block is already possible for the height property: Using height: 10%; means exactly the same as height: 10% of height;. Therefore, relating the margin or padding properties to the height value of the containing block should also be possible.

Thank You once again for the link to [css-sizing-3].

@SebastianZ
Copy link
Contributor

@Loirooriol Thank You for the hint to #2864. I didn't know that an inhert() function is planned. I also dont find a specification text for [css-values-5] already, and the [css-values-4] specification text seem not to mention an inherit() function.

You can't find any specification of inherit() yet because #2864 is the issue that suggests to add it. 😃

Sebastian

@Loirooriol
Copy link
Contributor

<property> can be any property name of the containing block which has a length value.

Seems important to note that, technically speaking, the containing block is just a rectangle. Yes, it's typically established by an element, and we can refer to the properties of that element. But for example, sometimes the containing block is established by the content area, and sometimes by the padding area. What should of width refer to, the computed value of width, whose final meaning depends on box-sizing? May be a bit confusing if width: 100% of width and width: 100% mean slightly different things. And what if the computed value is not a <length-percentage>?

I'm also not sure if there are clear usecases for of padding-left, etc. that are not already covered by inherit(). It seems to me that, when referring specifically to the containing block, we are basically interested in its width and height (and by this I mean the actual size of the rectangle, not the properties of the establishing element).

So, rather than a of <property> syntax, maybe we should have new units for that? I think that's what #1645 proposes.

BTW, there are units for query containers https://drafts.csswg.org/css-contain-3/#container-query-length

@RolandHeinze
Copy link
Author

@Loirooriol Yes, the containing block is by definition a rectangle, and it can be the content box or padding box of an element, the viewport, or even the bounding box of two differnt padding boxes of inline elements. Therefore, if we were only interested in the demensions of that rectangle, it would be the best to have new measures for that. Maybe, it would be a good idea to name them cbh, cbw, cbi, cbb, cbmin, and cbmax in accordance with the cqh, cqw, cqi, cqb, cqmin, and cqmax query container relative lengths of css-contain-3. The shortcut cb means here containing block. I didn't know about #1645 but I don't like the measure names suggested there. They are too generic.
BTW, concerning the bounding box of two differnt padding boxes of inline elements item 4.1. of the definition of containing block in CSS2.1, I have made a few tests which showed that Firefox and Chrome have different options conerning the dimenstions of the containing block.

Concerning the inherit() funcction, my understanding is that it only refers to parent element properties. In that case, inherit() does something diffenent than my suggested of <property> semantics. I am not nailed to the syntax which I suggested, and an alternative would be to also use a function like cb(<property>) such that one can write calc(0.1 * cb(height)) in accordance with the inherit() function but 10% of height is shorter. The disadvantage of the latter is that it is not obvious to which element height is related. An alternative would be to use the syntax 10% of cb(height).

  • If the containing block does not refer to an element, and also not to the viewport, a rule using of <property> should be ignored.
  • If the containing block refers to the viewport, the properties height and width make sense and the viewport height and width should be used. All properties concerning padding and margin would return a length of 0, as the viewport can be interpreted as having a margin and padding of size 0. If other properties are used, the complete rule can be ignored.
  • If the containing block refers to an element, of <property> should return the same as inherit() but refering to the containing block element and not the parent element.

So, of width and of height refer to the width and height of the element or the viewport but not to the width and height of the containing block. Measures should be used in the latter case.

The ability to refer to arbitrary properties of the containing block may be unnecessary or unwanted for some people but it opens up more flexibility for the author of stylesheets, and maybe some new ideas concerning the usage open up new ways for layouts or special designs which were not possible with CSS today Of course, having new measures for the containing block is a first step in that direction.

@Loirooriol
Copy link
Contributor

If the containing block refers to an element, of <property> should return the same as inherit() but refering to the containing block element and not the parent element.

What if you use height: 50% of height where the element establishing the containing block has a computed height of 75% or max-content? What if the containing block rectangle is a grid area much smaller than the establishing grid container element?

@RolandHeinze
Copy link
Author

@Loirooriol

What if you use height: 50% of height where the element establishing the containing block has a computed height of 75% or max-content?

Percentage values for height already refer to the height of the containing block (see Calculating percentage values from the containing block). If the containing block includes padding, the padding can simply be substracted from the containing block height and You get the height of the content box, or the border height can be added, and You get the border box height. Therefore, it should not be a problem to compute of height in that case.

What if the containing block rectangle is a grid area much smaller than the establishing grid container element?

Can You please explain in more detail what the problem is that You are concerned about?

@Loirooriol
Copy link
Contributor

Percentage values for height already refer to the height of the containing block

They refer to the height of the containing block rectangle. Not to the computed value of the height property on the element that establishes the containing block, as inherit() would do (if the containing block is established by the parent). What I'm saying is that the feature that you want should probably use the former, just like percentages do now.

Can You please explain in more detail what the problem is that You are concerned about?

#grid {
  display: grid;
  height: 100px;
  grid-template-rows: 10px 90px;
}
#grid-item {
  grid-row: 1;
  height: 50% of height;
}

Again, this should likely use the containing block rectangle. So just like height: 50%, it would be 50% of 10px, 5px. Not 50% of 100px, 50px.

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

4 participants