calc-size-height-interpolation.html (11128B)
1 <!DOCTYPE html> 2 <meta charset="UTF-8"> 3 <title>height: calc-size() animations</title> 4 <link rel="help" href="https://drafts.csswg.org/css-values-5/#calc-size"> 5 <meta name="timeout" content="long"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="../../../support/interpolation-testcommon.js"></script> 9 10 <style> 11 .parent { 12 display: block; 13 width: 600px; 14 height: 300px; 15 } 16 html.no-parent-height .parent { 17 height: auto; 18 } 19 .target { 20 display: block; 21 } 22 .target::before { 23 display: block; 24 content: ""; 25 width: 23px; 26 height: 100px; 27 } 28 </style> 29 30 <body> 31 32 <script> 33 test_interpolation({ 34 property: 'height', 35 from: 'calc-size(auto, size)', 36 to: 'calc-size(auto, size * 2)', 37 }, [ 38 { at: -0.25, expect: '75px' }, 39 { at: 0, expect: '100px' }, 40 { at: 0.25, expect: '125px' }, 41 { at: 0.5, expect: '150px' }, 42 { at: 0.75, expect: '175px' }, 43 { at: 1, expect: '200px' }, 44 { at: 1.25, expect: '225px' }, 45 ]); 46 47 test_interpolation({ 48 property: 'height', 49 from: neutralKeyframe, 50 to: 'calc-size(auto, size * 2)', 51 }, [ 52 { at: -0.25, expect: '75px' }, 53 { at: 0, expect: '100px' }, 54 { at: 0.25, expect: '125px' }, 55 { at: 0.5, expect: '150px' }, 56 { at: 0.75, expect: '175px' }, 57 { at: 1, expect: '200px' }, 58 { at: 1.25, expect: '225px' }, 59 ]); 60 61 test_interpolation({ 62 property: 'height', 63 from: 'calc-size(min-content, 0 * size)', 64 to: 'calc-size(min-content, size)', 65 }, [ 66 { at: -0.25, expect: '0' }, 67 { at: 0, expect: '0' }, 68 { at: 0.25, expect: '25px' }, 69 { at: 0.5, expect: '50px' }, 70 { at: 0.75, expect: '75px' }, 71 { at: 1, expect: '100px' }, 72 { at: 1.25, expect: '125px' }, 73 ]); 74 75 test_interpolation({ 76 property: 'height', 77 from: 'calc-size(min-content, 0px)', 78 to: 'calc-size(min-content, size)', 79 }, [ 80 { at: -0.25, expect: '0' }, 81 { at: 0, expect: '0' }, 82 { at: 0.25, expect: '25px' }, 83 { at: 0.5, expect: '50px' }, 84 { at: 0.75, expect: '75px' }, 85 { at: 1, expect: '100px' }, 86 { at: 1.25, expect: '125px' }, 87 ]); 88 89 test_interpolation({ 90 property: 'height', 91 from: '0', 92 to: 'calc-size(max-content, size)', 93 }, [ 94 { at: -0.25, expect: '0' }, 95 { at: 0, expect: '0' }, 96 { at: 0.25, expect: '25px' }, 97 { at: 0.5, expect: '50px' }, 98 { at: 0.75, expect: '75px' }, 99 { at: 1, expect: '100px' }, 100 { at: 1.25, expect: '125px' }, 101 ]); 102 103 const KEYWORDS = { 104 "auto": 100, 105 "min-content": 100, 106 "fit-content": 100, 107 "max-content": 100, 108 "stretch": 300, 109 }; 110 111 for (const keyword in KEYWORDS) { 112 let expected = KEYWORDS[keyword]; 113 test_interpolation({ 114 property: 'height', 115 from: keyword, 116 to: `calc-size(${keyword}, size * 2)`, 117 }, [ 118 { at: -0.25, expect: `${expected * 0.75}px` }, 119 { at: 0, expect: `${expected}px` }, 120 { at: 0.75, expect: `${expected * 1.75}px` }, 121 { at: 1, expect: `${expected * 2}px` }, 122 { at: 1.25, expect: `${expected * 2.25}px` }, 123 ]); 124 125 test_interpolation({ 126 property: 'height', 127 from: keyword, 128 to: 'calc-size(any, 50px)', 129 }, [ 130 { at: -0.25, expect: `${expected * 1.25 - 50 * 0.25}px` }, 131 { at: 0, expect: `${expected}px` }, 132 { at: 0.75, expect: `${expected * 0.25 + 50 * 0.75}px` }, 133 { at: 1, expect: `50px` }, 134 { at: 1.1, expect: `${50 * 1.1 - expected * 0.1}px` }, 135 ]); 136 137 test_interpolation({ 138 property: 'height', 139 from: 'calc-size(any, 50px)', 140 to: `calc-size(${keyword}, size * 2)`, 141 }, [ 142 { at: -0.05, expect: `${50 * 1.05 - expected * 0.1}px` }, 143 { at: 0, expect: "50px" }, 144 { at: 0.75, expect: `${50 * 0.25 + expected * 1.5}px` }, 145 { at: 1, expect: `${expected * 2}px` }, 146 { at: 1.25, expect: `${expected * 2.5 - 50 * 0.25}px` }, 147 ]); 148 149 test_no_interpolation({ 150 property: 'height', 151 from: keyword, 152 to: 'calc-size(50px, size)', 153 }); 154 } 155 156 const KEYWORD_PAIRS = [ 157 [ "auto", "fit-content" ], 158 [ "fit-content", "min-content" ], 159 [ "stretch", "auto" ], 160 [ "max-content", "stretch" ], 161 ]; 162 163 for (const pair of KEYWORD_PAIRS) { 164 test_no_interpolation({ 165 property: 'height', 166 from: pair[0], 167 to: `calc-size(${pair[1]}, size)`, 168 }); 169 } 170 171 test_interpolation({ 172 property: 'height', 173 from: 'calc-size(20px, size)', 174 to: 'calc-size(60px, size)', 175 }, [ 176 { at: -0.25, expect: '10px' }, 177 { at: 0, expect: '20px' }, 178 { at: 0.75, expect: '50px' }, 179 { at: 1, expect: '60px' }, 180 { at: 1.25, expect: '70px' }, 181 ]); 182 183 test_interpolation({ 184 property: 'height', 185 from: 'calc-size(50%, size)', /* 150px */ 186 to: 'calc-size(50px, size)', 187 }, [ 188 { at: -0.25, expect: '175px' }, 189 { at: 0, expect: '150px' }, 190 { at: 0.75, expect: '75px' }, 191 { at: 1, expect: '50px' }, 192 { at: 1.25, expect: '25px' }, 193 ]); 194 195 test_interpolation({ 196 property: 'height', 197 from: 'calc-size(37px, 200px)', 198 to: 'calc-size(37px, size * 2 + 3% + 17px)', /* adds to 100px */ 199 }, [ 200 { at: -0.25, expect: '225px' }, 201 { at: 0, expect: '200px' }, 202 { at: 0.75, expect: '125px' }, 203 { at: 1, expect: '100px' }, 204 { at: 1.25, expect: '75px' }, 205 ]); 206 207 test_interpolation({ 208 property: 'height', 209 from: 'calc-size(auto, size)', 210 to: '50%', 211 }, [ 212 { at: -0.25, expect: '87.5px' }, 213 { at: 0, expect: '100px' }, 214 { at: 0.75, expect: '137.5px' }, 215 { at: 1, expect: '150px' }, 216 { at: 1.25, expect: '162.5px' }, 217 ]); 218 219 // Rerun roughly the same test with an auto height container. 220 let auto_style_text = ` 221 .parent { 222 height: auto; 223 } 224 `; 225 let auto_style_element = document.createElement("style"); 226 auto_style_element.append(document.createTextNode(auto_style_text)); 227 document.head.append(auto_style_element); 228 229 test_interpolation({ 230 property: 'height', 231 from: 'calc-size(auto, size * 2)', 232 to: '50%', 233 }, [ 234 { at: -0.25, expect: '250px' }, 235 { at: 0, expect: '200px' }, 236 { at: 0.75, expect: '50px' }, 237 /* TODO(https://crbug.com/40339056): It's questionable whether this should 238 * be the case, particularly for transitions. Perhaps the value at the 239 * end should have its percentage-ness back and be 100px here? */ 240 { at: 1, expect: '0px' }, 241 { at: 1.25, expect: '0px' }, 242 ]); 243 244 auto_style_element.remove(); 245 246 test_no_interpolation({ 247 property: 'height', 248 from: 'calc-size(auto, size)', 249 to: 'calc-size(50%, size)', 250 }); 251 252 test_no_interpolation({ 253 property: 'height', 254 from: 'calc-size(calc-size(auto, size / 2), size * 2)', 255 to: 'calc-size(12.5%, size * 4)', 256 }); 257 258 test_interpolation({ 259 property: 'height', 260 from: 'calc-size(calc-size(auto, size / 2), size * 2)', 261 to: 'calc-size(auto, size * 2)', 262 }, [ 263 { at: -0.25, expect: '75px' }, 264 { at: 0, expect: '100px' }, 265 { at: 0.75, expect: '175px' }, 266 { at: 1, expect: '200px' }, 267 { at: 1.25, expect: '225px' }, 268 ]); 269 270 test_interpolation({ 271 property: 'height', 272 from: 'calc-size(calc-size(min-content, size / 2), size * 2)', /* 100px */ 273 to: 'calc-size(calc-size(any, 150px), size * 2)', /* 300px */ 274 }, [ 275 { at: -0.25, expect: '50px' }, 276 { at: 0, expect: '100px' }, 277 { at: 0.75, expect: '250px' }, 278 { at: 1, expect: '300px' }, 279 { at: 1.25, expect: '350px' }, 280 ]); 281 282 test_interpolation({ 283 property: 'height', 284 from: 'calc-size(calc-size(auto, size / 2), size * 2)', 285 to: 'calc-size(auto, size * 5)', 286 }, [ 287 { at: -0.125, expect: '50px' }, 288 { at: 0, expect: '100px' }, 289 { at: 0.75, expect: '400px' }, 290 { at: 1, expect: '500px' }, 291 { at: 1.25, expect: '600px' }, 292 ]); 293 294 test_interpolation({ 295 property: 'height', 296 from: 'calc-size(calc-size(100px, size / 2), size * 2)', 297 to: 'calc-size(12.5%, size * 4)', 298 }, [ 299 { at: -0.25, expect: '87.5px' }, 300 { at: 0, expect: '100px' }, 301 { at: 0.75, expect: '137.5px' }, 302 { at: 1, expect: '150px' }, 303 { at: 1.25, expect: '162.5px' }, 304 ]); 305 306 test_interpolation({ 307 property: 'height', 308 from: 'calc-size(calc-size(100px, size * 2), size * 2)', 309 to: 'calc-size(100px, size * 3)', 310 }, [ 311 { at: -0.25, expect: '425px' }, 312 { at: 0, expect: '400px' }, 313 { at: 0.75, expect: '325px' }, 314 { at: 1, expect: '300px' }, 315 { at: 1.25, expect: '275px' }, 316 ]); 317 318 test_interpolation({ 319 property: 'height', 320 from: 'calc-size(calc-size(auto, size / 2), size * 2)', 321 to: 'calc-size(calc-size(calc-size(auto, size + size / 2 + size / 2), size + size), size / 4 + size / 8 + size / 8)', 322 }, [ 323 { at: -0.25, expect: '75px' }, 324 { at: 0, expect: '100px' }, 325 { at: 0.75, expect: '175px' }, 326 { at: 1, expect: '200px' }, 327 { at: 1.25, expect: '225px' }, 328 ]); 329 330 // Test that we don't interpolate if doing so would require too much expansion. 331 // See https://github.com/w3c/csswg-drafts/issues/10369 . 332 test_no_interpolation({ 333 property: 'height', 334 from: 'calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(calc-size(auto, size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2), size / 2 + size / 2)', 335 to: 'calc-size(auto, size * 3)', 336 }); 337 338 test_interpolation({ 339 property: 'height', 340 from: 'calc-size(20%, size)', 341 to: 'calc-size(60%, size)', 342 }, [ 343 { at: 0, expect: '60px' }, 344 { at: 0.5, expect: '120px' }, 345 { at: 1, expect: '180px' }, 346 ]); 347 348 document.documentElement.classList.add("no-parent-height"); 349 350 // repeat the previous test, but with height:auto on the parent 351 test_interpolation({ 352 property: 'height', 353 from: 'calc-size(20%, size)', 354 to: 'calc-size(60%, size)', 355 }, [ 356 { at: 0, expect: '100px' }, 357 { at: 0.5, expect: '100px' }, 358 { at: 1, expect: '100px' }, 359 ]); 360 361 test_interpolation({ 362 property: 'height', 363 from: 'calc-size(50px, size)', 364 to: 'calc-size(60%, size)', 365 }, [ 366 { at: 0, expect: '100px' }, 367 { at: 0.5, expect: '100px' }, 368 { at: 1, expect: '100px' }, 369 ]); 370 371 test_interpolation({ 372 property: 'height', 373 from: 'calc-size(50px, size)', 374 to: 'calc-size(200px, size)', 375 }, [ 376 { at: 0, expect: '50px' }, 377 { at: 0.5, expect: '125px' }, 378 { at: 1, expect: '200px' }, 379 ]); 380 381 document.documentElement.classList.remove("no-parent-height"); 382 383 test_no_interpolation({ 384 property: 'height', 385 from: 'calc-size(50%, size)', 386 to: 'calc-size(min-content, size)', 387 }); 388 389 test_interpolation({ 390 property: 'height', 391 from: 'calc-size(50px, size)', 392 to: 'calc-size(min-content, size)', 393 }, [ 394 { at: 0, expect: '50px' }, 395 { at: 0.5, expect: '75px' }, 396 { at: 1, expect: '100px' }, 397 ]); 398 399 </script>