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-sizing] Adding a 'size' shorthand for 'width'/'height' #820

Open
tabatkins opened this issue Dec 19, 2016 · 58 comments
Open

[css-sizing] Adding a 'size' shorthand for 'width'/'height' #820

tabatkins opened this issue Dec 19, 2016 · 58 comments

Comments

@tabatkins
Copy link
Member

@tabatkins tabatkins commented Dec 19, 2016

Many people thruout the years have requested a 'size' property as a shorthand for 'width' and 'height', for the common cases when you want to set them both to the same value. (Either making the element square, or making it a similar rectangle to the containing block with percentages, or using the same keyword for both.)

This seems mildly useful, but it has a naming problem - the @page rule already has a 'size' property, and it's not a shorthand for the 'width' and 'height' properties @page also has. ('size' sets the size of the margin box, while 'width' and 'height' set the content box.)

Other suggestions for names?

@astearns
Copy link
Member

@astearns astearns commented Dec 19, 2016

dimensions (probably too long and difficult to spell)
area (not quite the right meaning)
embiggedness (the real reason I'm adding this comment)

I've added this to the list of mistakes

@frivoal
Copy link
Collaborator

@frivoal frivoal commented Dec 20, 2016

Also, just to put it out there, how bad would it be if we added this under the size name and kept @page's size stay the way it is, effectively making the size shorthand unavailable in @page?

On the one hand, this is dirty and there is no precedent for properties meaning completely different things in different context, on the other hand, the usages seem really disconnected, and authors would likely cope just fine.

(and on the third hand, it isn't entirely clear why size in @page is considered a property rather than a descriptor, but it doesn't really make much of a difference anyway, so ignore my 3 handed monster).

@Crissov
Copy link
Contributor

@Crissov Crissov commented Dec 20, 2016

box, content-box …, box-size

@frivoal
Copy link
Collaborator

@frivoal frivoal commented Dec 20, 2016

Not content-box, as that would be the wrong name when box-sizing: border-box is on.
As for box, it doesn't seem wrong, but it's awfully generic.

@inoas
Copy link

@inoas inoas commented Dec 20, 2016

I don't see the benefit. I'd rather not pollute the property space with property names that yield little benefit. If you want to set both, then just set both.

p.s.: What would be more interesting is aspect-ratio values for height and width (behaving similar to auto, insofar as that they will scale when one value is set or the other).

@Crissov
Copy link
Contributor

@Crissov Crissov commented Dec 20, 2016

Without added features beyond a shorthand, such a new property would be nonsense anyway.

<box>: [ <width> <height>? | <width> <box-aspect> | <box-aspect> <height> ] || <box-sizing>
<box-aspect>: <<number>> | <<integer>> '/' <<integer>> | 'golden' | 'sqrttwo'

PS: Maybe box-ratio makes more sense than box-aspect.

@inoas
Copy link

@inoas inoas commented Dec 20, 2016

What would take precedence if width/height and new-property are set and values are conflicting?

I'd argue something like this would make sense:

.block {
  height: 640px; /* change this through MQ */
  width: 480px;  /* change this through MQ */
}
img.some {
  display: block;
  width: 100%;
  height: aspect(0.5);      /* set's the height to half of the width */
  height: auto(0.5);        /* set's the height to half of the width */
  height: auto-aspect(0.5); /* set's the height to half of the width */

  height: aspect-ratio(0.5);  /* set's the height to half of the width */
  height: aspect-ratio(golden);  /* set's the height to golden cut */
  height: aspect-ratio(calc(9/16));  /* set's the height to 16:9 */
}
@tabatkins
Copy link
Member Author

@tabatkins tabatkins commented Dec 22, 2016

This topic is not about a theoretical aspect-ratio property; please move any such discussion to a different issue. (There might already be one started for that.)

@inoas
Copy link

@inoas inoas commented Dec 22, 2016

@tabatkins so on the constructive side:
What would take precedence if width/height and new-property are set and values are conflicting?
What are the functional benefits?

@Crissov
Copy link
Contributor

@Crissov Crissov commented Dec 23, 2016

The issues are connected however, @tabatkins, because it could make sense to name them all box-* and combine them in a box shorthand property – or only add that. The syntax of an aspect ratio property or function should be discussed separately, though.

<box>: <box-size> || <box-sizing>
<box-size>: [ <width> <height>? | <width> <box-aspect> | <box-aspect> <height> | <box-aspect> ] /* = */
<box-size>: [ <width> [ <height> | <box-aspect> ]? | <box-aspect> <height>? ]
@inoas
Copy link

@inoas inoas commented Dec 23, 2016

@Crissov then the rule would be whatever is set as a property (with the same or higher specificity, obviously) overwrites each other? E.g. would this hold true?

div {
  dimensions: 100px 200px; /* width: 100px, height 200px */
  width: 50px;  /* width: 50px, height: 200px */
  dimensions: 100px; /* width: 100px, height: 200px */

  /* Related / Off-Topic: */
  dimensions: 100px aspect-ratio(calc(9/16)); /* width: 100px, height: 56.26px */
}
@Crissov
Copy link
Contributor

@Crissov Crissov commented Dec 23, 2016

I'd say that a single length makes the box square – assuming 1:1 is the default aspect ratio that the shorthand resets to:
100px × 200px @ 1:2 → 50px × 200px or 50px × 100px → 100px × 100px.

It could also keep the current AR, hence
100px × 200px → 50px × 200px → 100px × 400px.

Alas, then width before should do, too, i.e.
100px × 200px @ 1:2 → 50px × 100px → 100px × 400px.

Otherwise, yes box and box-size would work like other shorthand properties. The WG would decide the most useful and compatible approach.

@fantasai
Copy link
Collaborator

@fantasai fantasai commented Dec 27, 2016

@inoas Precedence is calculated by the cascade, as size would be a shorthand property. See https://www.w3.org/TR/css-cascade/#shorthand-property

@Crissov As Tab said, please take discussion of aspect ratios elsewhere. This issue is literally just a naming conflict issue.

@fantasai
Copy link
Collaborator

@fantasai fantasai commented Dec 27, 2016

@inoas Oh, as for the benefit: there are many times when one wants to set both width and height, or both min/max-width and min/max-height, to the same thing. It's not commonly desired for length values (since that would always make a square), but for keywords and percentages it is.

@Crissov
Copy link
Contributor

@Crissov Crissov commented Dec 27, 2016

@fantasai The detour to aspect ratios was necessary, for me at least, to prefer box-size over just box as an alternative to size. @tabatkins didn’t specify the exact syntax or scope of the shorthand nor link to one, so it’s difficult to suggest an alternative without considering such side issues.

@fantasai
Copy link
Collaborator

@fantasai fantasai commented Dec 28, 2016

It would be size: <'height'> <'width'>? with omitted <'width'> taken from <'height'>. Basically your standard shorthand.

@inoas
Copy link

@inoas inoas commented Dec 28, 2016

@fantasai <'height'> <'width'>? would be consistent with how padding and margin with 2 values works in terms of the direction (horizontal, vertical), however elsewhere sizes are usually defined width first then height. That's the only thing that would make me worry a little tiny bit.

Thanks for pointing to the shorthand block. I just wasn't aware of the nomenclature. That clears the conflicting (that isn't there!).

Edit: box-size is too close to box-sizing and can easily be confused, IMHO.

@fantasai fantasai added the Agenda+ label Feb 16, 2017
@jonathantneal
Copy link
Contributor

@jonathantneal jonathantneal commented Feb 22, 2017

this is dirty and there is no precedent for properties meaning completely different things in different context

Are there other concerns with @frivoal’s suggestion that the @page at-rule could define its own context where size uses the existing meaning? To me, this seems worth exploring, as the alternatives seem far from the cowpath.

@Crissov
Copy link
Contributor

@Crissov Crissov commented Feb 22, 2017

@inoas The similarity of box-size and box-sizing would be a feature, not a bug, in my opinion – also possible:

box-size: <'height'> <'width'>? || <'box-sizing'>?

or, of course,

box-size: <'width'> <'height'>? || <'box-sizing'>?
@fantasai
Copy link
Collaborator

@fantasai fantasai commented Feb 22, 2017

Note also that inline-size and block-size use the word size, so using any other term would be inconsistent with those.

@tabatkins
Copy link
Member Author

@tabatkins tabatkins commented Feb 22, 2017

Conclusion from today's call: currently tabling this issue. We can unblock it with:

  • implementor interest in using 'size', despite the minor implementation concerns that it brings due to context-difference between normal styles and @page
  • a new name that meets broad agreement.
@astearns astearns removed the Agenda+ label Feb 22, 2017
@jonathantneal
Copy link
Contributor

@jonathantneal jonathantneal commented Feb 22, 2017

What does implementor interest look like? Are outsiders (those who don’t work with browser vendors) capable of helping in this area?

If an implementor is interested, how blocking is the later issue. I’m just not clear if this is an either/or list.

@astearns
Copy link
Member

@astearns astearns commented Feb 22, 2017

It's an either/or list.

If we can come up with a name that isn't 'size' that is really good for the author experience, then it's relatively easy to spec and implement.

Or if there is enough author convenience in a shorthand named 'size' that convinces implementors to take it on, we can progress with that name. My understanding (as a non-implementor) is that this approach is slightly more complicated, and no one has (yet) considered this shorthand worth the effort to implement. Bugs, blog posts and bribes are needed.

@upsuper
Copy link
Member

@upsuper upsuper commented Feb 23, 2017

I have another concern for serialization. If we add size (or whatever it would be called), the following block

div {
  width: 200px;
  height: 100px;
}

would suddently be serialized to something like size: 200px 100px;.

Code may be broken if they rely on parsing the serialization themselves. Not sure how usual this can be, though.

@heycam
Copy link
Contributor

@heycam heycam commented Oct 16, 2019

Suggestion seems fine to me. To clarify, CSSPageRule.style.getPropertyValue("size") would return an empty string, and you'd need to pass the real descriptor name "page-size" to get its value?

@css-meeting-bot
Copy link
Member

@css-meeting-bot css-meeting-bot commented Oct 16, 2019

The CSS Working Group just discussed Adding a 'size' shorthand for 'width'/'height', and agreed to the following:

  • RESOLVED: We are redefining the size property in @page to be called page-size. Also defining that size in the page context parses into page-size. The size property is a shorthand for width and height
The full IRC log of that discussion <dael> Topic: Adding a 'size' shorthand for 'width'/'height'
<dael> github: https://github.com//issues/820
<dael> TabAtkins: discussed in past. Useful b/c size often set together. @page rule has a size declaration and we can't collide names.
<dael> TabAtkins: fantasai had a great suggestion to unblock. Rename @page declaration to page-size. Define @page has a parse time alias of size turning into page-size and that frees up size.
<dael> TabAtkins: Any existing pages using size will work. Anyone using CSSOM to page @page will see a page-size property. I suspect that's almost 0 since @page is only useful in printing. Printing doesn't have much JS support. Almost no possible breakage and this will let us do the size thing we've wanted to do for at least a decade.
<dael> TabAtkins: Clever way to get what we want.
<dael> florian: I think you're slightly overstating lack of JS support, but I agree with the argument
<dael> Rossen_: It's a cool proposal. I'm in favor. Other opinions?
<dael> dauwhe: I'll try and contact Prince about this
<dael> dauwhe: They're a PDF formatter that uses @page and supports JS
<dael> Rossen_: Should we wait?
<dael> dauwhe: No, go ahead
<dael> Rossen_: Thanks for the reach out
<dael> florian: Since this is new aliasing should we be explicit about how it can be used
<dael> fantasai: It's defined at parse time and you never see the other name.
<dael> florian: Of CSS file?
<dael> AmeliaBR: Does become a question. If you use cssom method to pase string that's parsed that is also parse time. Need defined somewhere. Need to define it somewhere for explaining relationship of MS prefixed force-colors vs new force-color
<dael> florian: WE have general aliasing, but this alias is weird
<dael> TabAtkins: Normal is shorthanding based. Property then does show up in all contexts. THis would be not that. Does need clarification. Happy to work to see exactly what to clarify.
<dael> emilio: If can put width and height in @page this would be quirky because size means one thing in @page
<dael> emilio: Can set width and height in @page rule. Means size does something different in @page then everywhere else.
<dael> TabAtkins: That's why we can't overlap. b/c size is not a shorthand in @page
<dael> fantasai: Confusion from naming property anything other than 'size' is higher then size in @page not being width and height
<dael> florian: Dev tools should be warning about this. If page-width exists and you try and use size you should be warned.
<dael> TabAtkins: I don't think any browser respects @page size declaration
<dael> florian: Chrome does
<dael> TabAtkins: Okay. Cool. I think spec should clarify that it's page-size and it's required to do this parsing. And I'll file a bug on our dev tools that we should have a maybe use something else
<dael> Rossen_: Prop: Add size as a shorthand for width and height for everywhere by @page?
<dael> fantasai: Several things. 1) We are redefining the size property in @page to be called page-size.
<dael> Rossen_: Let's resolve there first
<dael> fantasai: Also defining that size in the page context parses into page-size
<dael> fantasai: Once that's resolved, then the size property is a shorthand for width and height
<dael> Rossen_: Objections to these three steps?
<dael> RESOLVED: We are redefining the size property in @page to be called page-size. Also defining that size in the page context parses into page-size. The size property is a shorthand for width and height
<AmeliaBR> (To clarify my earlier comment, the similarity to forced color was that any rule inside the `@media (-ms-high-contrast)` would include an implicit `forced-color-adjust: none` declaration added at parse time. But doesn't look like that got included in the spec, it was just a suggestion of how MS could handle internally.)
@tabatkins
Copy link
Member Author

@tabatkins tabatkins commented Oct 16, 2019

To clarify, CSSPageRule.style.getPropertyValue("size") would return an empty string, and you'd need to pass the real descriptor name "page-size" to get its value?

Yes. My intention (to be clarified in CSSOM working with @emilio or @zcorpan) is that anything which parses a whole declaration or larger will allow "size" and translate it, but anything which just takes a declaration name directly won't know about "size".

@Marat-Tanalin
Copy link

@Marat-Tanalin Marat-Tanalin commented Oct 17, 2019

Hopefully both single-value (size: 10px) and two-values (size: 2em 3em) syntaxes are going to be supported.

@tabatkins
Copy link
Member Author

@tabatkins tabatkins commented Oct 17, 2019

Yes, absolutely.

@bernhardf-ro
Copy link

@bernhardf-ro bernhardf-ro commented Oct 21, 2019

I am with RealObjects. If we may weigh in on the actual usage of CSS Paged Media: Our product PDFreactor, a HTML-to-PDF converter, has been commercially available since 2006 and has supported JavaScript since 2012. Other commercial paged media user agents include Prince, supporting JavaScript since 2011, and Antenna House Formatter.

The introduction of the 'page-size' property and the new behavior of 'size' would be an API change for the CSSOM and derived data structures. For functionalities that have been in production use for years, we'd appreciate if significant changes could be avoided.

We'd like to suggest having another look at the approach where 'size' is a shorthand everywhere and the width and height properties apply to pages, thus eliminating the need for the 'page-size' property. We realize that width and height would be applied to the margin box for pages. However, we don't think that this would create significant confusion. Most importantly, this approach would not cause any breaking changes for authors at all. Please note that we even encountered customers that found it counter-intuitive that width and height cannot be set on pages.

@Marat-Tanalin
Copy link

@Marat-Tanalin Marat-Tanalin commented Oct 21, 2019

@bernhardf-ro

this approach would not cause any breaking changes for authors at all.

Afaict, the change is not breaking since size inside @page will continue to work for the purpose of backward compatibility, effectively being an alias for the new page-size:

Also defining that size in the page context parses into page-size

Still, I agree that renaming size to page-size is probably not necessary, given that size meaning inside @page rules is similar to its new meaning for regular elements, and especially given that size and page-size are going to be interchangeable inside @page anyway, so adding page-size probably just bloats the CSS keyword list.

@faceless2
Copy link

@faceless2 faceless2 commented Oct 21, 2019

According to https://www.w3.org/TR/css-page-3/#fixed-sizing, width and height do apply to paged media. If they are specified, they set the size of the page "content" box, and size is ignored.

Just for completeness, because I haven't seen it suggested yet:

size in the @page context is effectively setting the margin box on the page. I don't know how often the width and height properties are used instead to specify page sizes, but as this option was not in CSS 2.1 I expect it's a lot less common than size.

So another option would be to introduce margin-box as a new values for box-sizing, and use that as the default in the page context. If you allow for a few special values (like "A4" as an alias for "210mm 297mm"), then size becomes the shorthand for width/height without any need to rename anything. The cost is if anyone is using width and height to set the page size, they would need to add a new box-sizing: context-box declaration to their @page rule.

If necessary this could be limited so it only works in the @page context, to avoid complicating css-sizing.

@bernhardf-ro
Copy link

@bernhardf-ro bernhardf-ro commented Oct 22, 2019

Documents accessing the size property of an @page rule in the CSSOM via JS will stop working. So at least technically the change is breaking. We do not have enough data for a detailed estimate on the magnitude of the actual negative effects, but there definitively will be more than none. (We also offer a Paged Media based editing framework, which allows more direct access to the CSSOM for more complex integrations. Those customers would also be affected. So it is not only JavaScript.)

Thanks for pointing out that in the Paged Media specification width and height already affect the page size, specifically the page area (page content box). However, there is practically no support for this in user agents while size is supported and essential in all Paged Media based ones. Also we are not sure about the use cases for basing the page size on its area/content size. So, in our opinion, changing width and height looks preferable to changing size.

Also the behavior of width and height already depends on the context in multiple cases, like inline or table related boxes. Having them affect the margin size, instead of the one from box-sizing, when used in @page is not a complex or confusing special case. (It may even be what authors expect, but that is speculation.)

We also agree that paper sizes like A4 can be handled at the shorthand level and think that would be an elegant solution, also allowing to style any box to have one of the standardized sizes.

Overall the approach of having the shorthand in all cases, including @page, may have more positive effects and opportunities than negative ones.

@tabatkins
Copy link
Member Author

@tabatkins tabatkins commented Oct 22, 2019

Documents accessing the size property of an @page rule in the CSSOM via JS will stop working. So at least technically the change is breaking.

Yes, pagerule.getPropertyValue('size') would stop working; this is indeed a breaking API change.

We also agree that paper sizes like A4 can be handled at the shorthand level and think that would be an elegant solution, also allowing to style any box to have one of the standardized sizes.

A problem here is that shorthands have to re-synthesize themselves from the longhands, but the keywords do not map cleanly to integer px values (and lengths in all UAs are stored as some fixed fraction of a px), which means that if you, say, set size: A4;, you'll read back two decimal-heavy px lengths unless we specify a "close enough" rounding that must return the keyword.

(That's not impossible, but it is new.)

[suggestion to switch @page/width and height to setting the page margin box and making them shorthands of size]

Hm, that's interesting. If you're right that the usage of width/height on @page is lower (and thus will cause less breakage) than the JS querying of size, then that's a reasonable alternative. Getting some feedback from other printing software would be useful here.

@bernhardf-ro
Copy link

@bernhardf-ro bernhardf-ro commented Oct 23, 2019

Getting some feedback from other printing software would be useful here.

We also hope for more parties commenting on this. Maybe adding [css-page-3] to the title would draw the necessary attention.

If it is any help, we found that of 4 user agents that support size (Chrome, PDFreactor, Prince, AH Formatter), 3 do not support width and height at all and the remaining one, AH Formatter, does not resize the page as per the specification.
So, while there is one implementation that does not ignore width and height, its behavior deviates far enough from the specification that making it compliant to the current specification would be as much of a change as adapting it to our proposal.

[what exactly retrieving size should return]

Returning 2 lengths, even after setting an identifier, looks like the best solution to us. Most script authors that have to retrieve the size would benefit from a consistent format and most likely prefer always getting lengths.
For example, size: A4, just like size: 210mm 297mm, should result in width: 210mm; height: 297mm and, in turn, in size: 210mm 297mm.

On the other hand, to keep the identifier if (and only if) it has been set, would be possible, but require passing it to width and height, e.g. width: A4; height: A4, which we consider excessive. It would create a lot of additional work for the sake of symmetry.

@Crissov
Copy link
Contributor

@Crissov Crissov commented Oct 23, 2019

Paper size approximation

Regarding standard page sizes being stored with the canonical unit px (in browsers at least, hopefully not in CSS-to-PDF software): since 24px = 0.25in, US sizes, which are all based on full, half or quarter inches, do not have the problem, but calc(96px/25.4) and calc(25.4mm/96) yield indeed awfully odd numbers, roughly 3.78px and 0.265mm. A4, i. e. 297 mm × 210 mm, would become c. 1122.52px × 793.79px, which, if first rounded to the nearest CSS pixel, converts back to 297.12mm × 210.08mm.

Many PDFs exhibit a similar issue, wherein ISO page dimensions have been converted to an integer number of DTP points, resulting in 297.04 mm × 209.9 mm for instance.

However, ISO 216 specifies tolerances for cut paper sizes that are well beyond such rounding effects: ±1 mm for the sizes that have keywords in CSS if I remember correctly. Also, the sizes are iteratively rounded (floored?) from theoretical √2-based values to an integer number of millimeters anyway. The theoretical size of A4 would be about 297.302mm × 210.224mm or ca. 1123.66px × 794.55px.

In other words, if width and length are within 1mm of an ISO size after having been converted from a px, itʼs pretty safe to assume that the size originally specified was indeed the respective standard format.

New size keywords

This reminded that there are other common sizes that may deserve keywords. (See #328 for paper sizes.) Iʼm not sure theyʼre worth the cost, because their actual values are often at least as familiar as their names and abbreviations, but Iʼm thinking of vga = 640px 480px and the like. Besides <page-size>, size should then also learn orientation modifiers landscape and portrait from @page.

@XiBOR
Copy link

@XiBOR XiBOR commented Jan 24, 2020

Wouldn't it be more convenient to make reductions for all properties at once?
For example:

size: 10px; // width: 10px, height: 10px || min-width: 10, max-width: 10, min-height: 10, max-height: 10
size: 10px 20px; // width: 10px, height: 20px || min-width: 10, max-width: 10, min-height: 20, max-height: 20
size: 10px 20px 30px 40px; // min-width: 10, max-width: 20, min-height: 30, max-height: 40
@Crissov
Copy link
Contributor

@Crissov Crissov commented Jan 24, 2020

size: 10px could also be a shorthand for roughly size: 7.07px 7.07px with an aspect ratio of 1:1, i. e. specify the diagonal or diameter.

@Loirooriol
Copy link
Collaborator

@Loirooriol Loirooriol commented Jan 24, 2020

@Crissov You can use calc(10px * cos(atan(1/1))) and calc(10px * sin(atan(1/1))) for that.
Overcomplicating size with diagonals would be very confusing and unexpected.

@Crissov
Copy link
Contributor

@Crissov Crissov commented Jan 25, 2020

Diagonals would of course only make sense if one could also set the aspect ratio within size:

size: [<'width'> <'height'>] 
    | [<length> || <'aspect-ratio'>] 
@tabatkins
Copy link
Member Author

@tabatkins tabatkins commented May 12, 2020

I'm downloading AH Formatter right now (well, I'm requesting a trial download, we'll see), so I can see what they actually do with 'width'/'height' on pages, per @bernhardf-ro's comment that they're the only implementor that has those descriptors at all, and they do something different than the spec anyway.

Changing the definition of @page/width and @page/height seems like the most viable way forward here, since no one's come up with a reasonable alternate name for 'size'.

@jsnkuhn
Copy link

@jsnkuhn jsnkuhn commented Dec 26, 2020

Would there be a need for min-size and max-size properties as shorthands for min-width/min-height and max-width/max-height? Or would the use of size: clamp() or size: clamp() clamp() be enough to cover all of that?

@SebastianZ
Copy link
Contributor

@SebastianZ SebastianZ commented Dec 28, 2020

Using clamp(), min(), and max() should be sufficient to cover all use cases of min-width, min-height, max-width, and max-height.

Sebastian

@Loirooriol
Copy link
Collaborator

@Loirooriol Loirooriol commented Dec 28, 2020

Note that width: 100px; max-width: 0% and width: min(100px, 0%) have different intrinsic contributions when the containing block is intrinsically sized. https://drafts.csswg.org/css-sizing/#cyclic-percentage-contribution

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

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.