tor-browser

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

try-tactic-anchor.html (7816B)


      1 <!DOCTYPE html>
      2 <title>CSS Anchor Positioning: try-tactic, anchor()</title>
      3 <link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#typedef-position-try-fallbacks-try-tactic">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <style>
      7  :root {
      8    --anchor-left:anchor(left);
      9  }
     10  #cb {
     11    position: absolute;
     12    width: 400px;
     13    height: 400px;
     14    border: 1px solid black;
     15  }
     16  #anchor {
     17    position: absolute;
     18    left: 150px;
     19    top: 150px;
     20    width: 60px;
     21    height: 70px;
     22    background-color: coral;
     23    anchor-name: --a;
     24  }
     25  #target, #ref {
     26    position: absolute;
     27    left: 450px; /* force fallback */
     28    width: 40px;
     29    height: 40px;
     30    background-color: skyblue;
     31    position-anchor: --a;
     32  }
     33  #ref {
     34    background-color: seagreen;
     35  }
     36 </style>
     37 <style id=style>
     38 </style>
     39 <div id=cb>
     40  <div id=anchor></div>
     41  <div id=target></div>
     42  <div id=ref></div>
     43 </div>
     44 <script>
     45 
     46 // Verify that a given try-tactic + untransformed declaration equals
     47 // a reference element using `transformed` directly.
     48 function test_anchor_flip(try_tactic, untransformed, transformed) {
     49  test((t) => {
     50    style.textContent = `
     51      @position-try --pf {
     52        inset: auto;
     53        ${untransformed}
     54      }
     55      #target {
     56        position-try-fallbacks: --pf ${try_tactic};
     57      }
     58      @position-try --ref {
     59        inset: auto;
     60        ${transformed}
     61      }
     62      #ref {
     63        position-try-fallbacks: --ref;
     64      }
     65    `;
     66    assert_equals(target.offsetLeft, ref.offsetLeft, 'offsetLeft');
     67    assert_equals(target.offsetTop, ref.offsetTop, 'offsetTop');
     68  }, `${try_tactic}, ${untransformed}, ${transformed}`);
     69 }
     70 
     71 // These are the possible transformations between
     72 // anchor(left/right/top/bottom):
     73 //
     74 // ┌───┬────┬────┬────┬────┐
     75 // │ - │ L  │ R  │ T  │ B  │
     76 // │ L │ -  │ LR │ LT │ LB │
     77 // │ R │ RL │ -  │ RT │ RB │
     78 // │ T │ TL │ TR │ -  │ TB │
     79 // │ B │ BL │ BR │ BT │ -  │
     80 // └───┴────┴────┴────┴────┘
     81 
     82 // No flip, no transformation.
     83 test_anchor_flip('', 'right:anchor(left)', 'right:anchor(left)');
     84 
     85 // flip-block does not affect left-right.
     86 test_anchor_flip('flip-block', 'right:anchor(left)', 'right:anchor(left)');
     87 // flip-inline does not affect left-right.
     88 test_anchor_flip('flip-inline', 'bottom:anchor(top)', 'bottom:anchor(top)');
     89 
     90 // Note that the letters represent the arguments to the anchor() functions,
     91 // not the properties. For example, LR: anchor(left) => anchor(right).
     92 
     93 // LR
     94 test_anchor_flip('flip-inline', 'right:anchor(left)', 'left:anchor(right)');
     95 // RL
     96 test_anchor_flip('flip-inline', 'left:anchor(right)', 'right:anchor(left)');
     97 
     98 // LT
     99 test_anchor_flip('flip-start', 'right:anchor(left)', 'bottom:anchor(top)');
    100 // TL
    101 test_anchor_flip('flip-start', 'bottom:anchor(top)', 'right:anchor(left)');
    102 
    103 // LB
    104 test_anchor_flip('flip-inline flip-start', 'right:anchor(left)', 'top:anchor(bottom)');
    105 // BL
    106 test_anchor_flip('flip-start flip-inline', 'top:anchor(bottom)', 'right:anchor(left)');
    107 
    108 // RT
    109 test_anchor_flip('flip-start flip-block', 'left:anchor(right)', 'bottom:anchor(top)');
    110 // TR
    111 test_anchor_flip('flip-block flip-start', 'bottom:anchor(top)', 'left:anchor(right)');
    112 
    113 // RB
    114 test_anchor_flip('flip-start', 'left:anchor(right)', 'top:anchor(bottom)');
    115 // BR
    116 test_anchor_flip('flip-start', 'top:anchor(bottom)', 'left:anchor(right)');
    117 
    118 // TB
    119 test_anchor_flip('flip-block', 'bottom:anchor(top)', 'top:anchor(bottom)');
    120 // BT
    121 test_anchor_flip('flip-block', 'top:anchor(bottom)', 'bottom:anchor(top)');
    122 
    123 // Logical versions.
    124 //
    125 // These tests duplicate the above, but replace the input logical anchor()
    126 // functions.
    127 
    128 // LR
    129 test_anchor_flip('flip-inline', 'right:anchor(start)', 'left:anchor(right)');
    130 // RL
    131 test_anchor_flip('flip-inline', 'left:anchor(end)', 'right:anchor(left)');
    132 
    133 // LT
    134 test_anchor_flip('flip-start', 'right:anchor(start)', 'bottom:anchor(top)');
    135 // TL
    136 test_anchor_flip('flip-start', 'bottom:anchor(start)', 'right:anchor(left)');
    137 
    138 // LB
    139 test_anchor_flip('flip-inline flip-start', 'right:anchor(start)', 'top:anchor(bottom)');
    140 // BL
    141 test_anchor_flip('flip-start flip-inline', 'top:anchor(end)', 'right:anchor(left)');
    142 
    143 // RT
    144 test_anchor_flip('flip-start flip-block', 'left:anchor(end)', 'bottom:anchor(top)');
    145 // TR
    146 test_anchor_flip('flip-block flip-start', 'bottom:anchor(start)', 'left:anchor(right)');
    147 
    148 // RB
    149 test_anchor_flip('flip-start', 'left:anchor(end)', 'top:anchor(bottom)');
    150 // BR
    151 test_anchor_flip('flip-start', 'top:anchor(end)', 'left:anchor(right)');
    152 
    153 // TB
    154 test_anchor_flip('flip-block', 'bottom:anchor(start)', 'top:anchor(bottom)');
    155 // BT
    156 test_anchor_flip('flip-block', 'top:anchor(end)', 'bottom:anchor(top)');
    157 
    158 // The same again, except with self-start/self-end.
    159 
    160 // LR
    161 test_anchor_flip('flip-inline', 'right:anchor(self-start)', 'left:anchor(right)');
    162 // RL
    163 test_anchor_flip('flip-inline', 'left:anchor(self-end)', 'right:anchor(left)');
    164 
    165 // LT
    166 test_anchor_flip('flip-start', 'right:anchor(self-start)', 'bottom:anchor(top)');
    167 // TL
    168 test_anchor_flip('flip-start', 'bottom:anchor(self-start)', 'right:anchor(left)');
    169 
    170 // LB
    171 test_anchor_flip('flip-inline flip-start', 'right:anchor(self-start)', 'top:anchor(bottom)');
    172 // BL
    173 test_anchor_flip('flip-start flip-inline', 'top:anchor(self-end)', 'right:anchor(left)');
    174 
    175 // RT
    176 test_anchor_flip('flip-start flip-block', 'left:anchor(self-end)', 'bottom:anchor(top)');
    177 // TR
    178 test_anchor_flip('flip-block flip-start', 'bottom:anchor(self-start)', 'left:anchor(right)');
    179 
    180 // RB
    181 test_anchor_flip('flip-start', 'left:anchor(self-end)', 'top:anchor(bottom)');
    182 // BR
    183 test_anchor_flip('flip-start', 'top:anchor(self-end)', 'left:anchor(right)');
    184 
    185 // TB
    186 test_anchor_flip('flip-block', 'bottom:anchor(self-start)', 'top:anchor(bottom)');
    187 // BT
    188 test_anchor_flip('flip-block', 'top:anchor(self-end)', 'bottom:anchor(top)');
    189 
    190 
    191 function test_anchor_size_flip(try_tactic, flip_expected) {
    192  test((t) => {
    193    style.textContent = `
    194      @position-try --pf {
    195        inset: auto;
    196        width: calc(anchor-size(width) + 20px);
    197        height: anchor-size(height);
    198      }
    199      #target {
    200        position-try-fallbacks: --pf ${try_tactic};
    201      }
    202    `;
    203 
    204    let expected_width = anchor.offsetWidth + (flip_expected ? 0 : 20);
    205    let expected_height = anchor.offsetHeight + (flip_expected ? 20 : 0);
    206 
    207    assert_equals(target.offsetWidth, expected_width, 'offsetWidth');
    208    assert_equals(target.offsetHeight, expected_height, 'offsetHeight');
    209  }, try_tactic);
    210 }
    211 
    212 // No flip, no transformation.
    213 test_anchor_size_flip('', /* expect_flip */ false);
    214 
    215 // Note: only the cross-axis flips cause width/height to change.
    216 // LR, TB (and their reverse versions) are in-axis, other combinations are
    217 // cross-axis.
    218 
    219 // In-axis:
    220 
    221 // LR, RL
    222 test_anchor_size_flip('flip-inline', /* expect_flip */ false);
    223 // TB, BT
    224 test_anchor_size_flip('flip-block', /* expect_flip */ false);
    225 
    226 // Cross-axis:
    227 
    228 // LT, TL, RB, BR
    229 test_anchor_size_flip('flip-start', /* expect_flip */ true);
    230 
    231 // LB, BL
    232 test_anchor_size_flip('flip-inline flip-start', /* expect_flip */ true);
    233 
    234 // RT, TR
    235 test_anchor_size_flip('flip-start flip-block', /* expect_flip */ true);
    236 
    237 
    238 test((t) => {
    239  style.textContent = `
    240    @position-try --pf {
    241      inset: auto;
    242      right: var(--anchor-left);
    243    }
    244    #target {
    245      position-try-fallbacks: --pf;
    246    }
    247  `;
    248  // Initially positioned to the left of the anchor.
    249  assert_equals(target.offsetLeft, 110, 'offsetLeft');
    250 
    251  // Now positioned to the right of the anchor.
    252  style.textContent += `
    253    #target {
    254      position-try-fallbacks: --pf flip-inline;
    255    }
    256  `;
    257  assert_equals(target.offsetLeft, 210, 'offsetLeft');
    258 }, 'Can transform a value post-var-substitution');
    259 
    260 </script>