is-land
A new performance-focused way to add interactive client-side components to your web site.
Or, more technically: a framework independent partial hydration islands architecture implementation.
- See the source code on GitHub
- Check out the screencast on Eleventy’s YouTube channel
- Learn more about Islands Architecture
Features:
- Easy to add to existing components
- Zero dependencies
- Small footprint
- Not tightly coupled to a server framework or site generator tool.
- Server-rendering (SSR) component examples available for SSR-friendly frameworks (Svelte, Vue, Preact, and SolidJS are provided)
Integrations in the wild: Eleventy, WebC, Slinkity, SvelteKit, Bridgetown, Lit
Examples:
- Web Components (on this page)
- Web Components using Declarative Shadow DOM (New in v3.0.0)
Svelte (and SSR)
Vue (and petite-vue) (and SSR)
Preact (and SSR)
Lit (and SSR)
Alpine.js
- Solid
- Embedded in
Markdown
defer-hydrationComponent Attribute Support (New in v3.0.0) Read more about `defer-hydration` at zachleat.com- Experimental: Image Loading
- Test: Stress test of 10000 islands
- Test: Deeper nesting of islands
- Test: Rename
<is-land>to a different tag name or change theon:attribute prefix
Standalone
This is a control to make sure the component initializes as expected without an island.
Defaults
These islands are eagerly loaded and initialized.
Gnarly nesting
Testing A
Testing B
Scroll down
on:visible
Works with <details>
The child content in this <details> will not be initialized until you open it
on:visible nested group
Parent island has on:visible but none of the child components have an explicit loading condition. They will inherit the loading conditions of all of the ancestors.
on:idle
on:interaction
Requires one of: touchstart, click.
Note here that we used one parent island to group both of these components, and interacting with either initializes the whole group.
Use on:interaction="mouseenter,focusin" to override the events.
In this example we use a third party web component (<details-utils>) without any code changes made to the component. Note that children here are maintained before and after initialization (e.g. click the summary to expand before init and it keeps that state after init).
Toggle Menu (Default open: click outside to close after island initializes)
Note that interacting with content inside of the menu works without closing the menu.
Toggle Menu (Default closed: will toggle before island initializes)
Note that interacting with content inside of the menu works without closing the menu.
on:media
Viewport size
on:media="(min-width: 64em)"
This only runs when the viewport is greater than or equal to 1024px wide: on:media="(min-width: 64em)"
This only runs when the viewport is less than 1024px wide: on:media="(max-width: 63.9375em)"
Reduced Motion
This runs when the user prefers reduced motion: on:media="(prefers-reduced-motion)"
This runs when does not have a reduced motion preference: on:media="(prefers-reduced-motion: no-preference)"
on:save-data
This runs when the user has Save Data enabled:
on:save-data="false" This runs when the user does not have Save Data enabled:
Controlling fallback content
If you put child content in a <template> it will be JavaScript-only (no fallback). Use this to your advantage! You can mix and match <template> with other progressively enhanced content in the island.
Use the ready attribute on <is-land> (added when the island is hydrated) for additional styling!
Use data-island="replace" to replace the island content with the template. If more than one of these exists in an island, only the first is used.
This content is pre-JS. This is where your loading spinner goes 😈
Do you know the aspect ratio of the hydrated content? On my personal web site I use this to hydrate a <lite-youtube> component. Works great with CSS aspect-ratio!
Custom Lazy Asset Loading
Nest any inline <script>, <script src>, <style>, <link rel="stylesheet"> inside a <template data-island> to execute when conditions are met. The text will turn red when the inline CSS loads and bold when the external stylesheet loads.