layer-cssom-order-reverse.html (3689B)
1 <!DOCTYPE html> 2 <title>CSS Cascade Layers: at-rule and style invalidation on layer order changes</title> 3 <link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering"> 4 <link rel="author" href="mailto:xiaochengh@chromium.org"> 5 <link rel="stylesheet" href="/fonts/ahem.css"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <style> 9 #reference { 10 color: green; 11 font: 20px/1 ahem; 12 width: max-content; 13 } 14 </style> 15 16 <div id=target>Lorem ipsum</div> 17 <div id=reference>Lorem ipsum</div> 18 19 <script> 20 const testCases = [ 21 { 22 title: 'Insert layer invalidates style', 23 sheets: [ 24 '', 25 ` 26 @layer first { 27 #target { color: green; } 28 } 29 @layer second { 30 #target { color: red; } 31 } 32 `, 33 ], 34 update: function(sheets) { 35 sheets[0].insertRule('@layer second {}', 0); 36 }, 37 property: 'color', 38 }, 39 { 40 title: 'Delete layer invalidates style', 41 sheets: [ 42 '@layer second {}', 43 ` 44 @layer first { 45 #target { color: red; } 46 } 47 @layer second { 48 #target { color: green; } 49 } 50 `, 51 ], 52 update: function(sheets) { 53 sheets[0].deleteRule(0); 54 }, 55 property: 'color', 56 }, 57 { 58 title: 'Insert layer invalidates @font-face', 59 sheets: [ 60 '', 61 ` 62 @layer first { 63 @font-face { 64 font-family: custom; 65 src: local('Ahem'), url('/fonts/Ahem.ttf'); 66 } 67 } 68 @layer second { 69 @font-face { 70 font-family: custom; 71 src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff'); 72 } 73 } 74 #target { font: 20px/1 custom; width: max-content; } 75 `, 76 ], 77 update: async function(sheets) { 78 await document.fonts.load('20px/1 ahem'); 79 await document.fonts.load('20px/1 custom'); 80 document.body.offsetLeft; // Force style recalc 81 sheets[0].insertRule('@layer second {}', 0); 82 await document.fonts.load('20px/1 custom'); 83 }, 84 property: 'width', 85 }, 86 { 87 title: 'Delete layer invalidates @font-face', 88 sheets: [ 89 '@layer second {}', 90 ` 91 @layer first { 92 @font-face { 93 font-family: custom; 94 src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff'); 95 } 96 } 97 @layer second { 98 @font-face { 99 font-family: custom; 100 src: local('Ahem'), url('/fonts/Ahem.ttf'); 101 } 102 } 103 #target { font: 20px/1 custom; width: max-content; } 104 `, 105 ], 106 update: async function(sheets) { 107 await document.fonts.load('20px/1 ahem'); 108 await document.fonts.load('20px/1 custom'); 109 document.body.offsetLeft; // Force style recalc 110 sheets[0].deleteRule(0); 111 await document.fonts.load('20px/1 custom'); 112 }, 113 property: 'width', 114 }, 115 ]; 116 117 for (let testCase of testCases) { 118 promise_test(async test => { 119 const styleElements = testCase.sheets.map(sheet => { 120 const element = document.createElement('style'); 121 element.appendChild(document.createTextNode(sheet)); 122 document.head.appendChild(element); 123 return element; 124 }); 125 test.add_cleanup(() => { 126 for (let element of styleElements) 127 element.remove(); 128 }); 129 130 const sheets = styleElements.map(element => element.sheet); 131 await testCase.update(sheets); 132 const actual = getComputedStyle(target).getPropertyValue(testCase.property); 133 const expected = getComputedStyle(reference).getPropertyValue(testCase.property); 134 assert_equals(actual, expected); 135 }, testCase.title); 136 } 137 </script>