Custom code blocks

Write your own interaction in HTML, CSS and JavaScript. How the sandbox works, how theme auto-styling works, and what a custom block can and cannot do.

The Custom code block lets you author an interaction Compose does not ship. You write HTML, CSS and JavaScript; the exported course runs it in a sandboxed frame.

What you author

Field Contents
HTML The body of your block
CSS Styles for it
JavaScript The block’s script
Height The frame’s height in pixels; leave at 0 for the default
Auto styling Whether Compose injects the course theme into your frame. On by default

The sandbox

In the exported course, a custom block runs inside an isolated <iframe>. It inherits nothing from the surrounding page — not the course stylesheet, not its scripts, not its variables.

That is deliberate. A broken or heavyweight custom block cannot take the course down with it, and a course containing an author’s experiment still renders and still reports completion.

The practical consequences:

  • You cannot read or write the learner’s progress from a custom block.
  • You cannot reach the course’s JavaScript or the SCORM API.
  • A custom block does not gate navigation and does not contribute to the score.
  • Anything you need must be inside the block’s own HTML, CSS and JavaScript.

The block cannot reach the network

Isolation stops a custom block reaching the course. It does nothing about the outside world — so without this, a block copied from the internet could quietly call home from inside a course you believed was self-contained, and your LMS would carry it to every learner.

So the exported frame declares a content policy that permits only what a self-contained block needs: its own inline script and styles, and data: images, fonts and media.

If your block needs an asset, import it into the course and reference it. Compose embeds asset:// references directly into the block when it exports, so they work inside the frame without a network request:

<img src="asset://your-image-key" />

Pick images through the media picker rather than typing a path — see Files and media. Embedded assets are capped at 512 KB each, because they end up base64-encoded inside the exported page; anything larger is left alone and reported as an export warning.

Auto-styling

With Auto styling on — the default — Compose injects the course’s theme values into the frame before your CSS runs:

  • CSS custom properties for the course’s accent, background, surface and text colours, corner radius and typefaces
  • Sensible base styles keyed off them: typography, links in the accent colour, buttons, inputs and code

So a custom block looks like it belongs in the course without you restyling everything. Your CSS is applied after, so anything you set always wins.

Turn auto-styling off and the frame gets a minimal baseline instead — a system font and a small margin — which is what you want if you are bringing a complete design of your own.

/* With auto styling on, these are already defined for you */
.my-button {
  background: var(--accent);
  border-radius: var(--radius);
  font-family: var(--font-body);
}

In the editor

The canvas and the preview panel show a static code panel for a custom block, not the running frame. To see it actually run, use Preview — the preview is the real exported course, so your block executes there exactly as it will for a learner.

Sharing a custom block

Edit ▸ Share block as file… writes any block, including a custom code block, to a small .ceblock file. Blocks saved into your Blocks folder appear in the Blocks tab of the left panel, ready to insert into any course.

Because a custom code block carries its own HTML, CSS and JavaScript, a shared .ceblock is effectively a portable interaction — the closest thing Compose has to a plugin.

See Templates and reusable pieces.

Things worth knowing

Keep it compatible with older browsers

Courses often run inside an LMS’s embedded viewer, which can be an old engine. The course runtime Compose ships is deliberately conservative for that reason; your custom block should be too if your learners are on managed machines.

Nothing external will be there

A SCORM package is often served from an LMS with no outbound internet, or opened from disk. Anything your block fetches from a CDN will simply not load. Inline what you need.

Validation

Compose flags an empty custom code block in the status strip. It cannot check whether your code works — use Preview for that.

Ask AI

Ask anything about Mauvely

Answers come from this documentation.