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-contain-3] "container width" and "container height" units #5888

Closed
una opened this issue Jan 22, 2021 · 37 comments
Closed

[css-contain-3] "container width" and "container height" units #5888

una opened this issue Jan 22, 2021 · 37 comments

Comments

@una
Copy link
Contributor

una commented Jan 22, 2021

Viewport-relative units (such as vh and vw) are commonly used among UI design for sizing and spacing of elements.

With the new container queries spec, authors will want to use such units as container-height (ch) and container-width (cw) for container-based sizing.

An example is using cw units in srcset similarly to how one would use vw units in srcset. Percentages would not work in that instance, as the value needs to be absolute or relative length.

Edit: ch would not work as a unit name due to the existing ch (character) unit

@dbaron
Copy link
Member

dbaron commented Jan 22, 2021

The ch unit already exists with a different meaning (short for "character"), so this will at least need a different name.

@jimmyfrasche
Copy link

ew and eh

@nigelmegitt
Copy link

rw and rh would match the identically named <length> units in TTML2, in the case that the container is the root container region, which makes sense e.g. for playing captions over a video container, where it is normal to render text at a height proportional the height of the video.

@una una changed the title [css-conditional] [css-contain] cw and ch units [css-conditional] [css-contain] "container width" and "container height" units Jan 25, 2021
@una
Copy link
Contributor Author

una commented Jan 25, 2021

@nigelmegitt I like the idea of using "root" in the name here. Potentially also "root container width" (rcw) and "root container height" (rch) to specify container from root. I also like rw and rh

@chrishtr
Copy link
Contributor

@mirisuzanne

@mirisuzanne
Copy link
Contributor

Yeah, I'm totally in favor of this, and think it would be very useful. My understanding was that container-relative units would have an additional performance cost with every use, making them likely too expensive. I would love to find out that I mis-understood.

There has been some previous discussion of this in other container query threads.

@astearns astearns added this to the VF2F-2021-02-11 APAC milestone Feb 2, 2021
@astearns astearns added this to Feb 11 in Feb 2021 vf2f Feb 2, 2021
@astearns astearns moved this from Feb 11 earlier to Feb 11 later in Feb 2021 vf2f Feb 2, 2021
@lilles
Copy link
Member

lilles commented Feb 2, 2021

Container units would be as costly as vh/vw for @media query changes, I suppose. Blink marks computed styles for an element with a flag saying that it relies on viewport units and such elements have styles recomputed when the viewport size changes. Same should work for container units/queries.

@fantasai
Copy link
Collaborator

Note, we use 'r' as a prefix currently for the root element e.g. in rem and rlh so probably should avoid that as a prefix here.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-conditional] [css-contain] "container width" and "container height" units.

The full IRC log of that discussion <astearns> topic: [css-conditional] [css-contain] "container width" and "container height" units
<astearns> github: https://github.com//issues/5888
<dlibby> una: this issue is regarding a new sizing unit
<dlibby> una: one for container width and one for height, how inline vs. block is used
<dlibby> una: could be something useful for ui designed, similar to vw/vh
<dlibby> una: could be related to srcset based on container width, probably want different images based on container size
<florian> q+
<emilio> q+
<jensimmo_> A big +1 from me for CW and CH. Or even just a unit in the inline direction if that's only what's possible. Such a thing will be very useful.
<dlibby> una: would like to get consensus on whether this concept (container-sized units) makes sense
<dlibby> astearns: clarify - these units would key off of container size we discussed before?
<astearns> ack florian
<dlibby> una: yes, could use for widths or similar to other viewport unit usage
<fremy> q?
<dlibby> florian: viewport units are useful, this sounds useful too. perhaps we already have this via percentage
<dlibby> florian: if this is direct parent, then % gives you this - examples where this is not true?
<bkardell_> % doesn't work if it isn't your parent tho
<dlibby> leaverou: font-size is one example
<dlibby> florian: realize there are cases where it doesn't work, but are those real use cases
<astearns> ack emilio
<iank_> re: only your direct parent -> except in quirks mode :P
<dlibby> emilio: this would resolve at computed value time?
<dlibby> una: yes
<dlibby> emilio: the thing with srcset is that it might not quite work - how do they evaluate in media queries?
<dlibby> emilio: assume these would resolve against viewport size. don't want to wait until layout to start loading images, since it's a bit circular
<dlibby> astearns: (this is the next issue)
<leaverou> +1 for adding these units, if they are implementable
<dlibby> emilio: sounds workable as long as we have a strong definition of what a container is
<jensimmo_> q?
<leaverou> perhaps cnw and cnh for names? (since ch is taken)
<dlibby> astearns: other comments/concerns?
<fremy> also +1 from me
<dlibby> jensimmons: big +1, when teaching viewport units people like them but not quite what they want
<dlibby> jensimmons: could really be useful for font-sizing
<dlibby> jensimmons: percent could work for margins, but this seems like something people will get excited for
<dlibby> jensimmons: if we only get inline direction, maybe a minor limitation, but better than today
<dlibby> astearns: could see vw convert to this quickly
<jensimmo_> border thickness is another thing that cannot be done with %
<dlibby> astearns: see enthusiasm and support - resolve to pursue container units along with container queries?
<dlibby> florian: we know we can have 2d containment, we suspect 1d, not sure on block - should this influence which units we want to expose?
<leaverou> also is the container width unit essentially a container inline unit? Does it change with writing mode?
<leaverou> (if so the unit could just be ci and cb)
<fantasai> leaverou, I think we should pick a prefix that can be expanded in the future, so probably a 2-letter prefix
<dlibby> astearns: not quite sure followed previous discussion, though we were going to have a draft with 2d and everything, see what we can get
<leaverou> fantasai: fair point
<dlibby> florian: i think we can do 2d and inline, but not sure if we can do block
<dlibby> florian: or we won't do block yet, at least
<dlibby> iank: highly unlikely to be able to do block only
<dlibby> iank: would like to make sure we have use cases for block direction
<astearns> ack fantasai
<dlibby> jensimmons: border could be interesting. could set it 1/10th of inline, 1/10 of block on rectangular box
<dlibby> fantasai: if we add block or things that may or may not exist need to define if they don't
<dlibby> fantasai: also should have a consistent prefix, 'c' and 'r' are problematic currently
<dlibby> fantasai: pick one we're unlikely to use or use a two letter combo
<dlibby> una: rch sound good
<dlibby> fantasai: we have to be careful as existing letters at the beginning won't work
<dlibby> una: let's bikeshed in the issue
<fantasai> r is particularly problematic since we're using it as a prefix for root
<dlibby> jensimmons: liked leaverou's thought of only allowing inline/block instead of height width
<dlibby> una: i'd like to keep symmetry of vw/vh to this proposal
<dlibby> una: but do like inline/block
<dlibby> fantasai: viewport units have logical units already
<fantasai> (vi and vb)
<dlibby> astearns: let's bikeshed in the issue, get examples of what the CSS really looks like
<dlibby> astearns: any objections to adding units, name tbd
<dholbert> it's also worth thinking / defining what happens when the item & the container have orthogonal writing modes

@astearns
Copy link
Member

I got ahead of the bot:

Also should consider 4 names for height/width and inline/block
RESOLVED: add new units to express container dimensions

@matthew-dean
Copy link

Yeah, I think I came up with aw / ah / ai / ab (for allocated width, height, inline-axis, block-axis), but could also be: qw / qh / qi / qb? (For queried units?)

@matthew-dean
Copy link

matthew-dean commented Feb 12, 2021

Also relevant: WICG/container-queries#12 (comment)

WICG/container-queries#12 (comment)

So whatever the "prefix", should have [x]min and [x]max to correspond with viewport units? (So, 6 names, @astearns ?)

@fantasai
Copy link
Collaborator

Important comment from @dholbert in those minutes: need to consider what happens when the element and container writing modes don't match.

@LoganDark
Copy link

cx and cy

@davewallace
Copy link

bw for box width, bh for box height 📦

@Martinspire
Copy link

Martinspire commented Apr 27, 2021

What if not CO was the shorthand, but CT instead? So CTW (container width) and CTH (container height) instead of COW and COH? In the past I've seen many projects using containers and ct to prefix stuff instead of co. It prevents making words that don't make sense (like cow) and still is similar enough to container...

Alternatively, one could imagine that character would get a different name here if it conflicts with easy container references, since that isn't widely used anyways and allowing like CHR instead of CH for character in other places would make it deprecated soon anyways. Looking at how widely it is used, might make sense to see if its up for replacement.

I also like the box one from @davewallace above. Since you can have containers in containers, its not much different from boxes in boxes. It would also help shave off a few characters to make filesize a little shorter.

@mirisuzanne
Copy link
Contributor

Important comment from @dholbert in those minutes: need to consider what happens when the element and container writing modes don't match.

Since vi and vb resolve based on the root element’s writing mode, I expect we would use the container writing mode here. That has the advantage of ensuring that the containment axis and unit axis always match: when the container has inline containment, the inline units match the contained dimension.

@mirisuzanne
Copy link
Contributor

Well, both my example fallbacks are based on existing CSS mechanisms. One is used for parse-time issues like invalid syntax, while the other is used for computed-value-time issues like invalid custom properties.

Looking back through the transcript, it seems like we plan resolve these units at computed value time, which means we're in custom-property (invalid-at-computed-value-time/IACVT) territory. So, having suggested it, I now think we can't use the parse-time fallback, even if we wanted to? So that complicates things a bit more.

I think ideally we might want:

  • A decent default that ensures we always get some value, even if it's not ideal in all cases (are there better options than viewport?)
  • Some way to provide an IACVT fallback, to override that default

@lilles
Copy link
Member

lilles commented Jun 8, 2021

As you mentioned, this won't work since the first declaration will be dropped at parse time as long as the 'cw' unit is supported at all:

p {
  padding: 1em;
  padding: 10cw; /* ignored if no width-query is possible */
}

If you resolve against 0 or the viewport dimensions, could one use calc with the existing min()/max() functions, or would that bee too hard to do predictably because you cannot predict if the fallback will be narrower or wider than a working container?

@andruud
Copy link
Member

andruud commented Jun 8, 2021

For that kind of fallback, just make it possible to query for a given container type?

p { padding: 1em; }

@container (inline-size) {
   p { padding: 10cw; }
}

custom-property territory

I don't think we're automatically in custom-property territory here, we should first try to be in em-territory (which is also resolved computed value time).

@dvdherron
Copy link

a suggestion for units I don't think I've seen yet: qw, qh ( query-width, query-height? )

@una
Copy link
Contributor Author

una commented Jun 10, 2021

I like qw and qh to not clash with ch (more than rcw and rch)

@mirisuzanne mirisuzanne changed the title [css-conditional] [css-contain] "container width" and "container height" units [css-contain-3] "container width" and "container height" units Jun 11, 2021
@mirisuzanne
Copy link
Contributor

mirisuzanne commented Jun 11, 2021

Just to flesh that out into the six value we need:

  • qw: 1/100th of the container width
  • qh: 1/100th of the container height
  • qi: 1/100th of the container inline-size
  • qb: 1/100th of the container block-size
  • qmin: the smaller of qw and qh
  • qmax: the larger of qw and qh

(the only potential confusion here might be with the Q unit?)

In each case, the value can only be resolved inside a container of the appropriate type. As an initial draft, I'm proposing that unresolved container-units default to zero. Any other fallback seems dangerous and unpredictable. Zero may seem dangerous, but I think it can work well in practice.

The calc(), min(), max(), and clamp() functions already provide a fairly reliable way to specify fallback values. Consider these uses, assuming there is no container:

.examples {
  font-size: calc(1em + 0.2qmin); /* 1em */
  font-size: clamp(1em, 5qw, 3em); /* 1em */
  font-size: clamp(1em, max(5qw, 3vw), 3em); /* clamp(1em, 3vw, 3em) */
  padding: max(2qh, 1em) max(2qw, 1em); /* 1em 1em */
}

And, as mentioned by @andruud above, we can ensure they resolve by specifying them inside the appropriate @container queries. (I'll start with this as the draft spec, and we can revisit before publishing)

@matthew-dean
Copy link

matthew-dean commented Jun 11, 2021

(the only potential confusion here might be with the Q unit?)

That.... is a very unusual unit. I would petition to have that one (Q) removed before that proposal exits draft status, personally, partly for its unusualness (upper-casing? single letter? seems very strange), partly because I don't see the need, and partly because of this proposal.

@Crissov
Copy link
Contributor

Crissov commented Jun 12, 2021

q could have been called qmm to make it more transparent for people unfamiliar with it, but for those that are actually using it, q is the appropriate symbol they are used to. (Some might say kyu would have been fine as well.)
It’s been in CSS for a while now and is not going to be changed.

@mirisuzanne
Copy link
Contributor

mirisuzanne commented Jun 17, 2021

For that kind of fallback, just make it possible to query for a given container type?

p { padding: 1em; }

@container (inline-size) {
   p { padding: 10cw; }
}

@andruud This ensures that that there is a proper container for the unit, but it doesn't ensure it's the nearest ancestor container referenced by the unit. We would still need to say that units evaluate against the nearest container of the appropriate type. And that puts us back in a situation where units could evaluate against multiple containers:

<div style="container: size;">
  <div style="container: block-size;">
    <div style="container: inline-size;">
      <div style="container: style;">
        <p>how do container units evaluate on this paragraph?</p>
      </div>
    </div>
  </div>
</div>

Which container is used for the various units?

p {
  /*  style (nearest)? block-size (of-type)? */
  margin: 1qb;

  /*  style (nearest)? inline-size (of-type)? */
  padding: 1qi;

  /*  style (nearest)? size (of-type)? or inline-size & block-size, individually per axis? */
  font-size: 1qmax;
}

@andruud
Copy link
Member

andruud commented Jun 18, 2021

That's a different question, but OK, how about making the units evaluate against the selected container (see "container selection process") for the container-query/element pair?

/* (Syntax borrowed from https://github.com/w3c/csswg-drafts/issues/6393). */
@container type(inline-size) {
   p { padding: 1qi; }
}

Here qi evaluates against whatever is the current selected container is for the matched element. This way authors have full flexibility.

Otherwise, if there is no enclosing @container rule, it evaluates against the nearest container (no mercy).

Worse ideas:

  • A function which can be used to select the container explicitly? calc(1 * qi(<selection>)) (beautiful).
  • Custom units and an API to define them?

@mirisuzanne
Copy link
Contributor

@andruud lol, no mercy.

If I were to do something like this now, without container queries, I would likely set eg --qi and --qb custom properties on each container with inline or block containment respectively, using JS. Then I would inherit them, and determine the other units from there:

[data-container~="inline-size"],
[data-container~="size"] {
  --qi: <set via JS>;
}

[data-container~="block-size"],
[data-container~="size"] {
  --qb: <set via JS>;
}

[data-container] * {
  --qmin: min(var(--qi, 0), var(--qb, 0));
  --qmax: max(var(--qi, 0), var(--qb, 0));
}

When I think of it that way - it doesn't bother me that the two dimensions might come from different containers. I feel like each unit represents the best info we have about the given axis. So that's making me lean towards doing unit container selection for each axis individually, as though qi represents @container type(inline-size) and qb represents @container type(block-size), and the other units are derived from those.

Then we only need the (merciless) fallback when there is no container in the requested dimension.

@andruud
Copy link
Member

andruud commented Jun 18, 2021

(Great, you already have a solution! :P)

While not impossible to have different units do their own "implicit container selection", it sounds like a mess to me. And of course it will add much-unneeded paper cuts to performance. (EDIT: Actually I'm not sure about that paper cut part).

  • What if the unit exists inside an at-container rule which selects some higher-up named container? Having multiple interpretations of the what the selected container is in the same context is what seems like a mess.
@container foo (...) {
   p { padding: 2qi; } /* Still resolves against nearest container with inline-size?! */
}
  • Is it a commonly needed to use qmax/min with different containers for each axis? If not, perhaps your way is actually good enough if CSSified?
@property --qi {
  syntax: "<length>";
  initial-value: 0px;
  inherits: false;
}

@property --qb {
  syntax: "<length>";
  initial-value: 0px;
  inherits: false;
}

@container somelevel {
  p { --qi: 2qi; }
}

@container anotherlevel {
  p { --qb: 2qb; }
}

p { padding: max(var(--qi), var(--qb)); }

(EDIT: The above code assumes units resolve against the container selected by the enclosing container query).

But I can see how that's a bit verbose if it's a common thing.

@mirisuzanne
Copy link
Contributor

I expect the vast majority of containers to be single-axis or style/state containers. Two-axis size containers are likely to be very rare. I think that makes your approach extremely limiting - these units would only be usable one at a time in very restricted ways. We'll almost never be able to combine inline & block units:

@container my-inline-container (...) {
  /* only inline units can be used in here? */
}

We would rarely be able to use qmin or qmax, or anything like padding: 2qb 2qi with both inline & block units in a single property. The min/max units would only be allowed when querying a 2d container, and the combined property would have to be split into individual queries.

This approach is also complicated by nested container rules:

@container my-inline-container (...) {
  @container my-block-container (...) {
    /* which container do we use for units in here? */
  }
}

The only way we can make these units broadly available & combine-able is to make them self-select their containers. I don't see a viable way around that.

@andruud
Copy link
Member

andruud commented Jun 21, 2021

@mirisuzanne Ack. To be clear then, container units basically ignore the container selection provided by the enclosing @container rule (if any), and do their own selection entirely?

@mirisuzanne
Copy link
Contributor

@andruud yes, that's my proposal. The units work completely independent of @container rules. So inside @container they would behave more like a nested query, rather than a reference to the outer query. I expect in practice some of the units are likely to reference the same container, but not all of them.

I've updated the editor's draft with that behavior.

@mirisuzanne
Copy link
Contributor

Agenda+ to discuss and get resolution on the the specified approach.

  • The unit names are:

    • qw: 1/100th of the container width
    • qh: 1/100th of the container height
    • qi: 1/100th of the container inline-size
    • qb: 1/100th of the container block-size
    • qmin: the smaller of qw and qh
    • qmax: the larger of qw and qh
  • Each unit is resolved in relation to the nearest ancestor with an appropriate container-type for the given dimension (where logical units are resolved based on the container's writing mode). That means a qi unit will resolve against the nearest ancestor with container-type of size or inline-size, and a qb unit will resolve against the nearest ancestor with container-type of size or block-size -- so the different axis units can resolve against different containers, and the qmin/qmax units will use the smaller/larger value, even if they come from different containers.

  • If no eligible query container is available, then use the small viewport size for that axis.

@jensimmons
Copy link
Contributor

jensimmons commented Oct 6, 2021

Typing this out in the meeting so we can see it:

  • qw: 1/100th of the container width
  • qh: 1/100th of the container height
  • qi: 1/100th of the container inline-size
  • qb: 1/100th of the container block-size
  • qmin: the smaller of qw and qh
  • qmax: the larger of qw and qh
.examples {
  font-size: calc(1em + 0.2qmin); /* 1em */
  font-size: clamp(1em, 5qw, 3em); /* 1em */
  font-size: clamp(1em, max(5qw, 3vw), 3em); /* clamp(1em, 3vw, 3em) */
  padding: max(2qh, 1em) max(2qw, 1em); /* 1em 1em */
}

or

  • cqw: 1/100th of the container width
  • cqh: 1/100th of the container height
  • cqi: 1/100th of the container inline-size
  • cqb: 1/100th of the container block-size
  • cqmin: the smaller of cqw and cqh
  • cqmax: the larger of cqw and cqh
.examples {
  font-size: calc(1em + 0.2cqmin); /* 1em */
  font-size: clamp(1em, 5cqw, 3em); /* 1em */
  font-size: clamp(1em, max(5cqw, 3svw), 3em); /* clamp(1em, 3svw, 3em) */
  padding: max(2cqh, 1em) max(2cqw, 1em); /* 1em 1em */
}

Also we now have:

  • svh
  • lvh
  • dvh
  • svw
  • lvw
  • dvw
  • svmin
  • lvmin
  • dvmin
  • svmax
  • lvmax
  • dvmax

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-contain-3] "container width" and "container height" units, and agreed to the following:

  • RESOLVED: Use cq as the prefix
The full IRC log of that discussion <dael> Topic: [css-contain-3] "container width" and "container height" units
<dael> github: https://github.com//issues/5888
<dael> miriam: earlier resolved we wanted them and went back to give names. Can't give 'c'. Best I saw was 'q' units. q-width, etc.
<florian> I like "q*"
<dael> astearns: Some people in issue have concerns about mix with q typographical, but I don't think we should worry
<dael> TabAtkins: same
<dael> astearns: was cq- considered?
<dael> miriam: I don't remember seeing that
<dael> astearns: I don't know I'm going to argue in favor of it
<dael> jensimmons: We did have vh and now we have lvh. Don't know if that leads us anywhere with this
<dael> jensimmons: Kontainer :)
<dael> astearns: fantasai on irc says c doesn't add much
<dael> jensimmons: Something with q. Agree it's a little awk but q just as a letter is nice
<dael> astearns: Anyone that wants to argue against the spec approach of q?
<fremy> I feel like qw is liked becaue people use QWERTY keyboards ^_^
<dael> astearns: prop: Go with specified approach using q
<heycam> "queried width" reads well
<dael> plinss: We do have q unit
<fremy> Doesn't feel as special on AZERTY ^_^
<dael> astearns: We do. Was discussion in issue about possibility of confusion. I think people that understand what q unit is will not be confused. People who don't know won't know it exists
<dael> plinss: Concern with future name collisions
<dael> emeyer: That was my concer with future names
<dael> astearns: Future that spawn their own units
<dael> plinss: Last time we went through I raised concern on explosion of unit types
<RRSAgent> logging to https://www.w3.org/2021/10/06-css-irc
<dael> astearns: Do you have a solution? We seem to be proliferating unit types. I agree 2 letter names are sometimes difficult
<dael> plinss: Function
<emeyer> q+
<dael> fantasai: If people type function names in parens when they want to use a unit they'll be unhappy. We have units for a reason and abbreviate for a reason so we should continue. Agree we should avoid collisions but at least following a pattern
<dael> plinss: Want to make sure this really need to be a unit and not that we're doing it because we did it before. not saying that's case here but need guidance for next one
<emeyer> My muting has gone crazyz.
<emeyer> I do want to advocate for cq. It’s more mnemonic.
<astearns> ack emeyer
<dael> astearns: emeyer advocates cq as the mnemonic. Does protect against possible future query units.
<emeyer> It would set a precedent of being more mnemonic with any future units.
<emeyer> That’s all from me.
<dael> astearns: Anyone that would object to using cq instead of merely q?
<TabAtkins> cq fine with me
<miriam> also ok with me
<fremy> cqw cqh sound fine
<dael> astearns: plinss you're okay adding these units because see need for them to be units but would like more guidlines of when units are necessary?
<dael> plinss: I don't have opinion on if these should be units. Haven't given much thought. I do want clear guidelines as to what should be a unit and why.
<dael> astearns: I think we need units b/c will use in same way as viewport units today.
<dael> astearns: I see comment from jensimmons ?
<dael> jensimmons: I wanted to see what it looked like
<dael> astearns: And what do you think?
<dael> jensimmons: Dunno
<dael> astearns: I think cq looks weird but may be because I looked at q for a while
<florian> I like the shorter version, but not to the point of blocking if we want to go the other way
<dael> astearns: I am swayed by future proofing to keep from future query units. cq provides distance from q unit
<dael> astearns: Prop: Use cq as the prefix
<dael> astearns: miriam okay with you?
<dael> miriam: Yeah
<dael> astearns: Objections to spec ch?
<dael> RESOLVED: Use cq as the prefix

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

No branches or pull requests