-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathindex.html
318 lines (242 loc) · 14.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A11y Toggle</title>
<link rel="stylesheet" href="./styles.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/themes/prism-coy.min.css" />
</head>
<body>
<main class="main" id="main" aria-label="Content">
<section>
<div class="container">
<h1 class="title">A11y Toggle</h1>
<p><a href="https://github.com/edenspiekermann/a11y-toggle">Get the code on GitHub</a> or skip to a specific documentation section right away:</p>
<ul>
<li><a href="#getting-started">Getting started</a></li>
<li><a href="#basic-example">Basic example</a></li>
<li><a href="#expanded-by-default">Expanded by default</a></li>
<li><a href="#non-button-toggles">Non-button toggles</a></li>
<li><a href="#multi-toggles">Multi toggles</a></li>
<li><a href="#animations">Animations</a></li>
<li><a href="#connected-toggles">Connected toggles</a></li>
<li><a href="#dynamically-injected-toggles">Dynamically injected toggles</a></li>
</ul>
<button data-a11y-toggle="explanations" type="button" class="button">
Read more about why you might need this. »
</button>
<div id="explanations">
<p>Pure CSS toggles using the <a href="https://css-tricks.com/the-checkbox-hack/">checkbox hack</a> introduce some usability and accessibility problems.</p>
<p>For starters, the checkbox hack relies on the <code>:checked</code> pseudo-class, which is <a href="http://quirksmode.org/css/selectors/mobile.html#t60">not supported everywhere</a>. For instance, BlackBerry browser, Opera Mini, Android Stock Browser and Firefox Android (amongst others) do not support this selector, making the whole thing broken.</p>
<p>On top of that, in order to be fully accessible a content toggle needs some extra attributes that cannot be toggled without JavaScript. The toggle itself needs a <code>aria-controls</code> attribute linking to the expandable element, and a <code>aria-expanded</code> attribute describing its state (expanded or collapsed). The collapsed element itself needs the <code>aria-hidden</code> attribute when invisible.</p>
<p><a href="https://github.com/edenspiekermann/a11y-toggle">a11y-toggle</a> takes care of all these considerations for you. Initial necessary attributes are being added by the script so you don’t even have to care about this.</p>
<p><strong>No more excuse now. Make your toggles accessible.</strong></p>
</div>
</div>
</section>
<section id="getting-started">
<div class="container">
<h2 class="title">Getting started</h2>
<p>To get started, simply include a11y-toggle.js (ideally the minified version, of course) in your document. It can be either in the <code><head></code> or at the bottom of the <code><body></code> although the latter the better, for performance reasons.</p>
<pre class="language-html"><code>
<script src="a11y-toggle.min.js" async></script>
</code></pre>
<p>That’s it! There is no need to initialize anything as everything else is being handled by the script itself. Simply check the <a href="#basic-example">next section</a> to see how to declare your toggles.</p>
</div>
</section>
<section id="basic-example">
<div class="container">
<h2 class="title">Basic example</h2>
<p>The bare minimum is a button with the <code>data-a11y-toggle</code> attribute mapped to an existing <code>id</code> in the document. You can have a look at the code below.</p>
<pre class="language-html"><code>
<button type="button" data-a11y-toggle="target">
Toggle code »
</button>
<div id="target">
Some content…
</div>
</code></pre>
<p>Initial ARIA-specific attributes such as <code>aria-expanded</code>, <code>aria-hidden</code> and <code>aria-labelledby</code>, as well as <code>id</code> on the toggle element (if none already) are being added automatically.</p>
<p>On the CSS Side, only hiding <code>aria-hidden</code> content is strictly necessary. It is also recommended to hide the button when JavaScript is disabled, by checking the presence of the <code>aria-controls</code> attribute for instance.</p>
<pre class="language-css"><code>
[aria-hidden='true'],
[data-a11y-toggle]:not([aria-controls]) {
display: none;
}
</code></pre>
<p>Note: globally hiding elements with <code>[aria-hidden="true"]</code> can have rendering issues with third party integrations. Only known to date is with Google Maps, in which it prevents the map tiles to render. Therefore <a href="https://github.com/edenspiekermann/a11y-toggle/issues/30">it needs to be resetted inside a Google Maps container</a>.</p>
<p data-height="191" data-theme-id="0" data-slug-hash="MyVNdN" data-default-tab="result" data-user="KittyGiraudel" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/KittyGiraudel/pen/MyVNdN/">a11y-toggle — Basic example</a> by Kitty Giraudel (<a href="http://codepen.io/KittyGiraudel">@KittyGiraudel</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>
</section>
<section id="expanded-by-default">
<div class="container">
<h2 class="title">Expanded by default</h2>
<p>If you want the content to be expanded by default, you can add a <code>data-a11y-toggle-open</code> attribute to the target element (not the toggle itself).</p>
<p>Note that this is the default behaviour when JavaScript is disabled, so that the content remains accessible even without JavaScript.</p>
<pre class="language-html"><code>
<button type="button" data-a11y-toggle="target">
Toggle code »
</button>
<div id="target" data-a11y-toggle-open>
Some content that is expanded by default…
</div>
</code></pre>
<p data-height="191" data-theme-id="0" data-slug-hash="bpvXPQ" data-default-tab="result" data-user="KittyGiraudel" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/KittyGiraudel/pen/bpvXPQ/">a11y-toggle — Expanded by default</a> by Kitty Giraudel (<a href="http://codepen.io/KittyGiraudel">@KittyGiraudel</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>
</section>
<section id="non-button-toggles">
<div class="container">
<h2 class="title">Non-button toggles</h2>
<p>A <code><button></code> element is definitely the most suited one for a toggle, however sometimes it might not be possible for whatever reason.</p>
<p>It is possible to use any other element as a toggle however you must manually specify the following attributes:</p>
<ul>
<li><code>role="button"</code></li>
<li><code>tabindex="0"</code></li>
</ul>
<pre class="language-html"><code>
<span role="button" tabindex="0" data-a11y-toggle="target">
Toggle code »
</span>
<div id="target">
Some content…
</div>
</code></pre>
<p>Because of <a href="https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile">a nasty bug on iOS</a>, you have to add this rule to your stylesheet to make the toggle actually clickable. Apparently, no pointer means no events.</p>
<pre class="language-css"><code>
[role="button"] {
cursor: pointer;
}
</code></pre>
<p data-height="191" data-theme-id="0" data-slug-hash="XdEvvm" data-default-tab="result" data-user="KittyGiraudel" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/KittyGiraudel/pen/XdEvvm/">a11y-toggle — Non-button toggles</a> by Kitty Giraudel (<a href="http://codepen.io/KittyGiraudel">@KittyGiraudel</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>
</section>
<section id="multi-toggles">
<div class="container">
<h2 class="title">Multi toggles</h2>
<p>A collapsible container can have several toggles able to control its visibility. There is no difference in markup regarding multi toggles.</p>
<pre class="language-html"><code>
<button type="button" data-a11y-toggle="target">
Toggle code »
</button>
<button type="button" data-a11y-toggle="target">
Toggle code »
</button>
<div id="target">
Some content…
</div>
</code></pre>
<p data-height="191" data-theme-id="0" data-slug-hash="Yqammr" data-default-tab="result" data-user="KittyGiraudel" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/KittyGiraudel/pen/Yqammr/">a11y-toggle — Multi toggles</a> by Kitty Giraudel (<a href="http://codepen.io/KittyGiraudel">@KittyGiraudel</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>
</section>
<section id="animations">
<div class="container">
<h2 class="title">Animations</h2>
<p>Given that a11y-toggle is completely unopinionated regarding the styling layer, it is really up to the developer to implete the sliding and/or fading animation. Here is an example below. Hat tip to <a href="http://a11y.nicolas-hoffmann.net/hide-show/#expand_9">Nicolas Hoffman</a>.</p>
<p>The markup does not change compared to the original version except that we add a class to the collapsible sections to be able to target them in CSS.</p>
<pre class="language-html"><code>
<button type="button" data-a11y-toggle="target">
Toggle code »
</button>
<div class="collapsible-box" id="target">
Some content…
</div>
</code></pre>
<p>The styles do not rely on <code>display: none</code> anymore but a tricky / hacky combination of declarations to make the magic happen.</p>
<pre class="language-css"><code>
.collapsible-box {
overflow: hidden;
opacity: 1;
max-height: 80em;
visibility: visible;
transition:
visibility 0s ease,
max-height 2s ease,
opacity 2s ease;
transition-delay: 0s;
}
.collapsible-box[aria-hidden='true'] {
max-height: 0;
opacity: 0;
visibility: hidden;
transition-delay: 2s, 0s, 0s;
}
</code></pre>
<p data-height="191" data-theme-id="0" data-slug-hash="wGmVVY" data-default-tab="result" data-user="KittyGiraudel" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/KittyGiraudel/pen/wGmVVY/">a11y-toggle — Animations</a> by Kitty Giraudel (<a href="http://codepen.io/KittyGiraudel">@KittyGiraudel</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>
</section>
<section id="connected-toggles">
<div class="container">
<h2 class="title">Connected toggles</h2>
<p>The library does not provide out-of-the-box support for connected toggles, which are a set of toggles with only one expanded at any time.</p>
<p>However with a tiny bit of JavaScript, it is possible to leverage the capabilities of the library to add this feature.</p>
<pre class="language-html"><code>
<div class="connected-toggles">
<button data-a11y-toggle="target-1" type="button">
Toggle content 1 »
</button>
<button data-a11y-toggle="target-2" type="button">
Toggle content 2 »
</button>
<div id="target-1">
Some content (1)…
</div>
<div id="target-2">
Some content (2)…
</div>
</div>
</code></pre>
<p>The trick is to collapse all targets in the set when one is being activated, except this one. The JavaScript snippet to achieve that should be pretty straight-forward.</p>
<pre class="language-javascript"><code>
function collapse (toggle) {
var id = toggle.getAttribute('data-a11y-toggle');
var collapsibleBox = document.getElementById(id);
collapsibleBox.setAttribute('aria-hidden', true);
toggle.setAttribute('aria-expanded', false);
}
function collapseAll (event) {
toggles
.filter(function (toggle) {
return toggle !== event.target;
})
.forEach(collapse);
}
var toggles = Array.prototype.slice.call(
document.querySelectorAll('.connected-toggles [data-a11y-toggle]')
);
toggles.forEach(function (toggle) {
toggle.addEventListener('click', collapseAll);
});
</code></pre>
<p>Note that if you have several instances of connected toggles on your page, you might want to read <a href="https://github.com/edenspiekermann/a11y-toggle/issues/31">this issue</a>, as the current code is too simple to cover this edge case.</p>
<p><strong>Beware!</strong> a11y-toggle is not a library to build tabs. While it certainly is possible to do so, remember that tabs imply other accessibility concerns which should be taken care of.</p>
<p data-height="191" data-theme-id="0" data-slug-hash="NNBmpR" data-default-tab="result" data-user="KittyGiraudel" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/KittyGiraudel/pen/NNBmpR/">a11y-toggle — Connected toggles</a> by Kitty Giraudel (<a href="http://codepen.io/KittyGiraudel">@KittyGiraudel</a>) on <a href="http://codepen.io">CodePen</a>.</p>
</div>
</section>
<section id="dynamically-injected-toggles">
<div class="container">
<h2 class="title">Dynamically injected toggles</h2>
<p>a11y-toggle fires once when the DOM is fully loaded (<code>DOMContentLoaded</code>). You will have to relaunch it if you dynamically add new toggles with JavaScript.</p>
<p>Thankfully, a11y-toggle exposes an <code>a11yToggle</code> function on the global object.</p>
<pre class="language-javascript"><code>
window.a11yToggle();
</code></pre>
<p>If you do not want to reinitialise everything, you can pass a context to the <code>a11yToggle</code> function which will be used as a root for <code>.querySelectorAll</code>.
<pre class="language-javascript"><code>
var newContainer = document.getElementById('new-container');
window.a11yToggle(newContainer);
</code></pre>
</div>
</section>
<footer role="contentinfo">
<div class="container">
© 2016 <a href="http://edenspiekermann.com">Edenspiekermann</a>
</div>
</footer>
</main>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/prism.min.js"></script>
<script src="main.js"></script>
</body>
</html>