Title: CSS Box Sizing Module Level 4 Shortname: css-sizing Level: 4 Status: ED Work Status: Exploring Group: csswg ED: https://drafts.csswg.org/css-sizing TR: https://www.w3.org/TR/css-sizing/ Editor: Tab Atkins, Google, http://xanthir.com/contact/, w3cid 42199 Editor: Elika J. Etemad / fantasai, Invited Expert, http://fantasai.inkedblade.net/contact, w3cid 35400 Editor: Jen Simmons, Mozilla, http://jensimmons.com/ Previous version: https://www.w3.org/TR/2012/WD-css3-sizing-20120927/ Abstract: This module extends the CSS sizing properties with keywords that represent content-based "intrinsic" sizes and context-based "extrinsic" sizes, allowing CSS to more easily describe boxes that fit their content or fit into a particular layout context. This is a delta spec over CSS Sizing Level 3. Ignored Terms: block-level box
spec:css-display-3; type:dfn; text:box spec:css-align-3; type:property; text:column-gap spec:css2; type: property text: min-width text: min-height text: max-width text: max-height
This module extends the 'width', 'height', 'min-width', 'min-height', 'max-width', 'max-height', and 'column-width' features defined in [[!CSS2]] chapter 10 and in [[!CSS3COL]]
Name: width, height, inline-size, block-size, min-width, min-height, min-inline-size, min-block-size, max-width, max-height, max-inline-size, max-block-size New Values: stretch | fit-content | contain
Name: aspect-ratio Value: auto || <This property sets a preferred aspect ratio for the box, which will be used in the calculation of ''height/auto'' sizes and some other layout functions. The box’s automatic sizes are calculated the same as for a replaced element with an intrinsic aspect ratio and no intrinsic dimension in that axis, see e.g. CSS2 § 10 and CSS Flexible Box Model Level 1 § 9.2. The axis in which the preferred size calculation depends on this aspect ratio is called the ratio-dependent axis, and the resulting size is definite if its input sizes are also definite.> Initial: auto Inherited: no Applies to: all elements except inline boxes and internal ruby or table boxes Computed value: specified keyword or a pair of numbers
ul {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(12em, 1fr));
}
li {
aspect-ratio: 1/1;
overflow: auto;
}
width and height attributes
to set the 'aspect-ratio' property,
giving the iframe an aspect ratio to use for sizing
so that it behaves exactly like an image with that aspect ratio.
<iframe src="https://www.youtube.com/embed/0Gr1XSyxZy0" width=560 height=315>
@supports (aspect-ratio: attr(width) / 1) {
iframe {
aspect-ratio: attr(width) / attr(height);
width: 100%;
height: auto;
}
}
<div id=container style="height: 100px; float: left;"> <div id=item style="height: 100%; aspect-ratio: 1/1;">content</div> </div>Since the height of the
#item is a percentage that resolves against a definite container,
the width of the item resolves to 100px for both its intrinsic size contributions as well as for final layout,
so the container also sizes to a width of 100px.
<div id=container style="height: auto; float: left;"> <div id=item style="height: 100%; aspect-ratio: 1/1;">content</div> </div>In this next example, the percentage height of the item cannot be resolved and [=behaves as auto=] (see [[CSS2/visudet#the-height-property]]). Since both axes now have an [=automatic size=], the height becomes the [=ratio-dependent axis=]. Calculating the [=intrinsic size contributions=] of the box produces a width derived from its content, and a height calculated from that width and the aspect ratio, yielding a square box (and a container) sized to the width of the word “content”.
width: auto; min-height: min-content; aspect-ratio: 1/1;using the aspect ratio to resolve the width would require knowing the min-content height of the element. Since for a non-replaced element, this value is not known until the width is resolved, we assume the 'min-height' value is zero while resolving the width. Then, once the width is known, we resolve the height, taking into account the ''height/min-content'' minimum.
div {
aspect-ratio: 1/1;
/* 'width' and 'height' both default to 'auto' */
}
+----------+ +----------+ +----------+ | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | | | ~~~ | | ~~~~~~~~ | +----------+ +----------+ | ~~~~~~~~ | | ~~~~~~ | +----------+When ''overflow: auto'' is specified, however, even the box with excess content maintains the 1:1 aspect ratio.
div {
overflow: auto;
aspect-ratio: 1/1;
}
+----------+ +----------+ +----------+ | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~^| | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | | | ~~~ | | ~~~~~~~~v| +----------+ +----------+ +----------+Overriding the 'min-height' property also maintains the 1:1 aspect ratio, but will result in content overflowing the box if it is not otherwise handled.
div {
aspect-ratio: 1/1;
min-height: 0;
}
+----------+ +----------+ +----------+ | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~ | | ~~~~~~~~ | | ~~~~~~~~ | | | | ~~~ | | ~~~~~~~~ | +----------+ +----------+ +-~~~~~~~~-+ ~~~~~~
<div style="height: 100px; aspect-ratio: 1/1;"> <span style="display: inline-block; width: 50px;"></span> <span style="display: inline-block; width: 150px;"></span> </div>The 'width' of the container, being ''width/auto'', resolves through the aspect ratio to 100px. However, its 'min-width', being ''min-width/auto'', resolves to 150px. The resulting width of the container is thus 150px. To ignore the contents when sizing the container, ''min-width: 0'' can be specified.
Name: contain-intrinsic-size Value: none | <This property allows elements with [=size containment=] to specify an explicit intrinsic inner size, causing the box to size as if its in-flow content totals to a width and height matching the specified [=explicit intrinsic inner size=] (rather than sizing as if it were empty). Note: This is not always equivalent to laying out as if the element had one child of the specified [=explicit intrinsic inner size=]. Note: An element with [=size containment=] is laid out as if it had no contents [[!CSS-CONTAIN-1]], which in many cases this will cause the element to collapse to zero inner height. This can be corrected with an explicit 'height' chosen to show the expected contents, but that can have unintended effects in some layout systems, such as Flex and Grid Layout, which treat an explicit 'height' as a stronger command than an implicit content-based height. The element thus might lay out substantially differently than it would have were it simply filled with content up to that height. Providing an [=explicit intrinsic inner size=] for the element preserves the performance benefits of ignoring its contents for layout while still allowing it to size as if it had content. Values are defined as:>{1,2} Initial: none Inherited: no Applies to: elements with [=size containment=] Computed value: as specified, with < > values computed Percentages: n/a Animation type: by computed value type
div {
width: max-content;
contain-intrinsic-size: 100px 100px;
overflow: auto;
}
The element ends up being ''100px'' wide and ''100px'' tall:
'contain-intrinsic-size' provides the max-content width,
and also the height.
If the element then ended up with content that was ''150px'' tall,
it would show a vertical scrollbar;
if the scrollbar is not overlay,
it will take up some of that ''100px'' width,
leaving a smaller amount
(roughly ''84px'', typically)
for the content to flow into.
(See [[css-overflow-3#scrollbar-layout]].)
Even though there's now less than ''100px'' of horizontal space available for the content,
it will not generate a horizontal scrollbar just because 'contain-intrinsic-size' indicates a ''100px'' width;
that would only happen if the actual content
had something unbreakable
and wider than the remaining space.
div {
width: max-content;
contain-intrinsic-size: 100px 100px;
height: 50px;
overflow: auto;
}
The element has a fixed ''50px'' height,
but 'contain-intrinsic-size' indicates a ''100px'' “estimated content height”.
The element thus assumes that it will need a vertical scrollbar
when it's filled with actual content,
resulting in a max-content width a little more than ''100px''
(roughly ''116px'', typically),
to accommodate the estimated ''100px'' of max-content width from 'contain-intrinsic-size',
and as well as the vertical scrollbar width (roughly ''16px'', typically).
However, even though the element reserves space on the assumption of needing a scrollbar,
it will not actually generate one
unless the actual content overflows:
if it ends up containing content that's less than 50px tall,
no vertical scrollbar will be generated at all,
but the element will still be ''116px'' wide.
<div class="outer"> <div class="inner"></div> </div>In the following case, the [=outer height=] of the inner box will exactly match the height of the outer box (200px), but its [=inner height=] will be 20px less, to account for its margins.
.outer { height: 200px; border: solid; }
.inner { height: stretch; margin: 10px; }
In the following case,
the height of the inner box
will exactly match the height of the outer box (200px).
The top margins will collapse,
but the bottom margins do not collapse
(because the bottom margin of a box is not adjoining
to the bottom margin of a parent with a non-''height/auto'' height,
see [[CSS2/box#collapsing-margins]]),
and therefore the inner box’s bottom margin will be truncated.
.outer { height: 200px; margin: 0; }
.inner { height: stretch; margin: 10px; }
Special thanks go to Aaron Gustafson, L. David Baron for their contributions to this module.