Advanced HTML for Good Developers

Advanced HTML for Good Developers

THANKS BURNT TOAST CREATIVE @burnttoastcre8v @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Jello MANDY MICHAEL Sta Software Engineer Google Developer Expert Microsoft Regional Director ff @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Advanced HTML for Good Developers

HTML for Performance & Accessibility

ACCESSIBILITY : Accessibility is the practice of making your websites & applications usable by as many people as possible. https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

WEB PERFORMANCE : Web performance is the objective measurement and perceived user experience of a website or application. https://developer.mozilla.org/en-US/docs/Learn/Performance/What_is_web_performance @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

HTML IS SIMPLE & VERY FRIENDLY. @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

WE MAKE THE MISTAKE OF ASSUMING BECAUSE IT’S SIMPLE IT’S NOT VALUABLE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<html> … <body> <header> <h1>Some text</h1> </header> <p>A paragraph…</p> <ul> <li>A list item</li> <li>Another item</li> </ul> <p>More content…</p> <hr> @mandy_kerr mandykerr @mandymichael@bsky.social …. @mandymichael@front-end.social

THE DOM TREE IS CONSTRUCTED OFF WHAT WE PROVIDE. @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

TYPE SCRIPT @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

interface dog { name: string age: number isFluffy: boolean } @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

WE DETERMINE WHAT WE EXPECT THE DATA TO BE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<html> <body> <header> <h1>Dogs: They are good</h1> </header> <main> <h2>Why are dogs good?</h2> <p>All dogs are good, they are the goodest doggies.</p> <figure> <img href=”dog.png” alt=”A white golden retriever, with his head dropping to the side and tongue dangling out of his mouth” /> <figcaption>Michaelangelo AKA “Jello”</figcaption> </figure> </main> </body> </html>

interface dog { name: any age: any isFluffy: any } @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<html> <body> <div> <div>Dogs: They are good</div> </div> <div> <div>Why are dogs good?</div> <div>All dogs are good, they are the goodest doggies.</div> <div> <img href=”dog.png” alt=”A golden retriever” /> <div>Michaelangelo AKA “Jello”</div> </div> </div> </body> </html>

IF YOU CHOOSE A GENERIC ELEMENT YOU GET A GENERIC OUTPUT @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

JUST <DIV> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

MEANINGFUL HTML @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

NOT EVERYONE INTERACTS THE SAME @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

ACCESSIBILITY TREE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

OVERLOOKING HTML CAN LEAD TO A LARGE COMPLEX DOM TREE. @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

A LARGE DOM WILL IMPACT LOAD TIMES @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

A LARGE DOM TREE CAN SLOW DOWN RENDERING & AFFECT RUNTIME PERFORMANCE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

GOOGLE RECOMMENDS Less than 1,500 nodes. warning at 800 nodes Max depth of 32 nodes No parent node with more than 60 child nodes @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

CREATE NODES ONLY WHEN NEEDED. DESTROY AFTER @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

ANY PERFORMANCE IMPACTS ON THE DOM FURTHER IMPACT THE ACCESSIBILITY TREE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

When the accessibility tree is slowed down by excessive code, it can create a lack of synchronization between the current state of the page and what is being reported by assistive tech ” Eric Bailey @mandy_kerr mandykerr @mandymichael@bsky.social ” @mandymichael@front-end.social

A LARGE COMPLICATED ACCESSIBILITY TREE CAN CRASH THE BROWSER @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

EVERYTHING ADDS UP @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

DON’T JUST USE DIVS @mandy_kerr batmandy @mandymichael@bsky.social @mandymichael@front-end.social

USE THE NAMED ELEMENT FOR WHAT YOU ARE BUILDING @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

If you have a header, use the <header> element <header>This is a header</header> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

HTML is intentionally simple, elements are named to help you out. @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Use heading elements in the correct order <h1> <h2> <h3> <h4> <h5> <h6> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

THE ROTOR CTRL+OPT+U @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

MAKE THE MOST OF BUILT-IN FUNCTIONALITY @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<details> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<datalist> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<input type=“date”> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

JUST BECAUSE IT’S IN A DESIGN DOES NOT MEAN YOU HAVE TO DO IT. @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<dialog> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Popover <button popovertarget=”mypopover”> Toggle </button> <div id=”mypopover” popover> Popover content </div> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

I AM A BUTTON @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<div onclick=”doSomething();”> I am a button </div> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

If you need a button, use the <button> element <button>Amazing button</button> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<div> FEATURES <button> Clickable / Tapable Focusable Keyboard Interaction Announce via assistive tech Submit / Reset Forms Disabled attribute Reported to accessibility tree :active, :hover, :focus & :disabled states @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<div tabindex=”0” role=”button” aria-pressed=“button” onclick=”doSomething();”> I am a button </div> const ENTER = 13; const SPACE = 32; myButton.addEventListener(‘keydown’, function(event) { if (event.keyCode === ENTER || event.keyCode === SPACE) { event.preventDefault(); doSomething(event); } }); function toggleButton(button) { button.setAttribute(“aria-pressed”, button.getAttribute(“aria-pressed”) === “true” ? “false” : “true” )}; } function doSomething() { // Your actual code to do what you want )}; @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

<div tabindex=”0” role=”button” aria-pressed=“button” onclick=”doSomething();”> I am a button </div> const ENTER = 13; const SPACE = 32; myButton.addEventListener(‘keydown’, function(event) { if (event.keyCode === ENTER || event.keyCode === SPACE) { event.preventDefault(); doSomething(event); } }); function toggleButton(button) { button.setAttribute(“aria-pressed”, button.getAttribute(“aria-pressed”) === “true” ? “false” : “true” )}; } function doSomething() { // Your actual code to do what you want )}; @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

A Button CSS Reset By Andy Bell button { display: inline-block; border: none; margin: 0; padding: 0; font-family: sans-serif; font-size: 1rem; line-height: 1; background: transparent; -webkit-appearance: none; } @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

If you need a link, use the <a> element <div> FEATURES <a> Navigate to a page or view Change url Browser redraw/refresh Focusable Keyboard Interaction Open in new window Reported to accessibility tree :active, :hover, :focus, :link & :visited states @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

IT’S LIKE USING A PRE-INSTALLED JS LIBRARY @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

DON’T FORGET ABOUT THE ATTRIBUTES @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

ARIA ATTRIBUTES FILL THE GAPS IN STANDARD HTML TO GIVE MORE CONTEXT TO THE ACCESSIBILITY TREE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

ARIA ATTRIBUTES aria-pressed aria-selected aria-expanded aria-grabbed aria-live aria-hidden aria-labelledby https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

“ If you’re writing CSS that conveys information. Ask yourself is that information also in the accessibility tree? If not, a bit of ARIA might help. JULIE GRUNDY @mandy_kerr mandykerr @mandymichael@bsky.social ” @mandymichael@front-end.social

LOADING & PERFORMANCE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

IMPROVING IMAGE PERFORMANCE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

width & height for improving Cumulative Layout Shift <img src=“jello.jpg” width=”640” height=”360” alt=“Jello rolling over”> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Cumulative Layout Shift : measures how much elements shift on the page as content is being downloaded @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Jello nursery rhyme Jello nursery rhyme Little uffy Jello likes to play outside down came the rain and Jello had to hide out came the sun and dried up all the rain So little uffy Jello could play outside again Little uffy Jello likes to play outside down came the rain and Jello had to hide out came the sun and dried up all the rain So little uffy Jello could play outside again <img src=“jello.jpg” alt=“Jello with rope in mouth”> fl fl fl fl @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Jello nursery rhyme Jello nursery rhyme Little uffy Jello likes to play outside down came the rain and Jello had to hide out came the sun and dried up all the rain So little uffy Jello could play outside again Little uffy Jello likes to play outside down came the rain and Jello had to hide out came the sun and dried up all the rain So little uffy Jello could play outside again <img src=“jello.jpg” width=”640” height=”360” alt=“Jello with rope in mouth”> fl fl fl fl @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Responsive images with srcset <img width=”1000” height=”1000” src=”jello-1000.jpg” srcset=”jello-1000.jpg 1000w, jello-2000.jpg 2000w” alt=”Jello rolling over” /> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Responsive images with sizes <img width=”1000” height=”1000” src=”jello-1000.jpg” srcset=”jello-1000.jpg 1000w, jello-2000.jpg 2000w,” sizes=”(min-width: 1000px) 1000px, 400px” alt=”Jello rolling over” /> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Responsive images with <source> <picture> <source media=”(max-width: 799px)” srcset=”jello-480w-sml.jpg” /> <source media=”(min-width: 800px)” srcset=”jello-800w.jpg” /> <img src=”jello-800w.jpg” alt=“Jello rolling over” /> </picture> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

IMAGE LAZY LOADING @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Native lazy-loading <img src=”img.png” loading=“lazy” width=”300” height=”300”/>

<iframe src=“img.png” loading=“lazy” /> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Only lazy load images that are not in viewport @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

LARGEST CONTENTFUL PAINT (LCP) : the render time of the largest image or text block visible within the viewport when the page rst starts loading. mandykerr @mandymichael@bsky.social fi @mandy_kerr @mandymichael@front-end.social

Only lazy load images that are not in viewport @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Lazy Loading browser support @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Optimising loading & Prioritisation @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Browser Prioritisation HTTP/1 HTTP/2 & HTTP/3 @mandy_kerr mandykerr Multiple TCP Connections each load 1 resource at a time. Single TCP/QUIC Connection sending multiple requests at the same time @mandymichael@bsky.social @mandymichael@front-end.social

Order of prioritisation can have a big impact on your web performance metrics. @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Browser Prioritisation varies between browsers https://calendar.perfplanet.com/2022/http-3-prioritization-demysti ed/ mandykerr @mandymichael@bsky.social fi @mandy_kerr @mandymichael@front-end.social

Priority Hints using the fetchpriority attribute @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Fetch Priority high: You want the browser to prioritize it low: You want the browser to deprioritize it auto: You want the browser to decide (Default) @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

fetchpriority sets the relative priority @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Relative Priority (CSS) <link rel=”stylesheet” href=”styles.css” fetchpriority=”high”> Highest Priority Highest priority

<link rel=”stylesheet” href=”styles.css” fetchpriority=”low”> Highest Priority High Priority web.dev/fetch-priority @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Relative Priority (Image) <img src=”image.jpg” fetchpriority=”high”> Low Priority High Priority <img src=”image.jpg” fetchpriority=”low”> Low Priority Low Priority web.dev/fetch-priority @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Fetch Priority <ul class=“carousel”> <li><img src=”img/1.jpg” <li><img src=”img/2.jpg” <li><img src=”img/3.jpg” <li><img src=”img/4.jpg” </ul> @mandy_kerr mandykerr fetchpriority=”high”></li> fetchpriority=”low”></li> fetchpriority=”low”></li> fetchpriority=”low”></li> @mandymichael@bsky.social @mandymichael@front-end.social

fetchpriority browser support @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Improve speed with Resource Hints @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

RESOURCE HINTS <link rel=”preconnect” href=“https://gooddogs.com/img”> <link rel=”dns-prefetch” href=“https://gooddogs.com/img”> @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

RESOURCE HINTS <link rel=”preconnect” href=”….”> Starts the connection process as soon as possible @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

RESOURCE HINTS <link rel=”preconnect” href=”….”> Starts the connection process as soon as possible Only for critical connections @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

RESOURCE HINTS <link rel=”dns-prefetch” href=”….”> Starts the DNS lookup https://caniuse.com/?search=dns-prefetch @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

EVERYTHING ADDS UP @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

dns-prefetch browser support @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Preloading resources @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

PRELOADING

<link rel=”preload” as=”script” href=”critical.js”> Only preload critical resources @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Preload is intended to let browser know about resources you need “later” @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

@mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

PRELOADING fi @mandy_kerr CSS: Resources that are inside CSS, like fonts or images. js: Preload chunks of critical js bundles, or resources that JS can request like JSON, imported scripts, or web workers Large files: Large les like video mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

“ …see preload as a queue-jump. If you and yer pals get queue jumped into a club (baller), it doesn’t only get you in quicker, it makes everyone behind you get in a little slower. - Harry Roberts, @csswizardry @mandy_kerr mandykerr @mandymichael@bsky.social ” @mandymichael@front-end.social

103 Early Hints (A sneaky bonus) @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

103 Early Hint Link: https://cdn.example.com; rel=preconnect, https://cdn.example.com; rel=preconnect; crossorigin https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103 @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

Early Hints browser support PRELOAD https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103 @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

EVERYTHING ADDS UP @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

DON’T JUST USE DIVS USE THE NAMED ELEMENTS LEVERAGE BUILT-IN FUNCTIONALITY CONVEY INFORMATION & CONTEXT EXPLORE THE ATTRIBUTES @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

MAKE IT USEFUL MAKE IT USABLE @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social

THANK YOU bit.ly/htmlresource @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social