Zach’s ugly mug (his face) Zach Leatherman

<is-land> Web Component

aerial photography of islands during daytime
December 07, 2023

This web component originally shipped May 2022 but was conspicuously missing from my web site.

<is-land> enables Islands Architecture* on any web site. It’s an HTML web component. It has zero dependencies. It doesn’t require any server-side or build integration.

*with credit to Katie Sylor-Miller.

I use this web component everywhere—it’s a good one. Astro’s has popularized Islands Architecture (great!) and this component serves as a build-independent decoupled alternative.

If you aren’t yet familiar, Islands Architecture (apologies for this oversimplification) is turbo-charged lazy loading. It’s a way to initialize components and resources for sections (islands) of your web site when certain conditions are met: the island becomes visible, the page is idle, the viewport is a certain size, on events (click, mouseover, etc), and respecting user preferences (save data, reduce motion, etc).

You can use this with JavaScript component frameworks but it’s primarily intended for use with Web Components.


Say you have a my-component.js web component definition file with the following content:

// my-component.js
customElements.define("my-component", class extends HTMLElement {
	// …

You can reference it on your web site like this:

<!-- Make sure is-land.js is first -->
<script type="module" src="is-land.js"></script>
<script type="module" src="my-component.js"></script>

<is-land on:visible on:idle>
	<my-component>Fallback content.</my-component>

Now any web components inside the <is-land> (that were not yet :defined when is-land.js loaded) will delay their initialization until the loading conditions are met.

Even lazier loading

If you want to lazily load the component definition when the island initializes, you can do that too.

<script type="module" src="is-land.js"></script>

<is-land on:visible on:idle>
	<my-component>Fallback content.</my-component>
	<template data-island>
		<script type="module" src="my-component.js"></script>
  • You could add a <link rel="stylesheet" href="my-component.css"> in there too, if your component has separate styles too (any valid markup works).
  • Use data-island="replace" to replace the Island’s content with the new template content.

Loading conditions

When using multiple loading conditions, all of the loading conditions for an island must be true before the island initializes.

  • on:visible
  • on:idle
  • on:interaction
    • defaults to touchstart,click, but you can change this to any event with on:interaction="mouseenter,focusin"
  • on:media
    • on:media="(min-width: 64em)" for Viewport size.
    • on:media="(prefers-reduced-motion: no-preference)" to only initialize when the user has no motion preference.
  • on:save-data="false" to only initialize when the user has not requested to Save Data.

Read the documentation on or check out a few introductory videos below:

IndieWeb Avatar for image by Martine Jacobsen

< Newer
One YouTube Embed weighs almost 1.2 MB
Older >
pagefind-search Web Component

Zach Leatherman IndieWeb Avatar for a builder for the web and the creator/maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 81 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 »


IndieWeb Avatar for https://apkhore.comIndieWeb Avatar for https://moneymanages.comIndieWeb Avatar for https://blog.goodlaptops.comIndieWeb Avatar for https://abuspeaks.comIndieWeb Avatar for https://jobnestle.comIndieWeb Avatar for https://evolucioncreativa.websiteIndieWeb Avatar for https://swissvolcano.comIndieWeb Avatar for https://techtoguide.comIndieWeb Avatar for https://mycheapwebhosting.comIndieWeb Avatar for https://www.pixellyft.comIndieWeb Avatar for https://siliconhype.comIndieWeb Avatar for https://atocs.netSashaJeff SikesChris LienertJanek VackarJohn AllsoppMatt WilcoxEdouard DuplessisLene SaileThe Aimless NomadZach LeathermanÅke JärvkloRyan MulliganBertrand DelacretazNicöd·eEleventy ???? v2.0.1westbrook~/j4v1Jay Contonio


SashaJari PennanenmotionsuggestsMatt WilcoxMarc LittlemoreMontyEdouard DuplessisCory Dransfeldt :prami:The Aimless NomadHurdalVic Nashkaiserkiwi :kiwibird:MiguelNick FOUOKevin ColeJared WhitemarcusewestbrookEleventy ???? v2.0.1feedle
  1. siggiarni


    @zachleat Ís-land? ????????

  2. Zach Leatherman

    Zach Leatherman

    @siggiarni ????????????????

  3. Tegan


    @zachleat Side note: Whenever I see the preview share card thing for your articles I am tricked! Tricked I say! into thinking it’s going to be a youtube video because I see your little head poking out of the corner and that’s just how youtube videos thumbnails all are

  4. Zach Leatherman

    Zach Leatherman

    @rawrmonstar I have a few youtube videos on this at the bottom of the post ????

  5. @zachleat question, that I don't think quit think warrants a github issue/qusetion: why use the `on:x` attribute pattern over something like `data-on-condition`? Just curious.

  6. Zach Leatherman

    Zach Leatherman

    @rem I don’t believe `data-` is required for custom elements so just a style preference

  7. Marc Khoury

    Marc Khoury

    @zachleat Can I untap it during my untap phase?

Shamelessly plug your related post

These are webmentions via the IndieWeb and

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)