ch-pseudo-recalc-on-font-load.html (2942B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Length unit 'ch' used in pseudo elements should be recalculated after loading a web font</title> 4 <link rel="help" href="https://www.w3.org/TR/css-font-loading-3/#font-face-load"> 5 <link rel="help" href="https://www.w3.org/TR/css-values-3/#font-relative-lengths"> 6 <link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#first-letter-styling"> 7 <link rel="author" href="xiaochengh@chromium.org"> 8 <script src="/resources/testharness.js"></script> 9 <script src="/resources/testharnessreport.js"></script> 10 <style> 11 .container { 12 font: 25px/1 "custom font", monospace; 13 } 14 15 .before::before, 16 .after::after, 17 .first-letter::first-letter, 18 .first-line::first-line { 19 font-family: monospace; 20 font-size: 1ch; /* Refers to originating element's font metrics, which are different from self font metrics. */ 21 } 22 23 .before::before, 24 .after::after { 25 content: 'text'; 26 } 27 28 /* Defined separately so that browsers that haven't shipped it can still pass other tests. */ 29 .marker::marker { 30 font-family: monospace; 31 font-size: 1ch; 32 content: 'text'; 33 } 34 35 </style> 36 37 <div class="container before"></div> 38 <div class="container after"></div> 39 <div class="container first-letter">text</div> 40 <div class="container first-line">text</div> 41 <li class="container marker"></li> 42 43 <script> 44 function parseFontSizeInPx(element, pseudoElement) { 45 const value = getComputedStyle(element, pseudoElement).fontSize; 46 if (!value.endsWith('px')) 47 return NaN; 48 return parseFloat(value); 49 } 50 51 const testCases = ['before', 'after', 'first-letter', 'first-line', 'marker']; 52 const elements = testCases.map(testCase => document.querySelector('.' + testCase)); 53 const asyncTests = testCases.map( 54 testCase => async_test(`ch in pseudo-element ::${testCase} should be recalculated after loading a web font`)); 55 56 // Before loading custom font, tests should be rendered with monospace 57 // fallback and have a '1ch' measurement much shorter than 25px. 58 for (let i = 0; i < testCases.length; ++i) { 59 asyncTests[i].step(() => { 60 const fontSizePx = parseFontSizeInPx(elements[i], '::' + testCases[i]); 61 assert_less_than(fontSizePx, 24); 62 }); 63 } 64 65 // Insert custom font into style sheet and load it 66 const customFont = new FontFace('custom font', 'url(/fonts/Ahem.ttf)'); 67 document.fonts.add(customFont); 68 69 // After loading custom font, tests should be rendered with the custom font, 70 // which is Ahem, and have a '1ch' measurement that equals 25px. 71 customFont.load().then( 72 () => { 73 for (let i = 0; i < testCases.length; ++i) { 74 asyncTests[i].step(() => { 75 const fontSizePx = parseFontSizeInPx(elements[i], '::' + testCases[i]); 76 assert_approx_equals(fontSizePx, 25, 0.1); 77 asyncTests[i].done(); 78 }); 79 } 80 }, 81 () => { 82 for (let i = 0; i < testCases.length; ++i) { 83 asyncTests[i].step(() => { 84 assert_unreached('Failed to load font'); 85 }); 86 } 87 } 88 ); 89 </script>