Making web and mobile applications
fast, secure, and easy to operate.
var isDHTML, isID, isAll, isLayers; if (document.getElementById) { isID = 1; isDHTML = 1; } else { if (document.all) { isAll = 1; isDHTML = 1; } else { browserVersion = parseInt(navigator.appVersion); if ((navigator.appName.indexOf('Netscape') != -1) && (browserVersion == 4)) { isLayers = 1; isDHTML = 1; } } } function findDOM(objectID,withStyle) { if (withStyle == 1) { if (isID) { return (document.getElementById(objectID).style) ; } else { if (isAll) { return (document.all[objectID].style); } else { if (isLayers) { return (document.layers[objectID]); } }; } } else { if (isID) { return (document.getElementById(objectID)); } else { if (isAll) { return (document.all[objectID]); } else { if (isLayers) { return (document.layers[objectID]); } }; } } } function setClass(objectID,newClass) { var dom =findDOM(objectID, 0); dom.className = newClass; }
Normalize browser features
Code once, works everywhere
addEventListener
and attachEvent
Faster, optimized, readable code
Function chaining & implicit iteration behavior
Less code. Faster to code.
<script src="jquery.js"></script> <script type="text/javascript"> $('li:first').addClass('first'); </script>
Many developers who have grown up only using frameworks have a total lack of understanding about the fundamental of HTML such as valid and semantic markup.
This is of great concern as semantic markup is one of the core principles of an accessible web.
— Russ Weakley, (@russmaxdesign) Front End Frameworks -- are they accessible
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
I feel like there's some Suze Orman happening in my timeline. People coming to grips w/ cost of their abstractions for the first time.
— Alex Russell (@slightlylate) August 29, 2016
Do your framework and tools cause your app to load in more than 5s on a 3G connection on real hardware? If "yes", YOU CANNOT AFFORD THEM.
The web wins each time a dev chooses to build a web app, no matter the tech, library, or framework they use. But every feature has a cost. Those costs might not be noticeable or important on desktop.
On a low end mobile device on a terrible network, they are huge.
Matthew McNulty (@mattsmcnulty)August 28, 2016
So, in a world where the world's most popular computers have flaky network connections and slow CPUs, anything that sheds JS is _golden_.
— Alex Russell (@slightlylate) August 28, 2016
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" placeholder="XXXXX" aria-label="Zip Code: 5-digit zip code"> </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" placeholder="XXXXX" aria-label="Zip Code: 5-digit zip code"> </span> </li>
// replaces each masked input t with a shell 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'), title = input.getAttribute('title'), id = input.getAttribute('id'), placeholder = document.createTextNode(input.getAttribute('placeholder')); input.setAttribute('maxlength', placeholder.length); if(title){ input.setAttribute('aria-label', document.querySelector("label[for= " + id + "]").innerText + ": " + title); } mask.setAttribute('aria-hidden', 'true'); mask.setAttribute('id', id + 'Mask'); mask.appendChild(emphasis); mask.appendChild(placeholder); wrap.setAttribute('class', 'shell'); wrap.appendChild(mask); input.parentNode.insertBefore( wrap, input ); wrap.appendChild(t); },
.shell { position: relative; line-height: 1; } .shell span { position: absolute; left: 3px; top: 1px; color: $themeColor; 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 { /* make them match */ background-color: transparent; font-size: 16px; font-family: monospace; padding-right: 10px; text-transform: uppercase; } /* hide placeholder */ .shell .masked::-webkit-input-placeholder {color: transparent;} .shell .masked::-moz-placeholder {color: transparent;} .shell .masked:-ms-input-placeholder {color: transparent;} .shell .masked::placeholder { color: transparent;}
<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>
<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