147 lines
6.2 KiB
HTML
147 lines
6.2 KiB
HTML
<!DOCTYPE html>
|
|
<html class="reftest-wait">
|
|
<meta charset="utf-8">
|
|
<title>CSS Test: BFCs with large margin, placed next to a float</title>
|
|
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
|
<link rel="help" href="https://www.w3.org/TR/CSS21/visuren.html#floats">
|
|
<link rel="help" href="https://www.w3.org/TR/CSS21/visudet.html#blockwidth">
|
|
<link rel="match" href="floats-wrap-bfc-with-margin-003-ref.html">
|
|
<!-- This test exercises the layout of an auto-width BFC with a large positive
|
|
margin on one side, positioned alongside a float. (Here, "large" = larger
|
|
than the space that's left when the float's width and the BFC's border
|
|
are subtracted away from the available space.)
|
|
|
|
The scenarios here break down into 3 cases, described below as A/B/C with
|
|
expected outcomes for each (with expectations based on the observed and
|
|
interoperably-implemented behavior of Gecko, WebKit, and Blink, aside
|
|
from some known bugs listed further down[1]):
|
|
|
|
(A) If the BFC's margin is on the same side as the float, then that margin
|
|
can simply overlap the float. In this case, nothing needs to overflow or
|
|
wrap, and there may even be some space remaining for the BFC's auto-width
|
|
content box (rendered as aqua).
|
|
|
|
(B) If the BFC's margin is on the "line-start" side and the float is on
|
|
the "line-end" side, then the BFC's margin pushes it into the float's
|
|
margin-box-area such that it impermissably "collides". So, the BFC
|
|
instead gets moved down below the float to avoid this collision. With
|
|
this moved-down placement, there may be space remaining for the BFC's
|
|
auto-width content-box -- precisely the same amount of space as in case A.
|
|
|
|
(C) If the BFC's margin is on the "line-end" side and the float is on the
|
|
"line-start" side, then the BFC is placed adjacent to the float, and its
|
|
large margin simply runs off the line-end edge of its containing
|
|
block. The BFC's content-box is 0 width (since there's no free space left
|
|
over).
|
|
|
|
Note: the expected-outcome in case B and C feels somewhat asymmetrical,
|
|
and in fact Gecko is the only engine that pushes the BFC down in case B.
|
|
But Blink/WebKit's alternative behavior for case B involves the BFC
|
|
overlapping the float, which clearly violates the spec, as discussed in
|
|
their bugs linked below. So I'm making the test expect Gecko's existing
|
|
and non-spec-violating behavior for case B, at this point. (I'm guessing
|
|
the asymmetry comes from how overflowing margins are handled at the
|
|
line-start vs. line-end edge, which makes some sense.)
|
|
|
|
Here's how this test's groups (black-bordered sections) map to these cases:
|
|
* This test's 1st, 4th, 5th, and 8th groups are "case A".
|
|
* This test's 3rd and 6th groups are in "case B".
|
|
* This test's 2nd and 7th groups are in "case C".
|
|
|
|
[1] Known bugs referenced above, which cause parts of this test to fail in
|
|
WebKit and Blink:
|
|
https://bugs.webkit.org/show_bug.cgi?id=240128
|
|
https://bugs.chromium.org/p/chromium/issues/detail?id=1322774
|
|
https://bugs.chromium.org/p/chromium/issues/detail?id=1323004
|
|
-->
|
|
<script>
|
|
const MARGIN_VALS = [15, 22, 28];
|
|
const HORIZ_SIDES = ["left", "right"]; // Used for 'float:*' and 'margin-*'.
|
|
const DIRECTION_VALS = ["ltr", "rtl"];
|
|
|
|
function newDivWithClassAndParent(className, parent) {
|
|
let elem = document.createElement("div");
|
|
if (className) {
|
|
elem.classList.add(className);
|
|
}
|
|
parent.appendChild(elem);
|
|
return elem;
|
|
}
|
|
function generateGroup(directionVal, floatVal, marginPropSuffix) {
|
|
let group = newDivWithClassAndParent("group", document.body);
|
|
group.style.direction = directionVal;
|
|
const marginPropName = "margin-" + marginPropSuffix;
|
|
|
|
for (let v of MARGIN_VALS) {
|
|
let container = newDivWithClassAndParent("container", group);
|
|
let float = newDivWithClassAndParent("float", container);
|
|
float.style.cssFloat = floatVal;
|
|
|
|
let bfc = newDivWithClassAndParent("bfc", container);
|
|
bfc.style[marginPropName] = v + "px";
|
|
}
|
|
}
|
|
function go() {
|
|
for (let directionVal of DIRECTION_VALS) {
|
|
for (let floatVal of HORIZ_SIDES) {
|
|
for (let marginPropSuffix of HORIZ_SIDES) {
|
|
generateGroup(directionVal, floatVal, marginPropSuffix);
|
|
}
|
|
}
|
|
}
|
|
// Note: the "reftest-wait" usage here isn't strictly necessary; it just
|
|
// helps ensure that we actually make it through all of the above JS and
|
|
// populate this document with the content that we want to render.
|
|
// (Specifically: if we e.g. throw a JS exception somewhere early in both
|
|
// the testcase and reference case, then the "reftest-wait" class will
|
|
// never be removed; and that will cause the test run to be classified
|
|
// as a failure, rather than a trivial "pass" with a visual comparison of
|
|
// two blank documents.)
|
|
document.documentElement.removeAttribute("class");
|
|
}
|
|
</script>
|
|
<style>
|
|
.group {
|
|
width: 300px;
|
|
border: 1px solid black;
|
|
}
|
|
.container {
|
|
/* This is the container that holds our float+bfc. We make it an
|
|
inline-block so that we can test a bunch of these in a row. */
|
|
display: inline-block;
|
|
vertical-align: top;
|
|
width: 30px;
|
|
height: 40px;
|
|
/* This border and margin are just cosmetic, to avoid overlap between
|
|
* adjacent containers within a row. */
|
|
border: 1px solid gray;
|
|
margin-left: 30px;
|
|
}
|
|
|
|
.float {
|
|
/* We'll set the float property elsewhere (to 'right' or 'left'). */
|
|
width: 7px;
|
|
height: 8px;
|
|
background: fuchsia;
|
|
border: 1px solid purple;
|
|
/* Each .float's margin-box (which the corresponding .bfc's border-box cannot
|
|
* overlap) is 14px wide:
|
|
* 7px content + 2px horizontal border + 5px horizontal margin
|
|
* Note that we're intentionally using a nonzero 'margin' here, to be sure
|
|
* the UA is using the float's margin-box (and not one of its other
|
|
* boxes) for this non-overlapping calculation. */
|
|
margin: 1px 3px 1px 2px;
|
|
}
|
|
.bfc {
|
|
/* Each .bfc's border-box width is 2px (from the border) plus whatever we
|
|
* resolve 'width:auto' to, which is influenced by the particular choice of
|
|
* 'margin' values (and the available space). */
|
|
display: flow-root;
|
|
background: aqua;
|
|
height: 15px;
|
|
border: 1px solid blue;
|
|
}
|
|
</style>
|
|
<body onload="go()">
|
|
</body>
|
|
</html>
|