Features | Solutions |
Issues | Prescriptions |
The 1st rule of ARIA use is if you can use a native HTML element or attribute with the semantics behavior already built in, do that instead!
— Estelle Weyl (@estellevw) February 25, 2016
I remember when 3G was primary mobile speed. It was slow but still worked, so why now when my phone says 3G it becomes completely useless.
— Stephen Gundee (@StephenGundee) March 23, 2016
Note: Include an alt attribute on all foreground images, with empty alt attribute for decorative images.
Image Optimization TipsLast-Modified
or ETag header to enable cache validation. ETags provide revalidation tokens automatically sent by client to check if there are file changes since last requested. async
attribute in your <script>
tags so client can continue downloading assets instead of waiting as scripts are downloaded, parsed and excecuted.Content-Type: text/html; charset=UTF-8
reduces browser processing. Can start parsing HTML immediately when it knows which character set it has.width=device-width, initial-scale=1
.
<meta name=viewport content="width=device-width, initial-scale=1">
vh
, vw
and percents for width.
Perceivable: Content & UI components
Operable: UI and Nav
Understandable: Information & operation of UI
Robust: Content interprable by UAs, including AT.
think
<ul> <li> <label for="expiration">Credit Card Expiration Month</label> <input id="expiration" type="tel" placeholder="MM/YY" class="masked" pattern="(1[0-2]|0[1-9])\/\d\d" data-valid-example="11/18" title="2-digit month and 2-digit year greater than 01/15"> </li> <li> <label for="zip">Zip Code</label> <input id="zip" type="tel" name="zipcode" class="masked" placeholder="XXXXX" pattern="\d{5}" title="5-digit zip code"> </li> <li> <label for="zipca">Canadian Zip Code</label> <input id="zipca" type="text" name="zipcodeca" class="masked" placeholder="XXX XXX" pattern="\w\d\w \d\w\d" data-charset="_X_ X_X" title="6-character alphanumeric zip code in the format of A1A 1A1"> </li> <li> <label for="tel">Telephone</label> <input id="tel" type="tel" name="phone" class="masked" placeholder="(XXX) XXX-XXXX" pattern="\(\d{3}\) \d{3}\-\d{4}" title="10-digit number"> </li> <li> <label for="cc">Credit Card Number</label> <input id="cc" type="tel" name="ccnumber" class="masked" placeholder="XXXX XXXX XXXX XXXX" pattern="\d{4} \d{4} \d{4} \d{4}" title="16-digit number"> </li> </ul>Input Masking README.md
<li> <label for="zip">Zip Code</label> <span class="shell"> <span aria-hidden="true" id="zipMask"><i></i>XXXXX</span> <input id="zip" type="tel" name="zipcode" pattern="\d{5}" class="masked" title="5-digit zip code" maxlength="5" data-placeholder="XXXXX"> </span> </li>
on data entry...123XX 123XX
<li> <label for="zip">Zip Code</label> <span class="shell"> <span aria-hidden="true" id="zipMask"><i>123</i>XX</span> <input id="zip" type="tel" name="zipcode" pattern="\d{5}" class="masked" title="5-digit zip code" maxlength="5" data-placeholder="XXXXX"> </span> </li>
// replaces each masked input with a shall containing the input and it's mask. createShell : function (input) { var wrap = document.createElement('span'), mask = document.createElement('span'), emphasis = document.createElement('i'), inputClass = input.getAttribute('class'), placeholderText = input.getAttribute('placeholder'), placeholder = document.createTextNode(placeholderText); input.setAttribute('maxlength', placeholder.length); input.setAttribute('data-placeholder', placeholderText); input.removeAttribute('placeholder');
if ( !inputClass || ( inputClass && inputClass.indexOf('masked') === -1 ) ) { input.setAttribute( 'class', inputClass + ' masked'); } mask.setAttribute('aria-hidden', 'true'); mask.setAttribute('id', input.getAttribute('id') + 'Mask'); mask.appendChild(emphasis); mask.appendChild(placeholder); wrap.setAttribute('class', 'shell'); wrap.appendChild(mask); input.parentNode.insertBefore( wrap, input ); wrap.appendChild(input); },
.shell { position: relative; line-height: 1; } .shell span { position: absolute; left: 3px; top: 1px; color: #ccc; pointer-events: none; z-index: -1; } .shell span i { /* any of these 3 will work */ color: transparent; opacity: 0; visibility: hidden; } .shell span, input.masked { background-color: transparent; font-size: 16px; font-family: monospace; padding-right: 10px; text-transform: uppercase; }
<label for="telephone">Telephone Number</label> <input type="tel" id="telephone" placeholder="(XXX) XXX-XXXX" aria-describedby="hint"> <span class="hint" id="hint">10-digit phone number</span>10-digit phone number
<section id="footer-listbox" role="listbox" aria-label="Select your country" class="footer-languageSelector"> <section role="option" tabindex="-1" aria-selected="true" id="footerLanguageOption-0" data-value="AR" class="footer-languageSelector-item"> <label>Argentina</label> <i class="footer-languageSelector-item-icon footer-img-AR"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-1" data-value="AU" class="footer-languageSelector-item"> <label>Australia</label> <i class="footer-languageSelector-item-icon footer-img-AU"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-2" data-value="BR" class="footer-languageSelector-item"> <label>Brazil</label> <i class="footer-languageSelector-item-icon footer-img-BR"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-3" data-value="CA" class="footer-languageSelector-item"> <label>Canada</label> <i class="footer-languageSelector-item-icon footer-img-CA"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-4" data-value="CL" class="footer-languageSelector-item"> <label>Chile</label> <i class="footer-languageSelector-item-icon footer-img-CL"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-5" data-value="CN" class="footer-languageSelector-item"> <label>China</label> <i class="footer-languageSelector-item-icon footer-img-CN"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-6" data-value="CO" class="footer-languageSelector-item"> <label>Colombia</label> <i class="footer-languageSelector-item-icon footer-img-CO"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-7" data-value="HK" class="footer-languageSelector-item"> <label>Hong Kong</label> <i class="footer-languageSelector-item-icon footer-img-HK"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-8" data-value="MY" class="footer-languageSelector-item"> <label>Malaysia</label> <i class="footer-languageSelector-item-icon footer-img-MY"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-9" data-value="MX" class="footer-languageSelector-item"> <label>Mexico</label> <i class="footer-languageSelector-item-icon footer-img-MX"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-10" data-value="NZ" class="footer-languageSelector-item"> <label>New Zealand</label> <i class="footer-languageSelector-item-icon footer-img-NZ"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-11" data-value="PE" class="footer-languageSelector-item"> <label>Peru</label> <i class="footer-languageSelector-item-icon footer-img-PE"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-12" data-value="SG" class="footer-languageSelector-item"> <label>Singapore</label> <i class="footer-languageSelector-item-icon footer-img-SG"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-13" data-value="ZA" class="footer-languageSelector-item"> <label>South Africa</label> <i class="footer-languageSelector-item-icon footer-img-ZA"></i> </section> <section role="option" tabindex="-1" aria-selected="false" id="footerLanguageOption-14" data-value="AE" class="footer-languageSelector-item"> <label>United Arab Emirates</label> <i class="footer-languageSelector-item-icon footer-img-AE"></i> </section> </section>
It's Monday 3rd of April 2016 and...
— Steve Faulkner (@stevefaulkner) April 4, 2016
First rule of ARIA, is still:https://t.co/bsiN798ARq pic.twitter.com/gXwDXAKGjU
<fieldset class="languageSelector"> <legend>Select your country:</legend> <ul> <li> <input type="radio" name="langSelect" id="langAR" value="AR"> <label for="langAR" class="langAR">Argentina</label> </li> <li> <input type="radio" name="langSelect" id="langAU" value="AU"> <label for="langAU" class="langAU">Australia</label> </li> <li> <input type="radio" name="langSelect" id="langBR" value="BR"> <label for="langBR" class="langBR">Brazil</label> </li> <li> <input type="radio" name="langSelect" id="langCA" value="CA"> <label for="langCA" class="langCA">Canada</label> </li> <li> <input type="radio" name="langSelect" id="langCL" value="CL"> <label for="langCL" class="langCL">Chile</label> </li> <li> <input type="radio" name="langSelect" id="langCN" value="CN"> <label for="langCN" class="langCN">China</label> </li> <li> <input type="radio" name="langSelect" id="langCO" value="CO"> <label for="langCO" class="langCO">Colombia</label> </li> <li> <input type="radio" name="langSelect" id="langHK" value="HK"> <label for="langHK" class="langHK">Hong Kong</label> </li> <li> <input type="radio" name="langSelect" id="langMY" value="MY"> <label for="langMY" class="langMY">Malaysia</label> </li> <li> <input type="radio" name="langSelect" id="langMX" value="MX"> <label for="langMX" class="langMX">Mexico</label> </li> <li> <input type="radio" name="langSelect" id="langNZ" value="NZ"> <label for="langNZ" class="langNZ">New Zealand</label> </li> <li> <input type="radio" name="langSelect" id="langPE" value="PE"> <label for="langPE" class="langPE">Peru</label> </li> <li> <input type="radio" name="langSelect" id="langSG" value="SG"> <label for="langSG" class="langSG">Singapore</label> </li> <li> <input type="radio" name="langSelect" id="langZA" value="ZA"> <label for="langZA" class="langZA">South Africa</label> </li> <li> <input type="radio" name="langSelect" id="langAE" value="AE"> <label for="langAE" class="langAE">United Arab Emirates</label> </li> <li> <input type="radio" name="langSelect" id="langUS" value="US"> <label for="langUS" class="langUS">United States</label> </li> </ul> </fieldset>
footer { fieldset { width: 215px; height: 160px; padding-right: 7px; li { font-size: $small; width: 100%; padding-left: 5px; border-top: 1px solid $label; line-height: 34px; } label { color: $white; background-position: 95% 50%; display: block; padding-left: 3px; } } }
footer { &.open { height: 168px; } &.closed fieldset { transform: scale(1,0); } fieldset { input[type=radio], legend { opacity: 0.01; position: absolute; right: 0px; } label:active, label:focus, label:hover, :checked + label { outline: 1px dotted $white; background-color: $mediumLightGray; } } }
think
estelle@instartlogic.com
@estellevw / @webdevtips
all talks at instartlogic.github.io
Accessibility
Performance
Github Repos