Skip to content

Embedding with iframe

KabanFriends edited this page Aug 27, 2026 · 2 revisions

The fastest way to put a widget on a page. Each widget ships an iframe shell, a small HTML page whose entire body is the widget, configured through the query string. You write one <iframe> tag and nothing else. No build step, no JavaScript on your page, and no conflict with your own stylesheet.

If you want the widget in your own DOM instead, read JavaScript API.

Embed the vanilla advancement tree

This works as written. The embed host publishes both the shell and the bundle.

<iframe
  src="https://mcwidgets.kaban.sh/advancements/embed.html?bundle=/bundles/vanilla/bundle.json"
  style="width: 100%; height: 420px; border: 0;"
  title="Minecraft advancements"
  loading="lazy"
></iframe>

Write &amp; rather than a bare & between parameters. It is what HTML expects inside an attribute value, and it removes any chance of a parameter name being read as a character reference.

Embed a crafting table

<iframe
  src="https://mcwidgets.kaban.sh/itemgui/embed.html?bundle=/bundles/itemgui-demo/bundle.json&amp;gui=crafting_table&amp;items=crafting1=diamond,crafting2=diamond,crafting3=diamond,crafting5=stick,crafting8=stick,result=diamond_sword"
  style="width: 100%; height: 220px; border: 0;"
  title="Crafting a diamond sword"
  loading="lazy"
></iframe>

items fills slots by name. The slot names and item names both come from the bundle, so a bundle you build yourself decides what you can write here. See Building Item GUI Bundles.

Point at your own bundle

Replace bundle with the URL of the bundle.json you built. It may be absolute or relative to the shell.

<iframe
  src="https://mcwidgets.kaban.sh/advancements/embed.html?bundle=https://example.com/mc/advancements/bundle.json"
  style="width: 100%; height: 420px; border: 0;"
  title="Server advancements"
></iframe>

The shell runs on the embed host, so it fetches your bundle across origins. Your server must send Access-Control-Allow-Origin on bundle.json. Without it the browser blocks the fetch and the widget prints a load error instead of a tree. The icon PNGs beside the bundle are loaded as images and need no such header, so a missing header shows up as a total failure rather than missing icons.

Serving the bundle from the same origin as the page does not help here. What matters is the origin of the shell.

Textures and the font look after themselves

Each widget resolves its own textures and its own font relative to the module it was loaded from, so bundle is the only thing an embed has to name. The shell at /advancements/embed.html loads /advancements/viewer.js, which finds its assets at /advancements/assets/. Copy that directory somewhere else and the same rule still holds.

assetBase overrides where those files come from, and coreAssetBase overrides the font on its own. Neither is needed on the embed host, or in any layout that keeps the module and its assets/ directory together. Reach for assetBase when you have deliberately separated them, most often after bundling the widget module into your own build output.

Size the iframe

The widget fills the box you give it and picks the largest whole-number GUI scale, 1 to 4, that fits. Nothing is ever drawn at a fractional scale, so pixels stay square.

The advancement viewer needs 252 by 140 CSS pixels for scale 1, the size of the in-game screen. A bundle with two or more tabs needs 280 by 168, because the tab strip reserves a 28 pixel band on each edge it uses. Below that the window is clipped rather than shrunk.

On a desktop-width page, a multi-tab tree reaches scale 2 somewhere around 420 pixels of height, which is where the text starts being comfortable to read.

The item GUI needs the size of its own GUI texture. A vanilla crafting table page is 176 by 166, so give it at least that.

Set the height in CSS. An iframe does not grow to fit its contents, and the widget has no fixed height to report.

<iframe src="..." style="width: 100%; height: 420px; border: 0;"></iframe>

To force one scale regardless of the box, add scale=2. Values are 1, 2, 3, 4, or auto.

Background

Both shells have a transparent page background, so whatever is behind the iframe shows through. The advancement viewer paints its own window and background tiles over that, and the item GUI paints only its GUI texture.

To dim the page behind an item GUI the way the game dims the world, add backdrop=dim. Any CSS colour also works, for example backdrop=%23202020. Percent-encode the #.

Touch and scrolling

On a phone, a widget that eats vertical swipes traps the reader. Both widgets avoid that by default.

The item GUI never claims a swipe. The advancement tree pans under the finger and then hands the swipe back to the page once the tree runs out, which keeps a full-width embed escapable.

Inside a long article you may prefer the tree to refuse vertical swipes outright. Add touchPan=page-first. The cost is real: one-finger vertical panning of the tree is then unreachable, because a scroll container cannot be given an axis its own touch rules deny. Horizontal swipes still pan, and two-finger gestures always belong to the browser.

Every parameter

Translation files, text components, and the font options are described in Text and fonts.

Clone this wiki locally