Embed options
Three ways to show Katsu #161.
Each frame loads only the modules it needs. Change ?id=161
in the public snippets to select another numeric tag ID.
Embed on another site
The snippets and Open links use public GitHub Pages URLs, ready to paste into another site once deployed. Local changes may not be published yet. These previews use relative URLs so local development and sizing stay same-origin.
- JSON and module URLs resolve relative to the framed page, not the host.
If self-hosting, keep the directory layout, modules,
load-tag.js,site.css,theme.jsand bundledtag.json. Serve over HTTP or HTTPS, notfile://. - Set the frame size on the host page. Check fixed heights at narrow widths and allow scrolling. Animation frames stay square.
- The gallery uses
ResizeObserverto fit frames to their content. Place the sizing script below after the matching iframes. It requires the same origin and cannot measure cross-origin content. - The gallery, player and static drawing share theme settings through same-origin storage. They follow the system until you choose a theme. The animation stays black.
- The host's
frame-srcpolicy must allow the player URL. The player'sframe-ancestorsandX-Frame-Optionsheaders must allow the host. - A sandbox needs
allow-scripts allow-same-originfor modules and playback. These permissions do not isolate untrusted same-origin code. - There is no cross-origin
postMessagecontrol API. Use the framed controls.
All three embeds accept a numeric ?id, for example
?id=147.
Omit it or use ?id=161 for bundled Katsu data without an external API request.
Other IDs use 000000book JSONP because its API has no CORS header.
JSONP executes scripts from that service; allow only trusted script sources in your CSP.
<script>
document.querySelectorAll('.player-frame, .drawing-frame').forEach(frame => {
let observer;
frame.addEventListener('load', () => {
if (observer) observer.disconnect();
const body = frame.contentDocument?.body;
if (!body) return;
observer = new ResizeObserver(() => {
const style = getComputedStyle(frame);
const border = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
frame.style.height = Math.ceil(body.getBoundingClientRect().height + border) + 'px';
});
observer.observe(body);
});
});
</script>