select-base-appearance-computed-style.html (6985B)
1 <!DOCTYPE html> 2 <link rel=author href="mailto:jarhar@chromium.org"> 3 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/10857"> 4 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/11486"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 8 <style> 9 select, ::picker(select) { 10 appearance: base-select; 11 } 12 #sibling { 13 color: CanvasText; 14 background-color: Canvas; 15 } 16 #parent { 17 text-transform: uppercase; 18 text-align: end; 19 } 20 </style> 21 22 <div id=parent> 23 <select> 24 <button>button</button> 25 <div id=parent-in-picker> 26 <option>option</option> 27 <optgroup> 28 <legend>legend</legend> 29 <option>option in optgroup</option> 30 </optgroup> 31 </div> 32 </select> 33 <div id=sibling>sibling</div> 34 </div> 35 <div id=initial></div> 36 37 <script> 38 const select = document.querySelector('select'); 39 const parent = document.getElementById('parent'); 40 const parentInPicker = document.getElementById('parent-in-picker'); 41 const sibling = document.getElementById('sibling'); 42 const intial = document.getElementById('initial'); 43 const button = document.querySelector('button'); 44 const option = document.querySelector('option'); 45 const optgroup = document.querySelector('optgroup'); 46 const legend = document.querySelector('legend'); 47 const optgroupOption = document.querySelector('optgroup > option'); 48 49 const canvas = getComputedStyle(sibling).backgroundColor; 50 const canvasText = getComputedStyle(sibling).color; 51 52 // All of the elements should inherit these properties. 53 const expectedInheritedProperties = { 54 'font-size': '24px', 55 'font-family': 'monospace', 56 'font-stretch': '150%', 57 'font-style': 'italic', 58 'font-variant': 'small-caps', 59 'font-weight': '500', 60 'line-height': '13px', 61 'text-shadow': 'rgb(1, 1, 1) 1px 1px 1px', 62 'text-rendering': 'optimizelegibility', 63 'letter-spacing': '1px', 64 'word-spacing': '2px', 65 'color': 'rgb(255, 0, 0)', 66 }; 67 for (const [property, value] of Object.entries(expectedInheritedProperties)) { 68 parent.style[property] = value; 69 parentInPicker.style[property] = value; 70 } 71 72 function testProperties(style, expectedProperties) { 73 const parentStyle = getComputedStyle(parent); 74 const initialStyle = getComputedStyle(initial); 75 76 for (let [property, value] of Object.entries(expectedProperties)) { 77 if (value == 'initial') { 78 value = initialStyle[property]; 79 } else if (value.endsWith('em')) { 80 // Properties with em units get serialized into px. In order to calculate 81 // the expected value of an em unit, we can set another element to the 82 // expected amount of ems and then serialize that one. 83 sibling.style[property] = value; 84 value = getComputedStyle(sibling)[property]; 85 } 86 assert_equals(style[property], value, property); 87 } 88 89 for (const [property, value] of Object.entries(expectedInheritedProperties)) { 90 // Don't test whether a property was inherited if expectedProperties 91 // already has an expected value for it. 92 if (!Object.keys(expectedProperties).includes(property)) { 93 assert_equals(style[property], value, property); 94 } 95 } 96 } 97 98 test(() => { 99 const expectedProperties = { 100 'background-color': 'rgba(0, 0, 0, 0)', 101 'border': '1px solid rgb(255, 0, 0)', /* color is currentColor */ 102 'min-inline-size': 'calc-size(auto, max(size, 24px))', 103 'display': 'inline-flex', 104 'user-select': 'none', 105 'min-block-size': `calc-size(auto, max(size, 24px, ${expectedInheritedProperties['line-height']}))`, 106 'padding-block-start': '0.25em', 107 'padding-block-end': '0.25em', 108 'padding-inline-start': '0.5em', 109 'padding-inline-end': '0.5em', 110 'gap': '0.5em', 111 'border-radius': '0.5em', 112 'text-indent': 'initial', 113 'cursor': 'initial', 114 'white-space': 'initial', 115 'align-items': 'initial', 116 'text-transform': 'initial', 117 'text-align': 'initial' 118 }; 119 testProperties(getComputedStyle(select), expectedProperties); 120 }, 'UA styles of base appearance <select>.'); 121 122 test(() => { 123 // margin-inline-start:auto is not tested here because the value 'auto' gets 124 // serialized to '0px'. 125 const expectedProperties = { 126 'content': 'counter(fake-counter-name, disclosure-open)', 127 'display': 'block' 128 }; 129 testProperties(getComputedStyle(select, '::picker-icon'), expectedProperties); 130 }, 'UA styles of base appearance select::picker-icon.'); 131 132 test(() => { 133 // Properties not tested here: 134 // min-inline-size: anchor-size(self-inline) 135 // min-block-size: stretch 136 const expectedProperties = { 137 'box-sizing': 'border-box', 138 'padding': '0px', 139 'margin': '0px', 140 'inset': 'auto', 141 'overflow': 'auto', 142 // position-area is actually 'block-end span-inline-end' but gets 143 // serialized this way. position-try-fallbacks also gets serialized 144 // differently. 145 // https://drafts.csswg.org/css-anchor-position/#position-area-computed 146 'position-area': 'end span-end', 147 'position-try-order': 'most-block-size', 148 'position-try-fallbacks': 'start span-end, end span-start, start span-start', 149 'border': `1px solid ${canvasText}`, 150 'background-color': canvas, 151 'color': canvasText 152 }; 153 testProperties(getComputedStyle(select, '::picker(select)'), expectedProperties); 154 }, 'UA styles of base appearance ::picker(select)'); 155 156 test(() => { 157 const expectedProperties = { 158 'min-inline-size': '24px', 159 'min-block-size': '24px', 160 'padding-block-start': '0px', 161 'padding-block-end': '0px', 162 'padding-inline-start': '0.5em', 163 'padding-inline-end': '0.5em', 164 'display': 'flex', 165 'gap': '0.5em', 166 'align-items': 'center', 167 'white-space': 'nowrap' 168 }; 169 testProperties(getComputedStyle(option), expectedProperties); 170 }, 'UA styles of base appearance <option>.'); 171 172 test(() => { 173 const expectedProperties = { 174 'content': `"${String.fromCodePoint(10003)}"` 175 } 176 testProperties(getComputedStyle(option, '::checkmark'), expectedProperties); 177 }, 'UA styles of base appearance option::checkmark.'); 178 179 test(() => { 180 const expectedProperties = { 181 'font-weight': '700', 182 'display': 'block' 183 }; 184 testProperties(getComputedStyle(optgroup), expectedProperties); 185 }, 'UA styles of base appearance <optgroup>.'); 186 187 test(() => { 188 const expectedProperties = { 189 'min-block-size': expectedInheritedProperties['line-height'], 190 'padding-inline': '0.5em', 191 'display': 'block', 192 'unicode-bidi': 'isolate', 193 'font-weight': '700' 194 }; 195 testProperties(getComputedStyle(legend), expectedProperties); 196 }, 'UA styles of base appearance <legend>.'); 197 198 test(() => { 199 // Properties not tested here: 200 // all: unset 201 const expectedProperties = { 202 'display': 'contents' 203 }; 204 testProperties(getComputedStyle(button), expectedProperties); 205 }, 'UA styles of base appearance select <button>.'); 206 207 test(() => { 208 const expectedProperties = { 209 'font-weight': '400', 210 }; 211 testProperties(getComputedStyle(optgroupOption), expectedProperties); 212 }, 'UA styles of base appearance <option> in <optgroup>.'); 213 </script>