tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

floats-wrap-bfc-with-margin-003.tentative.html (6377B)


      1 <!DOCTYPE html>
      2 <html class="reftest-wait">
      3 <meta charset="utf-8">
      4 <title>CSS Test: BFCs with large margin, placed next to a float</title>
      5 <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
      6 <link rel="help" href="https://www.w3.org/TR/CSS21/visuren.html#floats">
      7 <link rel="help" href="https://www.w3.org/TR/CSS21/visudet.html#blockwidth">
      8 <link rel="match" href="floats-wrap-bfc-with-margin-003-ref.html">
      9 <!-- This test exercises the layout of an auto-width BFC with a large positive
     10     margin on one side, positioned alongside a float. (Here, "large" = larger
     11     than the space that's left when the float's width and the BFC's border
     12     are subtracted away from the available space.)
     13 
     14     The scenarios here break down into 3 cases, described below as A/B/C with
     15     expected outcomes for each (with expectations based on the observed and
     16     interoperably-implemented behavior of Gecko, WebKit, and Blink, aside
     17     from some known bugs listed further down[1]):
     18 
     19     (A) If the BFC's margin is on the same side as the float, then that margin
     20     can simply overlap the float. In this case, nothing needs to overflow or
     21     wrap, and there may even be some space remaining for the BFC's auto-width
     22     content box (rendered as aqua).
     23 
     24     (B) If the BFC's margin is on the "line-start" side and the float is on
     25     the "line-end" side, then the BFC's margin pushes it into the float's
     26     margin-box-area such that it impermissably "collides".  So, the BFC
     27     instead gets moved down below the float to avoid this collision.  With
     28     this moved-down placement, there may be space remaining for the BFC's
     29     auto-width content-box -- precisely the same amount of space as in case A.
     30 
     31     (C) If the BFC's margin is on the "line-end" side and the float is on the
     32     "line-start" side, then the BFC is placed adjacent to the float, and its
     33     large margin simply runs off the line-end edge of its containing
     34     block. The BFC's content-box is 0 width (since there's no free space left
     35     over).
     36 
     37     Note: the expected-outcome in case B and C feels somewhat asymmetrical,
     38     and in fact Gecko is the only engine that pushes the BFC down in case B.
     39     But Blink/WebKit's alternative behavior for case B involves the BFC
     40     overlapping the float, which clearly violates the spec, as discussed in
     41     their bugs linked below. So I'm making the test expect Gecko's existing
     42     and non-spec-violating behavior for case B, at this point. (I'm guessing
     43     the asymmetry comes from how overflowing margins are handled at the
     44     line-start vs. line-end edge, which makes some sense.)
     45 
     46     Here's how this test's groups (black-bordered sections) map to these cases:
     47     * This test's 1st, 4th, 5th, and 8th groups are "case A".
     48     * This test's 3rd and 6th groups are in "case B".
     49     * This test's 2nd and 7th groups are in "case C".
     50 
     51     [1] Known bugs referenced above, which cause parts of this test to fail in
     52     WebKit and Blink:
     53     https://bugs.webkit.org/show_bug.cgi?id=240128
     54     https://bugs.chromium.org/p/chromium/issues/detail?id=1322774
     55     https://bugs.chromium.org/p/chromium/issues/detail?id=1323004
     56 -->
     57 <script>
     58  const MARGIN_VALS = [15, 22, 28];
     59  const HORIZ_SIDES = ["left", "right"]; // Used for 'float:*' and 'margin-*'.
     60  const DIRECTION_VALS = ["ltr", "rtl"];
     61 
     62  function newDivWithClassAndParent(className, parent) {
     63    let elem = document.createElement("div");
     64    if (className) {
     65      elem.classList.add(className);
     66    }
     67    parent.appendChild(elem);
     68    return elem;
     69  }
     70  function generateGroup(directionVal, floatVal, marginPropSuffix) {
     71    let group = newDivWithClassAndParent("group", document.body);
     72    group.style.direction = directionVal;
     73    const marginPropName = "margin-" + marginPropSuffix;
     74 
     75    for (let v of MARGIN_VALS) {
     76      let container = newDivWithClassAndParent("container", group);
     77      let float = newDivWithClassAndParent("float", container);
     78      float.style.cssFloat = floatVal;
     79 
     80      let bfc = newDivWithClassAndParent("bfc", container);
     81      bfc.style[marginPropName] = v + "px";
     82    }
     83  }
     84  function go() {
     85    for (let directionVal of DIRECTION_VALS) {
     86      for (let floatVal of HORIZ_SIDES) {
     87        for (let marginPropSuffix of HORIZ_SIDES) {
     88          generateGroup(directionVal, floatVal, marginPropSuffix);
     89        }
     90      }
     91    }
     92    // Note: the "reftest-wait" usage here isn't strictly necessary; it just
     93    // helps ensure that we actually make it through all of the above JS and
     94    // populate this document with the content that we want to render.
     95    // (Specifically: if we e.g. throw a JS exception somewhere early in both
     96    // the testcase and reference case, then the "reftest-wait" class will
     97    // never be removed; and that will cause the test run to be classified
     98    // as a failure, rather than a trivial "pass" with a visual comparison of
     99    // two blank documents.)
    100    document.documentElement.removeAttribute("class");
    101  }
    102 </script>
    103 <style>
    104 .group {
    105  width: 300px;
    106  border: 1px solid black;
    107 }
    108 .container {
    109  /* This is the container that holds our float+bfc.  We make it an
    110     inline-block so that we can test a bunch of these in a row.  */
    111  display: inline-block;
    112  vertical-align: top;
    113  width: 30px;
    114  height: 40px;
    115  /* This border and margin are just cosmetic, to avoid overlap between
    116   * adjacent containers within a row. */
    117  border: 1px solid gray;
    118  margin-left: 30px;
    119 }
    120 
    121 .float {
    122  /* We'll set the float property elsewhere (to 'right' or 'left'). */
    123  width: 7px;
    124  height: 8px;
    125  background: fuchsia;
    126  border: 1px solid purple;
    127  /* Each .float's margin-box (which the corresponding .bfc's border-box cannot
    128   * overlap) is 14px wide:
    129   *   7px content + 2px horizontal border + 5px horizontal margin
    130   * Note that we're intentionally using a nonzero 'margin' here, to be sure
    131   * the UA is using the float's margin-box (and not one of its other
    132   * boxes) for this non-overlapping calculation. */
    133  margin: 1px 3px 1px 2px;
    134 }
    135 .bfc {
    136  /* Each .bfc's border-box width is 2px (from the border) plus whatever we
    137   * resolve 'width:auto' to, which is influenced by the particular choice of
    138   * 'margin' values (and the available space). */
    139  display: flow-root;
    140  background: aqua;
    141  height: 15px;
    142  border: 1px solid blue;
    143 }
    144 </style>
    145 <body onload="go()">
    146 </body>
    147 </html>