commit 139b833802a0327a6404a6cda9313b6b8b5e245b
parent 24afab2006f1df855e947ac547aeb5ecffc81dd7
Author: Daniel Holbert <dholbert@cs.stanford.edu>
Date: Thu, 20 Nov 2025 06:10:05 +0000
Bug 1989365: Treat 'height:stretch' (and aliases) as able to resolve against quirks-mode body height. r=TYLin,layout-reviewers
This patch lets 'stretch' block-sizes get opted in so they can resolve against
the result of `CalcQuirkContainingBlockHeight()`. That's where we handle the
"html element fills the viewport" and "body element fills the html element"
quirks-mode behaviors explained here:
https://quirks.spec.whatwg.org/#the-html-element-fills-the-viewport-quirk
https://quirks.spec.whatwg.org/#the-body-element-fills-the-html-element-quirk
This makes us match the behavior that other browsers have been shipping (with
'stretch' in Chrome as well as its '-webkit-fill-available' alias in Chrome and
Safari), and we're aware of at least one site that depends on this behavior
(tracked in bug 1886566).
Differential Revision: https://phabricator.services.mozilla.com/D273323
Diffstat:
3 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp
@@ -2128,11 +2128,13 @@ LogicalSize ReflowInput::ComputeContainingBlockRectangle(
}
auto IsQuirky = [](const StyleSize& aSize) -> bool {
- return aSize.ConvertsToPercentage();
+ return aSize.ConvertsToPercentage() ||
+ aSize.BehavesLikeStretchOnBlockAxis();
};
const auto anchorResolutionParams = AnchorPosResolutionParams::From(this);
- // an element in quirks mode gets a containing block based on looking for a
- // parent with a non-auto height if the element has a percent height.
+ // In quirks mode, if an element has a percent height (or a 'stretch' height,
+ // which is kinda like a special version of 100%), then it gets its
+ // containing block by looking for an ancestor with a non-auto height.
// Note: We don't emulate this quirk for percents in calc(), or in vertical
// writing modes, or if the containing block is a flex or grid item.
if (!wm.IsVertical() && NS_UNCONSTRAINEDSIZE == cbSize.BSize(wm)) {
diff --git a/testing/web-platform/tests/css/css-sizing/stretch/stretch-quirk-001-ref.html b/testing/web-platform/tests/css/css-sizing/stretch/stretch-quirk-001-ref.html
@@ -0,0 +1,28 @@
+<!-- no doctype, to trigger quirks mode -->
+<meta charset="utf-8">
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<title>CSS Reference Case</title>
+<style>
+ body {
+ margin: 0;
+ }
+ body > * {
+ box-sizing: border-box;
+ height: 100vh;
+
+ /* The rest of these styles are just for cosmetics & consistency: */
+ width: 40px;
+ border: 5px solid blue;
+ vertical-align: top;
+ margin: 0 10px 0 0;
+ background: cyan;
+ }
+</style>
+<body>
+ <div style="display: inline-block">IB</div>
+ <canvas></canvas>
+ <iframe></iframe>
+ <button>B</button>
+ <input value="i">
+ <textarea></textarea>
+</body>
diff --git a/testing/web-platform/tests/css/css-sizing/stretch/stretch-quirk-001.html b/testing/web-platform/tests/css/css-sizing/stretch/stretch-quirk-001.html
@@ -0,0 +1,38 @@
+<!-- no doctype, to trigger quirks mode -->
+<meta charset="utf-8">
+<title>
+ CSS Test: 'stretch' heights can resolve against body height, with
+ quirks-mode body-fills-html-which-fills-viewport behavior
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#sizing-values">
+<link rel="help" href="https://quirks.spec.whatwg.org/#the-html-element-fills-the-viewport-quirk">
+<link rel="help" href="https://quirks.spec.whatwg.org/#the-body-element-fills-the-html-element-quirk">
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<link rel="match" href="stretch-quirk-001-ref.html">
+<meta name="assert"
+ content="In quirks mode, the body's automatic height should be considered definite for the purposes of 'stretch' resolution on its children">
+<style>
+ body {
+ margin: 0;
+ }
+ body > * {
+ box-sizing: border-box;
+ height: -webkit-fill-available;
+ height: stretch;
+
+ /* The rest of these styles are just for cosmetics & consistency: */
+ width: 40px;
+ border: 5px solid blue;
+ vertical-align: top;
+ margin: 0 10px 0 0;
+ background: cyan;
+ }
+</style>
+<body>
+ <div style="display: inline-block">IB</div>
+ <canvas></canvas>
+ <iframe></iframe>
+ <button>B</button>
+ <input value="i">
+ <textarea></textarea>
+</body>