<template src>#dpu-nextTPAC 2026
Dublin, Ireland & online
26–30 October 2026
<iframe seamless> and <link rel="import"> — not
really itwhatwg/html#2791 — 280+ comments, 225+ 👍Including one piece of HTML inside another is one of the oldest requests on the web. SSI and PHP were invented for it in 1995. On the client, <iframe seamless> had heavy Window/Document overhead and style/security issues, and HTML Imports loaded an inert document that still needed JS to stamp DOM. Meanwhile whatwg/html#2791 has been active since 2017.
“PHP was literally created to solve this problem… Imagine if the client could cache the entire header and footer and only need to download the main content.”
— @grepsedawk (
whatwg/html#2791)
“DRY HTML authoring without running code server-side or requiring JS. It's actually what I naively expected HTML imports to do at first.”
— @brandondees (74 👍) · GitHub has used
<include-fragment>in prod for 10+ years (@josh)
Developers in whatwg/html#2791 repeatedly highlight both the beginner/static-site ergonomics and the caching win of client-side includes. GitHub has used its <include-fragment> custom element in production for over a decade as a client-evaluated <esi:include>.
Client-side includes unlock four main benefits: buildless DRY HTML on static hosts without a server or build step; split caching between shared chrome or CDN-cached shells and dynamic user islands; loading async subsections (comments, feeds, recommendations) without delaying the main page; and composing fragments across separate services with native sanitization instead of iframes.
Client-side includes stalled on three core problems: synchronous fetching created parser-blocking network waterfalls, asynchronous fetching caused FOUC and layout shifts, and injecting fetched HTML carried XSS risk without a native sanitizer.
<template for>buffer (see later...)Each of those three blockers now has a platform primitive: out-of-order streaming (<template for>) decouples fetching from parser position, rel="expect" and buffer prevent FOUC and manage layout shifts, and the Sanitizer API makes external markup safe by default.
<template for src>Streams from a URL into a location in the DOM
Building directly on out-of-order streaming (<template for="name">), adding a src attribute fetches an external HTML fragment and streams it into the matching <?start>...<?end> marker range.
DOMContentLoaded but not the parserFirst mitigation: instead of blocking the HTML parser on a synchronous fetch, <template for src> fetches asynchronously (delaying DOMContentLoaded like <script defer>) so fetches can start early while the parser renders placeholders and <footer> immediately.
Second mitigation (part 1): unlike media subresources such as <img src> (where rel="expect" only waits for the tag to be parsed, not fetched), <template for src> expands into DOM structure—so expecting #content also waits for any client-side includes preceding #content in tree order. The HTML parser continues through <main> without blocking, and header + main paint together.
buffer)Second mitigation (part 2): for async fragments that shouldn't block initial page render, adding buffer parses the response into the template and swaps the placeholder atomically when ready.
buffer on the Main StreamBecause buffer is a general <template> primitive rather than a fetch-only flag, you can also use <template for="comments" buffer> on the incoming main HTML stream so streamed patches swap in atomically.
buffer Waits for SubresourcesWhile buffering into the template, the speculative preload scanner initiates subresource fetches. The atomic swap waits for external stylesheets, <link rel="preload">, and any internal <template for src> includes inside the buffered template to finish.
sanitize)src is sanitized by defaultsanitize="unsafe" opts out for trusted fragmentsThird mitigation: external includes (<template for src>) are sanitized by default using the browser's built-in Sanitizer API, which strips scripts, inline event handlers, and nested <template for> (preventing slot-hijacking or recursive includes).
sanitize on the Main StreamJust like buffer, sanitize works without src too. While inline <template for> is unsanitized by default because it's part of the main document stream, adding sanitize lets server-rendered pages declaratively sanitize untrusted regions directly in the HTML parser.
forfor: Patch "in place" of the templatesrc, buffer, and sanitize without PIsWhen you don't need out-of-order targeting, an empty for attribute (<template for src="header.html">, <template for buffer>, <template for sanitize>) acts in place—replacing the <template> element itself without needing <?start>/<?end> markers, and composing cleanly inside <template shadowrootmode="open">.
<template src> always uses CORSfragment-src directive when sanitized; script-src when unsafeAdditional details: <template src> is always CORS; CSP adds fragment-src (falling back to default-src) while script-src still governs sanitize="unsafe"; relative URLs inside fragments resolve against document.baseURI; and external SVGs can be included inline with CSS currentColor styling and built-in sanitization.
<template>?<script>, can be used with inline contentA new <fragment> element is rejected because <template> already has the self-consuming "disappear from the DOM" behavior and is valid everywhere in the HTML parser without foster-parenting.
<template> vs. a new elementfor shorthand (<template for src>)buffer wait for?404 / 500)Try it: Chrome Canary flag · WICG/declarative-partial-updates
Open the floor for feedback on <template src>, buffer, sanitize, and rel="expect" integration.
<?shellboundary>: Progressive shells (📅 Wednesday 9:00 Breakout)preserve: Keep islands (<video>, <iframe>, state) alive across patchesMutationObserver (📅 WHATWG Session)Quickly highlight sibling developments in WICG/declarative-partial-updates: progressive shells (<?shellboundary>), DOM preservation/merging (preserve attribute for islands inside patched ranges), and parser-aware MutationObserver. Invite everyone to the Seamless Navigation breakout on Wednesday at 9:00 and the WHATWG session.
Explainer: https://github.com/WICG/declarative-partial-updates/blob/main/fragment-include-explainer.md. Covers extending <template> with src, buffer, and sanitize to solve WHATWG HTML issue #2791.