This Proposal is Deprecated
28 |-
29 |
- 30 | The style part of the problem — 31 | responding to state — 32 | is conditional CSS 33 | that can be handled with 34 | 35 | container style queries. 36 | 37 |
- 38 | The issue of creating toggles 39 | should be addressed 40 | in other parts of the platform 41 | with features like 42 | 43 | invoker commands. 44 | 45 |
48 | In retrospect, 49 | I'm afraid this exploration 50 | (driven by Chrome) 51 | acted as a distraction 52 | from more viable solutions -- 53 | while requiring extra effort from accessibility experts 54 | to document all the issues with our approach. 55 |
56 |60 | What are CSS Toggles? 61 |
62 |63 | The goal of this (work in progress) feature 64 | is to make it possible for CSS to manage 65 | presentational state 66 | for patterns such as tabs/accordians, carousels, color modes, etc. 67 | There are still many questions to be answered 68 | around the scope, syntax, 69 | and (most importantly) accessibility 70 | of a feature like this in CSS. 71 |
72 |73 | This polyfill is designed to help us 74 | explore those questions. 75 | It implements the 76 | draft spec syntax 77 | as currently written, where possible -- 78 | in addition to some of the 79 | extensions proposed in our 80 | explainer. 81 |
82 |83 | 84 | The current polyfill implementation is a naive attempt 85 | to uncover and document any issues in the spec — 86 | which means that several of the following demos 87 | 88 | are currently inaccessible. 89 | 90 | 91 | While we hope that some of those issues 92 | can be resolved here in the polyfill, 93 | others may require changes to the spec itself, 94 | or access to browser-internals 95 | that cannot be polyfilled well using JS. 96 |
97 |98 | We're excited for you to play with this, 99 | suggest additional use-cases, 100 | help uncover undocumented issues, 101 | and provide us with feedback: 102 |
103 | 111 |115 | 🔗 116 | Global color toggle 117 |
118 | 119 |html {
120 | toggle-root: mode [auto light dark];
121 | }
122 |
123 | html:toggle(mode light) { ... }
124 | html:toggle(mode dark) { ... }
125 |
126 | .mode-btn {
127 | toggle-trigger: mode;
128 | }
129 | 133 | 🔗 134 | Binary self-toggle switches 135 |
136 |137 | Issue 20: 138 | There's a conflict between the HTML listitem role 139 | and the added ARIA role of 'button' 140 | used to make these interactive. 141 |
142 |-
143 |
- write an explainer 144 |
- draft a specification 145 |
- create a polyfill 146 |
- make a demo page 147 |
.todo li {
149 | toggle: todo self;
150 | list-style-type: '❌ ';
151 | }
152 |
153 | .todo li:toggle(todo) {
154 | list-style-type: '✅ ';
155 | }
156 | 160 | 🔗 161 | Accordion/disclosure components 162 |
163 |
164 | The goal of toggle-visibility
165 | is for browsers to handle accessibility
166 | and discoverability by default.
167 | We'll keep working to improve the polyfill a11y as well,
168 | but may not be able to achieve the same results.
169 |
171 | Issue 13:
172 | While aria-expanded may work in some situations,
173 | it has the same issues listed above with conflicting semantics/roles.
174 |
-
176 |
177 |
- Establish a toggle 178 |
.accordion>dt { 179 | toggle: glossary; 180 | }
181 |
182 | - Toggle item visibility 183 |
.accordion>dd { 184 | toggle-visibility: toggle glossary; 185 | }
186 |
187 | - Style the summary 188 |
.accordion>dt::marker { 189 | content: '👉🏽 '; 190 | } 191 | 192 | .accordion>dt:toggle(glossary) { 193 | background-color: var(--brand); 194 | color: var(--bg); 195 | } 196 | 197 | .accordion>dt:toggle(glossary)::marker { 198 | content: '👇🏽 '; 199 | } 200 |
201 |
206 | 🔗 207 | Tree view 208 |
209 |210 | Issue 23: 211 | Does 'tree view' require different semantics 212 | than simply 'nested disclosures' 213 | (which may better describe the current behavior)? 214 |
215 |-
216 |
- home 217 |
- 218 | 221 | 234 | 235 |
.nested {
237 | toggle: tree;
238 | }
239 |
240 | .nested+ul {
241 | toggle-visibility: toggle tree;
242 | }
243 | 247 | 🔗 248 | Tabs or exclusive accordions 249 |
250 |-
251 |
- 252 | Issue 9: 253 | Not possible to change initial state for one toggle in a group. 254 | 255 |
-
256 | Issue 13:
257 | In this case,
258 | the expected a11y handling requires the
259 |
tabrole 260 | andaria-selected. 261 | Is there a way to clearly support both 262 | disclosure and tab a11y using this shared syntax? 263 |
264 |
panel-tab {
268 | toggle: tab 1 at 0 group sticky;
269 | grid-row: tab;
270 | }panel-tab:toggle(tab) {
274 | background-color: var(--callout);
275 | }
276 |
277 | panel-card {
278 | toggle-visibility: toggle tab;
279 | grid-area: card;
280 | }286 | 🔗 287 | Named states 288 |
289 |290 | Issue 21: 291 | These act like radio buttons, 292 | but the proper a11y handling is not obvious from the syntax. 293 |
294 |.colors {
301 | toggle-root: colors [grape green blue red] at blue;
302 | }
303 |
304 | .colors button {
305 | toggle-trigger: colors;
306 | }
307 |
308 | /* for each color */
309 | .colors button.grape {
310 | toggle-trigger: colors grape;
311 | }
312 |
313 | .show-colors:toggle(colors grape) {
314 | background-color: var(--grape-9);
315 | }
316 |
317 | 322 | 🔗 323 | State machine transitions 324 |
325 |326 | This functionality & syntax is proposed 327 | in the explainer 328 | as syntax sugar on top of the existing functionality. 329 | However, it's not yet clear that there are 330 | entirely presentational (CSS-only) use-cases. 331 | If you have ideas, we'd love to hear from you. 332 | The following example would involve JS in production. 333 |
334 |335 | Issue 22: 336 | It is not clear in the a11y tree which 'transitions' 337 | are currently allowed/disabled, 338 | and the resulting generated content 339 | is not propery announced or selectable. 340 |
341 |@machine request {
349 | idle {
350 | try: loading;
351 | }
352 |
353 | loading {
354 | resolve: success;
355 | reject: failure;
356 | reset: idle;
357 | }
358 |
359 | failure {
360 | try: loading;
361 | reset: idle;
362 | }
363 |
364 | success {
365 | reset: idle;
366 | }
367 | }
368 |
369 | /* establish a toggle based on the machine */
370 | .request {
371 | toggle-root: machine(request);
372 | }
373 |
374 | /* the individual trigger buttons call 'transitions' */
375 | .request button[data-do="try"] {
376 | toggle-trigger: request do(try);
377 | }
378 |