Advanced HTML for Good Developers
A presentation at NDC Sydney 2024 in February 2024 in Sydney NSW, Australia by Mandy Michael
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
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
interface dog { name: any age: any isFluffy: any } @mandy_kerr mandykerr @mandymichael@bsky.social @mandymichael@front-end.social
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
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
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
If you need a button, use the <button> element <button>Amazing button</button> @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.socialOnly 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.socialRelative 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.socialPreload 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