@@ -30,10 +30,7 @@ spec:css-contain-2; type:dfn; text:size containment box
3030spec:css-sizing-4; type:property; text:contain-intrinsic-size
3131spec:css-sizing-4; type:property; text:aspect-ratio
3232spec:intersection-observer; type:dfn; text:intersection root
33- spec:css-sizing-3; type:value; for:height; text:auto
3433spec:css-sizing-3; type:property;
35- text:width
36- text:height
3734 text:min-width
3835 text:min-height
3936spec:css-sizing-3; type:dfn; text:width
@@ -107,75 +104,131 @@ Inline-Size Containment</h3>
107104 is determined as if the element had no content.
108105 However, content continues to impact the element’s [=block axis=] [=intrinsic size=] .
109106
110- In some cases,
111- changes in the [=block size=] can impact layout in the parent formatting context,
112- which then impacts the [=inline axis|inline=] [=available space=]
113- (e.g. by triggering scrollbars on an ancestor element)
114- or the result of [=container size queries=] ,
115- which then impacts the element’s [=inline size=] ,
116- creating a dependency of this [=inline size=] on the element’s content.
117- To prevent infinite cycles,
118- if this then results in a different [=block size=] on the element,
119- that new [=block size=] can impact the parent formatting context,
120- but not in a way that reverts it to the previously-problematic layout.
121- For example, if scrollbars were introduced, they are not then removed;
122- or if the inline size was reduced, it is not then restored to its previous size.
123-
124- Note: This is similar to the logic governing float placement,
125- in which a float whose logical height cannot fit
126- is shifted down to find more space,
127- which might also give it more inline-axis available space
128- and thus produce a shorter float
129- whose height could have fit in the initial space,
130- but it is not moved back up
131- (where it would again be narrower, and thus taller, and thus not fit).
132-
133- <div class=example>
134- For example,
135- the following <code> article</code> is constrained by both
136- the overall <code> section</code> '/width' ,
137- and impacted by the floated <code> div</code> s.
138-
139- <pre class=lang-markup>
140- <section style="width: 200px; border: solid; display: flow-root;">
141- <!-- floated elements that impact the available space -->
142- <div style="float: left; width: 50px; height: 80px; background: red;"></div>
143- <div style="float: right; width: 50px; height: 80px; background: red;"></div>
144- <div style="float: left; width: 160px; height: 80px; background: red;"></div>
145-
146- <!-- parent layout, determining context -->
147- <article style="border: solid; display: flow-root; min-width: min-content;">
148- <header style="background: orange; aspect-ratio: 1/1;">
149- <h4 style="margin:0;">Article Title</h4>
150- </header>
151- </article>
152- </section>
153- </pre>
154-
155- The block layout algorithm will attempt to layout the <code> article</code>
156- in the first available space between the first two floated <code> div</code> s.
157- However, the <code> header</code> '/aspect-ratio'
158- requires a space with '/height' equal or greater to the '/width' ,
159- and the available space is 100px wide by 80px tall,
160- so the <code> article</code> is unable to fit.
161- As a result, the block layout algorithm moves on,
162- and attempts to layout the <code> article</code> in the next available space.
163-
164- Since <code> article</code> 'min-width' depends on the [=min-content size=] ,
165- it will likely be too large to fit in the 40px wide space
166- beside the final floated <code> div</code> ,
167- and continue to layout below that <code> div</code> as well--
168- forming a 200px square below all the floated elements.
169-
170- However, if the 'min-width' is removed from the <code> article</code> ,
171- or if [=inline-size containment=] is added to
172- either the <code> article</code> or <code> header</code> ,
173- then the <code> article</code> will fit as a 40px square
174- next to the final floated <code> div</code> .
175- Even though this resulting size could also fit in the initial space,
176- agents do not backtrack
177- and attempt to place the <code> article</code>
178- in a context that previously failed.
107+ <div class=note>
108+ In some cases,
109+ changes in the [=block size=] can impact layout in the parent formatting context,
110+ which then impacts the [=inline axis|inline=] [=available space=]
111+ (e.g. by triggering scrollbars on an ancestor element)
112+ or the result of [=container size queries=] ,
113+ which then impacts the element’s [=inline size=] ,
114+ creating a dependency of this [=inline size=] on the element’s content.
115+
116+ This sort of "cycle" is not new;
117+ it is possible to construct examples of this
118+ using elements with aspect ratios,
119+ or complex usages of floats and clearing.
120+ In general, the relationship between an element's available inline space
121+ and it's resulting block size
122+ is unpredictable and non-monotonic,
123+ with the block size capable of bouncing up and down arbitrarily
124+ as the available inline space is changed.
125+
126+ Implementations today prevent infinite cycling
127+ by ensuring that layout always "moves forward";
128+ in other words,
129+ that certain aspects of a container's layout
130+ do not "revert" to a previous (known-problematic) state,
131+ even if a naive analysis of the constraints would allow for such.
132+ The mitigation for these issues
133+ is that certain aspects of layout
134+ are on a "ratchet",
135+ allowed to progress in one direction but not another:
136+ the available size a container presents to its contents is one such example,
137+ allowed to shrink
138+ (as a result of scrollbars, etc)
139+ but not to then reverse and grow again;
140+ the presence of scrollbars themselves is another,
141+ allowed to be added to an element
142+ but not to then be removed
143+ if the reduced inline available size
144+ causes the contents to no longer overflow;
145+ the "starting point" for elements to be laid out
146+ along the block axis is another,
147+ allowed to move downward as a result of floats
148+ but not to then move back upward
149+ and possibly cause already laid-out floats
150+ to have to move again.
151+
152+ These algorithm ratchets are well-known and common among implementations,
153+ and container queries
154+ (and the associated [=inline-size containment=] )
155+ do not introduce any conceptually new problems here.
156+ To the best of the specification editors' knowledge,
157+ existing layout techniques suffice to ensure that layout cycles do not occur,
158+ and the design of this feature
159+ attempts to make them rare in practice in any case.
160+
161+ The precise details of each implementation's mitigation strategies
162+ are not fully interoperable,
163+ unfortunately,
164+ so we hope to capture them in a future specification.
165+
166+ <div class=example>
167+ For example,
168+ the following <code> article</code> is constrained by both
169+ the overall <code> section</code> '/width' ,
170+ and impacted by the floated <code> div</code> s.
171+
172+ <xmp class=lang-markup>
173+ <section style="width: 200px; border: solid; display: flow-root;">
174+ <!-- floated elements that impact the available space -->
175+ <div style="float: left; width: 50px; height: 80px; background: red;"></div>
176+ <div style="float: right; width: 50px; height: 80px; background: red;"></div>
177+ <div style="float: left; width: 160px; height: 80px; background: red;"></div>
178+
179+ <!-- parent layout, determining context -->
180+ <article style="border: solid; display: flow-root;">
181+ <div style="background: orange; aspect-ratio: 1/1;">
182+ text
183+ </div>
184+ </article>
185+ </section>
186+ </xmp>
187+
188+ The block layout algorithm will first place the floating elements,
189+ with the first two sitting in the left and right corners of the container,
190+ and the third being pushed below them,
191+ since its width does not fit in the remaining space
192+ if it was placed with its top edge flush with the top of the container.
193+
194+ The following <code> article</code> will then be laid out.
195+ Because it is ''display: flow-root'' ,
196+ it avoids intersecting with any floats,
197+ and thus must take them into account
198+ when figuring out how to size and position itself.
199+
200+ The layout engine first attempts to put the <code> article</code> flush with the top of the container,
201+ as there is enough inline space to accommodate its [=min-content size=] ;
202+ resulting in it becoming ''100px'' wide.
203+ However, due the aspect ratio of its contents,
204+ this would cause the <code> article</code> to be ''100px'' tall as well,
205+ but there is only ''80px'' of available block space
206+ before it would intersect the third float,
207+ so this layout opportunity is discarded.
208+
209+ It then attempts to position the <code> article</code>
210+ flush with the top of the third float,
211+ in the narrow ''40px'' -wide space to its right.
212+ It fits, and its resulting ''40px'' height
213+ doesn't violate any layout rules either,
214+ so this is acceptable.
215+
216+ At this point, the width and height of the <code> article</code>
217+ (''40px'' each)
218+ <em> would</em> fit back in the original considered space,
219+ flush with the top of the container.
220+ However, "progress" along the block axis
221+ when considering layout opportunities
222+ is one such "ratchet" in layout,
223+ and an element is not allowed to return to a higher position
224+ after it determines its size.
225+
226+ Thus, the <code> article</code> is sized to ''40px'' wide and tall
227+ and positioned alongside the third float,
228+ even tho a similar element with an <em> explicit</em> <css> width: 40px</css>
229+ would be positioned at the top of the container,
230+ between the first two floats.
231+ </div>
179232 </div>
180233
181234 Issue(1031): Define inline-size containment in more detail
0 commit comments