-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathindex.html
More file actions
212 lines (185 loc) · 8.39 KB
/
index.html
File metadata and controls
212 lines (185 loc) · 8.39 KB
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
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<title>
Styled Radio Buttons
</title>
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script>
// remove no-js and add 'js' to the HTML
document.documentElement.className = document.documentElement.className.replace('no-js', 'js');
</script>
<link rel="stylesheet" href="../assets/css/--demo-only--.css">
<link rel="stylesheet" href="../assets/css/--shared--.css">
<link rel="stylesheet" href="../assets/css/radio--vhidden.css">
<link rel="stylesheet" href="../assets/css/radio.css">
</head>
<body>
<div class="demo-wrap">
<header class="demo-wrap__header">
<p class="demo-wrap__header__title">
Accessible Styled Form Controls
</p>
<nav>
<a href="https://github.com/scottaohara/a11y_styled_form_controls">See source on GitHub</a>,
<a href="/a11y_styled_form_controls">Index of styled form controls</a>
</nav>
</header>
<main aria-label="content">
<article class="demo">
<header>
<h1>Styled Radio Buttons</h1>
<p>Published: <time>July 26, 2018</time></p>
<p>Last updated: <time>December 17, 2018</time></p>
<p>
Cross-browser styling for HTML radio buttons.
</p>
</header>
<h2>
Pattern Demo
</h2>
<form>
<fieldset>
<legend>
Visually Hidden Radio Buttons
</legend>
<div class="c-radio">
<input type="radio" name="r_input" id="r_input_1" checked>
<label for="r_input_1">
Option 1
</label>
</div>
<div class="c-radio">
<input type="radio" name="r_input" id="r_input_2" disabled>
<label for="r_input_2">
Option 2 - this option is disabled and does not wrap,
just like the other options that don't wrap,
but it's specifically call it out here for reasons.
</label>
</div>
<div class="c-radio">
<input type="radio" name="r_input" id="r_input_3">
<label for="r_input_3">
Option 3
</label>
</div>
</fieldset>
</form>
<hr>
<form>
<fieldset>
<legend>
Restyled Radio Buttons
</legend>
<div> <!-- div used for vertically stacking radio buttons -->
<label class="n-radio-label">
<input type="radio" id="native_r" name="n_radio" class="n-radio">
<span>Restyle Option 1</span>
</label>
</div>
<div>
<label class="n-radio-label">
<input type="radio" id="native_r2" name="n_radio" class="n-radio" checked>
<span>Restyle Option 2</span>
</label>
</div>
<div>
<label class="n-radio-label">
<input type="radio" id="native_r3" name="n_radio" class="n-radio" disabled>
<span>Restyle Option 3 (disabled)</span>
</label>
</div>
</fieldset>
</form>
<details style="margin-top: 1em;" id="vdn" tabindex="-1">
<summary>Visual design note</summary>
<div>
<p>
<code>-moz-appearance: none;</code> does not completely remove the styling
from the radio button in Firefox prior to version 60.
</p>
<p>
The styled radio button utilizes <code>box-shadow</code>es to visually indicate
state. However <code>box-shadow</code> does not render as expected in IE11. The radio button looks as intended in Edge.
</p>
</div>
</details>
<section class="demo-details">
<h3>
Pattern Details
</h3>
<p>
These custom radio button styles follow one of the two following markup patterns:
</p>
<h4>1. Visually Hidden Radios</h4>
<details open>
<summary>Pattern Markup: Visually Hidden Style</summary>
<pre><code class="language-html"><div class="c-radio">
<input type="radio" name="my_radios" id="unique_id">
<label for="unique_id">
Label text here
</label>
</div></code></pre>
</details>
<p>
The <code>div class="c-radio"</code> container serves as a styling hook, utilizing <code>position: relative;</code> to keep absolutely positioned child elements, and pseudo elements, relative to the <a href="https://drafts.csswg.org/css2/visuren.html#x9">block container box</a>.
</p>
<p>
While the actual radio button is visually hidden from view, it remains essential to screen readers and keyboard user focus. Hiding it completely, with <code>display: none;</code>, for example, would require all the native radio button functionality to be rewritten in JavaScript. Allowing the native radio button to continue to receive focus ensures that the form control can lean on its native semantics.
</p>
<p>
Using standard visually hidden CSS to hide the native radio button off screen, or as a single pixel in the document, will mean that some screen reader users might be unable to locate the radio button. For instance, those searching by touch, or using a mouse while a screen reader announces what is being hovered. To mitigate this, the radio buttons have been positioned on top of their pseudo element styled counterparts, yet remain visually hidden. Note that NVDA does not announce the radio button role when hovered by mouse, regardless of it being styled or not, unless default NVDA settings are changed.
</p>
<p>
The <code>label</code>'s <code>:before</code> and <code>:after</code> pseudo elements are used to recreate the radio button in the new custom style. With the <code>:before</code> acting as the outer border of the radio button, and the <code>:after</code> as the visual indicator for the <code>checked</code> state.
</p>
<p>
The styling of the custom radio button is relayed from the state of the native form control. The <code>:checked</code>, <code>disabled</code>, and <code>:focus</code> radio button states will all be reflected in the custom style by the use of CSS sibling selectors. For example <code>input:checked ~ label:before {...}</code>
</p>
<h4 id="rstyled" tabindex=-1>2. Restyled Radio Elements</h4>
<details open>
<summary>Pattern Markup: Restyled Radio</summary>
<pre><code class="language-html"><label class="n-radio-label">
<input type="radio" name="n_radio" id="native_r2" class="n-radio">
<span>Label</span>
</label></code></pre>
</details>
<p>
With this markup pattern the radio button is restyled, having its native styling completely removed by CSS <code>appearance: none</code>, and then restyled via use of <code>box-shadow</code>s and <code>border</code>s.
</p>
<p>
The <code>span</code> element is used to wrap the radio button's text label so that a sibling selector can be used to modify the text's styling if the radio button is disabled.
</p>
<p>
Note, regarding the <a href="#vdn">visual design note</a>, there are issues with this styling technique in IE11 and Firefox pre-v60. If you need to support those browsers, then this pattern may not be sufficient, and the visually hidden technique should be considered instead.
</p>
<p>
IE11 and Edge can use <code>::-ms-check</code> to restyle both radio buttons and checkboxes. If using this vendor prefixed selector, make sure the checkbox and radio button styles don't clash.
</p>
<h4>Affects on Screen Reader Announcements?</h4>
<p>
Since the native radio buttons remains in the DOM, and are used as the focusable elements that control the state of their custom visualization, there are no alterations to how a screen reader announces styled radio buttons.
</p>
</section>
<h3>Continue reading</h3>
<p>
For additional information about creating minimal markup patterns for radio button and checkboxes, you should check out <a href="http://adrianroselli.com/2017/05/under-engineered-custom-radio-buttons-and-checkboxen.html">Under-Engineered Custom Radio Buttons and Checkboxen, by Adrian Roselli</a>.
</p>
</article>
</main>
</div> <!-- /.demo-wrap -->
<script>
var highlighterCSS = function () {
var head = document.head;
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '../assets/vendor/prism.css';
head.appendChild(link);
}
highlighterCSS();
</script>
<script src="../assets/vendor/prism.js"></script>
</body>
</html>