Designing for Everyone: Building Great Web Experiences for Any Device Aaron Gustafson BRK2411
A presentation at Microsoft Build 2018 in May 2018 in Seattle, WA, USA by Aaron Gustafson
Designing for Everyone: Building Great Web Experiences for Any Device Aaron Gustafson BRK2411
In October of 2016, mobile ate the desktop…
https://aka.ms/desktop-v-mobile-2016 Mobile traffic overtakes desktop globally
Mobile accounts for 56% of all traffic* Desktop Mobile *Based on 77 billion website visits. https://aka.ms/desktop-web-2017
But the numbers differ by industry News Desktop Mobile Food Desktop Mobile Finance Desktop Mobile https://aka.ms/desktop-web-2017
Desktop users spend more time on sites (60%)* Desktop Mobile *Based on 39 trillion seconds. https://aka.ms/desktop-web-2017
Anywhere from 10-300% Finance Desktop Mobile Food Desktop Mobile News Desktop Mobile https://aka.ms/desktop-web-2017
Bounce rates on mobile are 40% higher than desktop* 0 11 22 33 44 Desktop Mobile *Based on 584 billion page views. https://aka.ms/desktop-web-2017
Desktop users view more pages (59%) Desktop Mobile *Based on 584 billion page views. https://aka.ms/desktop-web-2017
Anywhere from 1.5x to 3x more pages per visit Finance Desktop Mobile Food Desktop Mobile News Desktop Mobile https://aka.ms/desktop-web-2017
The “desktop” experience matters
Web browsing is the #1 user activity on PCs
The “desktop” experience matters, even for Progressive Web Apps
40% of Order Ahead transactions on the Starbucks PWA come from desktop
Carnival Cruise Line saw a 16% opt-in for Push Notifications on desktop Katarzyna Ostrowska https://aka.ms/carnival-pwa
We believe the web can (and should) reach beyond the browser, which is why we are so heavily invested in making PWAs successful on Windows
PWAs start with a great web experience and then enhance that experience for performance, resilience, installation, and engagement
PWAs start with a great web experience and then enhance that experience for performance, resilience, installation, and engagement
PWAs start with a great web experience and then enhance that experience for performance, resilience, installation, and engagement
Progressive / prəˈɡresiv/ happening or developing gradually or in stages; proceeding step by step
Step 1 Focus on what matters
Consider forbes.com circa 2007
“Mobile first” thinking
Remember that text is the first interface
Is there anything missing that would help users be more successful?
Finding Our Focus Josh Williams Starbucks
Ta s k f i r s t ? Turns out customers like to “do” things with the apps we build
We focused on our key customer journeys · Enable customers to join the Starbucks Rewards program · Enable customers to transact via Order Ahead and Barcode Pay · Enable customers to track progress towards their earned rewards
Store Locator was our first actual production “PWA” feature And it was chromed in the previous site
From there, we were able to add in other key features · Sign-in and Account Create · Barcode pay · eGift and Account management · etc.
Finding Our Focus Josh Williams Starbucks
Step 2 Use markup that supports the core experience
The words we choose matter, but the markup we use matters equally
What does it mean?
<div class="entry"> <div class="entry__title">Progressive Web Apps and the Windows Ecosystem</div> <div class="entry__meta"> <div><b>Published</b> 24 May 2017</div> <div><b>Reading Time</b> 25 minutes</div> </div> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </div>This div marks up a piece of self-contained content
<div class="entry"> <div class="entry__title">Progressive Web Apps and the Windows Ecosystem</div> <div class="entry__meta"> <div><b>Published</b> 24 May 2017</div> <div><b>Reading Time</b> 25 minutes</div> </div> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </div>There’s a tag for that: article
<article class="entry"> <div class="entry__title">Progressive Web Apps and the Windows Ecosystem</div> <div class="entry__meta"> <div><b>Published</b> 24 May 2017</div> <div><b>Reading Time</b> 25 minutes</div> </div> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </article>This div is the title of the blog post
<article class="entry"> <div class="entry__title">Progressive Web Apps and the Windows Ecosystem</div> <div class="entry__meta"> <div><b>Published</b> 24 May 2017</div> <div><b>Reading Time</b> 25 minutes</div> </div> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </article>h6
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <div class="entry__meta"> <div><b>Published</b> 24 May 2017</div> <div><b>Reading Time</b> 25 minutes</div> </div> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </article>These div elements define various properties of the post
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <div class="entry__meta"> <div><b>Published</b> 24 May 2017</div> <div><b>Reading Time</b> 25 minutes</div> </div> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </article>There’s an element for the: dl
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <dl class="entry__meta"> <dt>Published</dt> <dd>24 May 2017</dd> <dt>Reading Time</dt> <dd>25 minutes</dd> </dl> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </article>Bonus: time
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <dl class="entry__meta"> <dt>Published</dt> <dd><time>24 May 2017</time></dd> <dt>Reading Time</dt> <dd>25 minutes</dd> </dl> <div class="entry__content"> I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div> </article>Bonus: time <time datetime="2017-05-24"> 24 May 2017</time> <time datetime="2017-05-24T11:13:24"> 24 May 2017</time> <time datetime="2017-05-24T11:13:24-04:00"> 24 May 2017</time>
This is “flow” content with line breaks
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <dl class="entry__meta"> <dt>Published</dt> <dd><time …>24 May 2017</time></dd> <dt>Reading Time</dt> <dd>25 minutes</dd> </dl> <div class="entry__content">I had the great pleasure of delivering a talk… <br><br> I do a lot of traveling and it’s… </div>
</article>This is “flow” content with generic divisions
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <dl class="entry__meta"> <dt>Published</dt> <dd><time …>24 May 2017</time></dd> <dt>Reading Time</dt> <dd>25 minutes</dd> </dl> <div class="entry__content"> <div>I had the great pleasure of delivering a talk…</div> <div>I do a lot of traveling and it’s…</div> </div> </article>That is meaningful content
<article class="entry"> <h1 class="entry__title">Progressive Web Apps and the Windows Ecosystem</h1> <dl class="entry__meta"> <dt>Published</dt> <dd><time …>24 May 2017</time></dd> <dt>Reading Time</dt> <dd>25 minutes</dd> </dl> <div class="entry__content"> <p>I had the great pleasure of delivering a talk…</p> <p>I do a lot of traveling and it’s…</p> </div> </article>With CSS it all looks the same anyway, so why should I care?
Readability
Readability
Hey Cortana, read me the top three headlines in today’s New York Times
Accessing content via semantics: function extractHeadlines( response ){ var $html = document.createElement('div'), $headings, i=0, headlines=[]; $html.innerHTML = response.contents; $headings = $html.querySelector('#top-news') .querySelectorAll('article h1, article h2, article h3'); heading_count = $headings.length; while (headlines.length < 3) { let $link = $headings[i].querySelector('a'); if ($link && $link.href) { headlines.push({ title: $headings[i].innerText.trim(), link: $link.href }); } i++; } console.log( headlines ); }
Accessing content via semantics: function extractHeadlines( response ){ var $html = document.createElement('div'), $headings, i=0, headlines=[]; $html.innerHTML = response.contents;
$headings = $html.querySelector('#top-news') .querySelectorAll('article h1, article h2, article h3'); heading_count = $headings.length; while (headlines.length < 3) { let $link = $headings[i].querySelector('a'); if ($link && $link.href) { headlines.push({ title: $headings[i].innerText.trim(), link: $link.href }); } i++; } console.log( headlines ); }
https://aka.ms/dependency-awareness
Let’s say you needed to code a button… <input type="submit" value="Sign Up"> <button type="submit">Sign Up</button> <a class="button" href="#">Sign Up</a>
<div class="button">Sign Up</div> Sign UpLet’s compare Pattern Display Semantics Focusable? Activate By Submits Forms input[type=submit] button button Ye s Mouse, touch, ENTER, SPACE Ye s button[type=submit] button button Ye s Mouse, touch, ENTER, SPACE Ye s a link Named generic Ye s Mouse, touch, ENTER No div block Not exposed No N/A No
UX gaps that need to be filled Pattern Display Semantics Focusable? Activate By Submits Forms input[type=submit] button button Ye s Mouse, touch, ENTER, SPACE Ye s button[type=submit] button button Ye s Mouse, touch, ENTER, SPACE Ye s a link Named generic Ye s Mouse, touch, ENTER No div block Not exposed No N/A No
Filling those gaps introduces dependencies Pattern Display Semantics Focusable? Activate By Submits Forms input[type=submit] None None None None None button[type=submit] None None None None None a CSS ARIA None JavaScript JavaScript div CSS ARIA HTML JavaScript JavaScript
More dependencies, more (potential) problems Dependencies Potential for failure
Disaster averted
More dependencies, more (potential) problems Dependencies Potential for failure
Enhance the experience Capabilities User Experience
Enhancing UX with markup <input type="email" name="email" id="email" required aria-required="true"> Experience deltas 1. Support for email input type? 2. Va l i d a t i o n a l g o r i t h m i m p l e m e n t e d ? 3. Virtual keyboard?
Enhancing UX with markup <input type="email" name="email" id="email"
required aria-required="true"> Experience deltas 1. Support for HTML validation?
Enhancing UX with markup <input type="email" name="email" id="email" required aria-required="true"
Experience deltas 1. Browser exposure of aria-required property? 2. Assistive tech implementation of aria-required?
Enhance the experience Capabilities User Experience required validation email validation dedicated keyboard text input required notification
When you think of user experience as a continuum that scales with capabilities, a progressive approach to interfaces is both elegant and powerful.
Step 3 Design in support of the core experience
Enhance the experience Capabilities User Experience floats grid blocks positioning flexbox media queries
https://aka.ms/enhanced-css-layouts
I’ve been amazed at how often those outside the discipline of design assume that what designers do is decoration—likely because so much bad design simply is decoration. Good design isn’t. Good design is problem solving. — Jeff Veen
To o l s f o r g r a p h i c d e s i g n · Alignment · Balance · Contrast · Emphasis · Gestalt · Harmony · Movement · Proportion · Proximity · Repetition · Rhythm · Unity · White Space
To o l s f o r g r a p h i c d e s i g n · Alignment · Balance · Contrast · Emphasis · Gestalt · Harmony · Movement · Proportion · Proximity · Repetition · Rhythm · Unity · White Space
Alignment
Contrast
Proportion
Proximity
Rhythm https://aka.ms/vertical-rhythm
Unity
Design considerations unique to the web · Screen size · Resolution · Brightness · Color density · User preference · Network speed & quality · Assistive technology
Design considerations unique to the web · Screen size · Resolution · Brightness · Color density · User preference · Network speed & quality · Assistive technology
Design considerations unique to the web · Screen size · Resolution · Brightness · Color density · User preference · Network speed & quality · Assistive technology Responsive layouts SVG, responsive images Contrast Color choice, media queries Responsive images, system fonts
Design considerations unique to the web · Screen size · Resolution · Brightness · Color density · User preference · Network speed & quality · Assistive technology
Examples of user preference · Larger or smaller fonts @media (min-width: 32em) { … } · High contrast colors @media (-ms-high-contrast: active) { … } @media (-ms-high-contrast: white-on-black) { … } @media (-ms-high-contrast: black-on-white) { … } · Reduced motion @media screen and (prefers-reduced-motion: reduce) { … }
Assistive technologies · Vision · Screen magnifiers
· Screen readers
· Braille printers & refreshable braille displays
· High contrast settings
· Motor/mobility · Speech recognition
· Mouse settings
· Keyboards & keyboard overlays
· Eye tracking
· Hearing · Captions & subtitles
Confirm Cancel Confirm Cancel Don’t rely on color alone to convey important information
https://aka.ms/color-contrast Good contrast ensures your content is readable
<a href="#figure-3-3">Figure 3.3</a> shows the lodging article in Safari with only the default browser styles applied. …
<figure id="figure-3-3"> … </figure> Explicit connections ensure everyone can follow references<a href="#figure-3-3">Figure 3.3</a> shows the lodging article in Safari with only the default browser styles applied. …
<figure id="figure-3-3"> … </figure> Explicit connections ensure everyone can follow referencesProvide ample space around interactive elements
<a href="…">Finish Reading</a> Consider what your design leaves unsaid
<b class="hidden">You can</b> finish reading
<b class="hidden">“The Web Should Just Work for Everyone” in less than 10 minutes</b> </a> Consider what your design leaves unsaid
Enhance the experience Capabilities User Experience
Enhancing design in CSS p { color: green; color: rgba(0, 255, 0, .8); } Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS p { color: green;
color: rgba(0, 255, 0, .8); } Older browsers without RGBa support, ignore the second rule Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS p {
color: green; color: rgba(0, 255, 0, .8); } Modern browsers with RGBa support, overwrite the first rule Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS h1:has(+ p) { color: green; } (That selects h1s that have adjacent sibling paragraphs.) Passwords can be a hassle
Enhancing design in CSS h1:has(+ p) { color: green; } Browsers that don’t support :has() ignore the entire rule set Passwords can be a hassle
Enhancing design in CSS h1:has(+ p) { color: green; } As browsers support :has(), matching h1s will turn green Passwords can be a hassle
Enhancing design in CSS @media only screen { p { color: green; } } Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS @media only screen { p { color: green; } } Browsers without media query support ignore the block Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS @media only screen { p { color: green; } } Browsers with media query support apply it Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS @supports (display: grid) { p { color: green; } } Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS @supports (display: grid) { p { color: green; } } Browsers that don’t grok @supports ignore the block Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS @supports (display: grid) { p { color: green; } } Browsers that understand @supports, but don’t display grid ignore it Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
Enhancing design in CSS @supports (display: grid) { p { color: green; } } Browsers that understand @supports and grid apply it Passwords can be a hassle. Most people don’t create strong passwords or make sure to maintain a different one for every site. People create easy- to-remember passwords and typically use the same passwords across all of their accounts.
When it comes to HTML & CSS, browsers ignore what they don’t understand
When it comes to HTML & CSS, browsers ignore what they don’t understand And new specs smartly override conflicting syntax
https://aka.ms/enhanced-css-layouts
Enhance the experience Capabilities User Experience
“Mobile first” design
.primary { float: left; width: 68%; } .secondary { float: right; width: 32%; } @media (max-width:599px) { .primary, .secondary { float: none; width: auto; } } “Desktop first”
.primary { float: left;
width: 68%;
}
.secondary { float: right;
width: 32%;
}
@media (max-width:599px) { .primary, .secondary {
float: none;
width: auto;
}
} “Desktop first”
.primary { float: left; width: 68%; } .secondary { float: right; width: 32%; } @media (max-width:599px) { .primary, .secondary { float: none; width: auto; } } “Desktop first”
@media (min-width:600px) { .primary { float: left; width: 68%; } .secondary { float: right; width: 32%; } } “Mobile first”
@media ( min-width:600px ) { .primary { float: left; width: 68%; } .secondary { float: right; width: 32%; } } “Mobile first”
Other ways to design “mobile first” · Selectively deliver advances styles · Isolate large CSS images in min-width media queries · Don’t hide content images using CSS · Use responsive images · Prefer system fonts · font-display: optional
Enhance the experience Capabilities User Experience
Step 4 Improve the core experience with JavaScript
When it comes to HTML & CSS, browsers ignore what they don’t understand
When it comes to HTML & CSS, browsers ignore what they don’t understand Sadly, that’s not the case with JavaScript
What happens when a browser doesn’t understand let ? document.body.innerHTML += '<p>Can I count to four?</p>’; for ( let i=1; i<=4; i++ ) { document.body.innerHTML += '<p>' + i + '</p>'; } document.body.innerHTML += '<p>Success!</p>';
https://aka.ms/js-let-down
https://aka.ms/js-let-down
More dependencies, more (potential) problems Dependencies Potential for failure
We can and should use JavaScript, but thoughtfully & intentionally
Enhance the experience Capabilities User Experience Server-side render JavaScript Application
Detecting support if ( navigator.credentials ) { // Actual logic goes here }
Creating the credential // Create a credential with WebAuthn APIs navigator.credentials.create({ publicKey: { rp: { /* relying party info / }, user: { / user info / }, authenticatorSelection: { authenticatorAttachment: "platform" }, pubKeyCredParams: [{ type: "public-key", alg: -257 / Accept RS256 credentials */ }], // and other required parameters such as challenge, timeout, ... } }).then(attestation => { // Send the credential to your server, which decodes it and stores the public key sendToServer(attestation); });
Verif ying the credential later // Next time the user visits the page, call the WebAuthn APIs navigator.credentials.get({ publicKey: { allowCredentials: [{ type: "public-key", id: credentialId // ID of credential(s) previously created }] // and other required parameters such as challenge, timeout, ... } }).then(assertion => { // Send the assertion to your server, which decodes it and ensures the // contained signature matches the public key received at credential creation sendToServer(assertion); });
Enhance the experience Capabilities User Experience Normal password WebAuthN
Wait, but don’t Progressive Webs and Service Workers require JavaScript?!
Registering a Service Worker if ( navigator.serviceWorker ) { navigator.serviceWorker.register('/serviceworker.js') .then(function(registration) { console.log('Success!', registration.scope); }) .catch(function(error) { console.error('Failure!', error); }); }
Object detection FTW! if ( navigator.serviceWorker ) { navigator.serviceWorker.register('/serviceworker.js') .then(function(registration) { console.log('Success!', registration.scope); }) .catch(function(error) { console.error('Failure!', error); }); }
Enhance the experience Capabilities User Experience Site PWA
Installed PWA Enhance the experience Capabilities User Experience Site PWA in browser
Enhance the Service Worker Capabilities User Experience Site Offline One-off Sync Less Network Reliance Periodic Sync Push Notifications
Did you know PWAs can enhance via native APIs?
if (window.Windows) { var uiSettings = new Windows.UI .ViewManagement .UISettings(); var color = uiSettings .getColorValue( Windows.UI .ViewManagement .UIColorType .background ); if (color.r == 0 && color.g == 0 && color.b == 0) { // changes for Dark Mode } } Detecting “dark mode”
if (window.Windows) {
var uiSettings = new Windows.UI .ViewManagement .UISettings(); var color = uiSettings .getColorValue( Windows.UI .ViewManagement .UIColorType .background ); if (color.r == 0 && color.g == 0 && color.b == 0) { // changes for Dark Mode } } Detecting “dark mode”
if (window.Windows) { var uiSettings = new Windows.UI .ViewManagement .UISettings();
var color = uiSettings .getColorValue( Windows.UI .ViewManagement .UIColorType .background ); if (color.r == 0 && color.g == 0 && color.b == 0) { // changes for Dark Mode } } Detecting “dark mode”
if (window.Windows) { var uiSettings = new Windows.UI .ViewManagement .UISettings(); var color = uiSettings .getColorValue( Windows.UI .ViewManagement .UIColorType .background );
if (color.r == 0 && color.g == 0 && color.b == 0) { // changes for Dark Mode } } Detecting “dark mode”
if (window.Windows) { var uiSettings = new Windows.UI .ViewManagement .UISettings(); var color = uiSettings .getColorValue( Windows.UI .ViewManagement .UIColorType .background ); if (color.r == 0 && color.g == 0 && color.b == 0) { // changes for Dark Mode } } Detecting “dark mode”
https://aka.ms/dark-mode-pwa-demo
We can and should use JavaScript, but thoughtfully & intentionally
Enhance the experience Capabilities User Experience
PWAs start with a great web experience and then enhance that experience for performance, resilience, installation, and engagement
PWAs start with a great web experience and then enhance that experience for performance, resilience, installation, and engagement
Focus Markup Design JavaScript
Thank you. @AaronGustafson @MSEdgeDev PWABuilder.com
© Copyright Microsoft Corporation. All rights reserved.