Zach’s ugly mug (his face) Zach Leat­herman

State of the Browser (2026) It’s 10PM: Do You Know Where Your JavaScript Is?

Watch in 53 minutes 10 April 16, 2026

This talk was given at State of the Browser (2026). Check out the event talk page (which includes a talk transcript, too).

We’ll talk about best practices to either reduce (or increase!) the JavaScript footprint on your web site to a sweet and very practical spot for best results. It’s far more common to have too much JavaScript on your web site, but can you go too far? Is zero JavaScript a worthwhile goal? Let’s talk about it!

Video

Watch on YouTube: State of the Browser (2026) It’s 10PM: Do You Know Where Your JavaScript Is?

Slides

A CRT television sits in an alley, its screen reading “10 PM Do you know where your children are?”
The year is 1964. Only 5 years before the Apollo 11 moon landing and the midpoint between the very first release of Internet Explorer (1995) and the current year 2026. https://unsplash.com/photos/a-tv-sitting-on-the-ground-in-front-of-a-brick-building-SnewvLPyeAQ
The same television, screen dark
The location? Los Angeles, CA (USA).
A smiling young man appears on the television screen through the static
The television screen shows a color bars test pattern
Local nightly news anchors for KHJ channel 9 decided to broadcast a PSA or Public Service Announcement (also known as a Public Information Film or PIF) warning to all parents in the area: It’s 10PM. Do you know where your children are?
The television screen now reads “10 PM Do you know where your JavaScript are?”
What kind of parents existed in 1964? What kind of kids? Why did they need this reminder? And today, I bring the developers creating the next generation of JavaScript heavy applications the same call to action: it’s 10PM — do you know where your JavaScript are?
Title: 10 PM Do you know where your JavaScript are?
Today we’re starting a rumor that Americans say that “JavaScript” is plural, just like we do with Math, which JavaScript is also coincidentally kinda bad at.
Title: 10 PM Do you know where your JavaScript are?
The title corrects itself to “Do you know where your JavaScript is?”
The title corrects itself again to “Do you know where your JavaScripts are?”
A phoropter sits in front of an eye chart
And to do that, we’ll take a trip to the local optometrist and create a little component that lets us compare two separate images, a before and an after image. https://optician-sans.com/
The television shows the Web Awesome comparison component—kittens in a basket, half color and half grayscale
Here’s what a component like this might look like. This one is a <wa-comparison> custom element from the Web Awesome component library. Today we’re going to walk through 14 different eras of web development as though they were DEFCON levels on a Cold War threat readiness system, and we’ll create 14 different image comparison components to show how far we’ve come and what might come next.
A Mandalorian stands in a Tatooine street as the Back to the Future DeLorean drives past
Let’s hop into our mandalorian time machine and travel back to the year 1991.
The Back to the Future time circuits read 08:00 PM 1990. Doc Brown, Waldo, and Tim Berners-Lee stand below
The year is 1991, a short 35 years backwards in time, but only 22 years after humanity bravely landed on the moon. One can only assume that dinosaurs had very recently gone extinct. We find a young, spry London-born 36 year old Tim Berners-Lee publishing the very first draft of…
HTML, with a beveled 1990s HTML button below it
HTML. How might one create an image comparison component in HTML? Call it out if you know it:
VS Code shows 1-html-only.html containing ASCII art, with the browser rendering below
That’s right, ASCII art. Unfortunately <pre> was not available to preserve whitespace.
The 1992 W3C “HTML Tags” page beside the original tag list, with nextid, isindex, hp1, hp2, and dir crossed out
Here are the originals. Which one could we use? Call it out if you know it https://www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Tags.html
The ASCII art wrapped in a plaintext element; the browser renders BEFORE || AFTER plus a stray closing tag
If you said plaintext, sure!
The same file with no closing tag; the browser still renders BEFORE || AFTER
but <plaintext> vacuums up the rest of the document (and doesn’t expect a closing tag), as stated to improve parsing performance. A thousand HTML sanitizer scripts just held this breath, because just like an unclosed <style> element, this behavior will still vacuum everything
The same ASCII art wrapped in a listing element instead
Let’s swap to <listing>, which is a better fit. I think we’ve exhausted this one. Let’s move on.
The time circuits read 09:00 PM 1992 with HTML added to the list. The Coneheads and the In Living Color Fly Girls join Doc Brown
The year is 1992. Some dude (we needn’t immortalize who) introduced the
IMG
`<img>` element, the very first mechanism for displaying images inline in HTML. First available in the Mosaic browser, this first offers us the barest bones featureless image comparison component was first possible. Leaving the viewer to crane their neck left and right to compare images, disgustingly manually.
VS Code shows 2-img.html with two img tags; the browser renders two frames of the Trojan Room coffee machine
Trojan Room Coffee pot at the University of Cambridge by Quentin Stafford-Fraser and Paul Jardetzky Originally created in 1991, put on the web after <img> was introduced; XBM format https://en.wikipedia.org/wiki/X_BitMap though GIF was available at the time (maybe JPEG, though that timeline is much closer) This may not be the first image, a title likely given to a July 1992 image of a Cern-based musical group. https://www.cl.cam.ac.uk/coffee/coffee.html https://www.webdesignmuseum.org/web-design-history
The time circuits read 10:00 PM 1995 with IMG added. HAL 9000 and the Macromedia logo flank Doc Brown
Can anyone guess what happened in 1995?
The monolith from 2001: A Space Odyssey, half covered by a yellow JS panel
https://www.youtube.com/watch?v=5NShEY1ScSY
VS Code shows 3.html with Dreamweaver’s MM_swapImage script and an img with an onmouseover handler
For this one, I think it’s prudent that we pay homage to the MM_swapImage script. If you aren’t familiar with this one, it was introduced in Macromedia Dreamweaver to swap image sources when a user interacts with them.
The television shows the Macromedia Dreamweaver splash screen
The same file annotated—the script is request 1 (JS), the image request 2, the inline handler request 3
Let’s start to document our dependencies.
Two browser windows side by side, one showing the monolith in grayscale and the other in color
A single browser window showing the monolith in color
Cons: not seen by the HTML preload scanner but guess what: we didn’t have a preload scanner then The mm_ scripts did include JavaScript preloading. I know this is a trivial example but it’s important to internalize this concept and how it can represents layout shift.
A GitHub code search for MM_swapImage returns 134k files, stamped PRESENT DAY over a dumpster fire
Anyway, let’s not spend too much time on this one it’s very outdated and not used any more.
The time circuits read 11:00 PM 1998 with JS added. Wes Bos, Bert Bos, and Håkon Wium Lie join Doc Brown
The W3C CSS level 2 specification beside the CSS logo, Håkon Wium Lie and Bert Bos, with Wes Bos crossed out
https://www.w3.org/TR/CSS1/ Håkon Wium Lie and Bert Bos who as far as I can tell is unrelated to Wes Bos CSS1 was in 96 but we’re going CSS2 in 98 so that we can use position and overflow
VS Code shows 4.html—a style block (1, CSS), two images (2 and 3), and an onmousemove script (4, JS)
The television shows the comparison demo mid-load, half of it still unstyled white
The time circuits read 12:00 PM 2003 with CSS added. Steven Champeon, a porg, and Nick Finck join Doc Brown
PE
The 2003 SXSW deck “Inclusive Web Design For the Future with Progressive Enhancement” by Steven Champeon and Nick Finck, courtesy of the Internet Archive
A close-up of the deck’s broken “next slide” and “previous slide” image links, with large red arrows
Introduced in a SXSW talk in 2003. Photo via https://www.linkedin.com/in/schampeo/ Slides: https://web.archive.org/web/20141108064903/http://hesketh.com/publications/inclusive_web_design_for_the_future/ Webmonkey article https://hesketh.com/publications/progressive_enhancement_and_the_future_of_web_design.html
A diagram—an HTML box with dotted arrows down to CSS and JS, beside the working comparison demo
Three browser windows showing HTML, then plus CSS, then plus JS
How it loads is just as important as what is loading. This ties into (not just) Progressive Enhancement, but Browser Support, Performance, FOUC, Layout Shift, et al
A single browser window showing the finished comparison
VS Code shows 5.html—an external stylesheet (1, CSS), two images (2 and 3), and an external script (4, JS)
A loading diagram—the images wait behind hourglasses, and red crosses show what breaks when the CSS or JS never arrives
The link element blocks rendering, waiting for the stylesheet. A script like this in 2003 was blocking, though now we can use modules or asynchronous/defer to better control that behavior. External requests creates a network dependency! In the wild wild west of the world wild web, no network request can be guaranteed to complete so we must think about what happens when resources don’t load or aren‘t supported by the viewer’s browser
The same diagram, labeled INTERACTIVE DEAD ZONE after TWILIGHT ZONE and EXTEMPORAL DEAD ZONE are crossed out
And even though progressive jpeg was available, I didn’t use it here for dramatic effect and the image content chunks in, line by line, reminiscent of my childhood.
Chrome DevTools with request blocking turned on
We should also think about what happens if the network requests complete but are delayed! Just off the cuff and absolutely in no way pun intended, maybe we could call it the extermporal dead zone
A service worker, sw.js, that delays responses
Markup with delay parameters added to the stylesheet and script URLs
SUSPEND REALITY and time warp in a service worker
A second service worker file, sw-tax.js
The time circuits read 01:00 PM 2008 with PE added to the list
Have you heard of 56k Fridays? I’m not saying you use this to add a simulated network delay to folks with more CPU cores, but here is a script to do that
CDN
May 2008 https://web.archive.org/web/20081216035512/http://googleajaxsearchapi.blogspot.com/2008/05/speed-up-access-to-your-favorite.html
The jQuery, Prototype, and Dojo logos beside Google Hosted Libraries
6.html loading jQuery from a CDN
Google Hosted Libraries popularized this in the jQuery community https://developers.google.com/speed/libraries
The dead zone diagram, now carrying 87 KB of JavaScript
Though instead of performance savings, there are now performance costs with this approach — though the biggest cost for me is relying on an external third party for your site’s runtime
DOUBLE-KEYED CACHE
An article about the polyfill.io supply chain attack
PRIVACY Separate cache for each origin https://andydavies.me/blog/2018/09/06/safari-caching-and-3rd-party-resources/ https://addyosmani.com/blog/double-keyed-caching/ https://developer.chrome.com/blog/http-cache-partitioning
SUBRESOURCE INTEGRITY
https://fossa.com/blog/polyfill-supply-chain-attack-details-fixes/
The time circuits read 02:00 PM 2008 with CDN added. Matt Mullenweg and Aaron Swartz join Doc Brown
https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Subresource_Integrity the failure mode here is pretty unfriendly.
SSG
November 2008
Jekyll and Tom Preston-Werner
Aaron Swartz’s “Bake, Don’t Fry”
Cheap server rendering without an application server, popularized via the default option for GitHub Pages
7.liquid, an Eleventy template
Real OG’s might recognize
A closer look at the same template
lol image map
The comparison image sliced into pieces
Eleventy writing out 7-1.html through 7-N.html
The television shows the comparison demo, black and white beside color
The dead zone diagram with only the stylesheet blocking
The time circuits read 03:00 PM 2010 with SSG added to the list
The PE profile here seems better but the user experience is definitely worse!
RWD
Håkon Wium Lie’s 1994 “Cascading HTML style sheets” proposal
though IE9 was first in 2011
The W3C Media Queries Working Draft from 2001
Ethan Marcotte’s “Responsive Web Design” on A List Apart
https://www.w3.org/TR/2001/WD-css3-mediaqueries-20010404/Overview.html
A media attribute support table beside Scott Jehl
implemented using @media and css background-image https://alistapart.com/article/responsive-web-design/
The television shows the monolith in black and white
Islands architecture popularized by the Astro about ten years after RWD is also in this same league https://scottjehl.com/posts/responsive-video/ 2023!
The television splits between black and white and color
Were CRT televisions 16:9? I don’t remember.
A GitHub commit diff swapping out an image
You might imagine doing the same with a navigation menu viewable at large viewport sizes but not at small ones.
Low←Tech Magazine and Kris De Decker
The time circuits read 04:00 PM 2008 with RWD added to the list
Not just on the client! Servers can make choices like this too: to conserve resources using static assets instead of dynamic pages, to use low-tech features like image dithering to reduce serving costs. https://solar.lowtechmagazine.com/
SPA
The Office “find the differences” triangle, labeled SPA, client side rendering / CSR, create-react-app
The react.dev Quick Start page, stamped PRESENT DAY over a dumpster fire
This wasn’t a particularly good time for folks that cared how the web was delivered or rendered. But it was a very popular time for web development!
ReactCompare.js rendering two plain img tags
The built index.html with one script and one stylesheet
Import your styles, and they get bundled up globally
Three browser windows—nothing, then JS, then CSS
A single faded browser window
The dead zone diagram carrying 191 KB of JavaScript
A toy Woody figure rides alone on the back of a flatbed trailer
2 network resources on the critical rendering path, including a hefty library This is like strapping your baby into the
The time circuits read 05:00 PM 2004 with SPA added to the list
https://www.reddit.com/r/mildlyinteresting/comments/133ze96/today_in_minnesota_an_empty_flatbed_with_a_single/
JS BUNDLERS, CSS-IN-JS
index.html with the stylesheet link crossed out
The dead zone diagram, 191 KB, with the blocking stylesheet gone
Styled Components 2016–2026 Emotion 2017
The dead zone diagram with a single script ahead of the images
I get it—why not? the JS dependency is already there! It makes sense if you’re already bought in to CSR. 51kb to 61 kb
ReactCompare.js rewritten with styled-components
Turns out JavaScript isn’t good at this, especially against CSS and especially when dealing with frequent rerenders.
“Forget everything you know about web development. Keep an open mind.”
https://styled-components.com/
A minified bundle, faded out
https://speakerdeck.com/vjeux/react-css-in-js?slide=28
The time circuits read 06:00 PM 2016 with BUNDLERS added to the list
SSR painted on a brick wall
“The many definitions of Server-Side Rendering” on zachleat.com
https://unsplash.com/photos/brown-and-black-brick-wall-KREQ7J7nsNw A mea culpa moment for CSR
npm install next@1 and a 107.1 MB dependency sunburst
Notably here when I’m talking about SSR, I’m using the component definition of SSR, not the application version (which means rendering dynamic HTML on-request). The reason it’s murky is because people are making money from the confusion 😘 https://www.zachleat.com/web/ssr-overloaded/
Next.js server-rendered HTML output with one stylesheet and four scripts
https://github.com/vercel/next.js/tree/1.0.1 used Glamor for first-party CSS
More of the same output—scripts 4, 5, and 6
The dead zone diagram—one stylesheet, then 22 KB and 328 KB of JavaScript
npx create-next-app@latest on v16, weighing in at 454.6 MB
next@1 (2016) 328 KB react@19 (2026) 191 KB next@16 (2026) hello world grown by 30% to 455.3 KB
page.tsx using ReactCompareSlider
A wall of preload markup, numbered 1 through 11
The comparison demo arriving from the server, with an eye watching
as we all know, systems typically get less complex over time so this is fine.
The comparison slider centered, with a pointing finger
The dead zone diagram with eleven numbered scripts and their sizes
The time circuits read 07:00 PM 2008 with SSR added to the list
almost 400 KB of JavaScript between your finger and your eye split across 6 external requests (EACH is required for interactivity), remember the goal is to poke the eye as fast as you can
CSS-IN-HTML, with tailwindcss.com
Linaria, vanilla-extract, and Panda CSS, stamped PRESENT DAY over a dumpster fire
Tailwind 1.0 was released in 2019
React 18’s “Library Upgrade Guide, style (most CSS-in-JS libs)” discussion from 2021
I could probably write a whole talk about the introduction of this compared with zero runtime CSS in JS tools. Linaria 1.0 was available in 2019 too. I do have opinions, primarily that CSS seems to be shipping wildly fast in a way that abstractions are having trouble keeping up. But the biggest takeaway here is that all of these tools helped move CSS out of the client JS bundle.
The time circuits read 08:00 PM 2020 with CSS-IN-HTML added to the list
Even React pivoted away from this in 2021. https://github.com/reactwg/react-18/discussions/110
WEB COMPONENTS
January 2020, Custom Elements v1 cross-browser available when Edge swapped to Chromium
The Web Awesome comparison component documentation, kittens split between color and grayscale
index.html using wa-comparison with two slotted images
https://webawesome.com/docs/components/comparison/
The dead zone diagram, down to 69 KB of JavaScript
The SSR and web component demos beside the diagram, now showing both the interactive dead zone and a flash of unstyled content
Smaller JavaScript cost than a jQuery (87 KB)
Two versions of fouc.css, cloaking undefined elements with an animation
demostyle.css hiding the before image until the component defines itself, and the flash of unstyled content crossed off the diagram
Flash of Unstyled Content
The time circuits read 09:00 PM 2020 with WEB COMPONENTS added to the list
IMAGINATION
Vite released April 2020
The same word with IMG marked up as a tag
A row of Wheel of Fortune slot machines labeled PROGRESSIVE ENHANCEMENT
demostyle.css beside index.html, with radio buttons added inside wa-comparison
You don’t have to gamble with these slots
The markup up close—two slotted images and a form with Grayscale and Color radio buttons
The form markup above a browser showing the kittens with working radio buttons
A range input whose oninput sets a CSS custom property, above the working slider demo
The first party, accessible JavaScript-enhanced experience is the ideal case. But here we provide an interactive middle ground when something in your environment has gone wrong.
The dead zone diagram at 69 KB, the interactive dead zone still spanning the images
This one is using a range input. You could use the :target pseudo selector here as well to make the dead zone interactive again. You could also imagine how this same logic could be applied to a tabs component, notable for making sacrifices in unstyled render or missing interactivity. Web components offer this unique styling and markup enhancement out of the box, and I think that’s great.
The same diagram with the dead zone arrow gone
The time circuits read 10:00 PM 2020 with IMAGINE added to the end of the list
The television in the alley reads “10 PM Do you know where your JavaScript are?”
Thank you—where to find me

< Older
AMA about Build Awesome, an Open Town Hall at the 11ty Meetup
Newer >
Collaborative Editing as Progressive Enhancement

Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at Font Awesome and the creator/maintainer of Build Awesome (née IndieWeb Avatar for https://www.11ty.devEleventy/11ty), an award-winning open source website generator. At one point he became entirely too fixated on web fonts. He has given 89 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of CloudCannon, Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

1 Repost

pablolarah
Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)