Custom Code Block


Custom Code live demo

A scoped micro-interaction

HTML provides the structure, CSS owns the presentation, and vanilla JavaScript enhances the button.

Ready

Use Custom Code for the smallest trusted fragment that standard Luna blocks cannot represent: a bespoke calculator, configurator, visualization, or micro-interaction. The live block above uses semantic HTML, scoped CSS, and progressive vanilla JavaScript.


Properties

Custom Code Properties panel with HTML, CSS, JavaScript, and advanced controls in a clear retina documentation capture

Properties contains three code editors. Keep the fragment self-contained, trusted, and as small as possible; surrounding headings, copy, media, navigation, forms, and calls to action should remain standard Luna blocks.


HTML

HTML defines the semantic structure rendered in the editor preview and published View. Script tags, inline event handlers, and javascript: URLs are rejected or stripped, so use ordinary elements, meaningful landmarks, labels, and accessible names.


CSS

CSS is scoped to this block: selectors and keyframe names are rewritten so the fragment does not leak into the page. External @import rules are not supported. Prefer fluid sizing, wrapping, clamp(), and Luna theme variables over fixed desktop-only values.


JavaScript

JavaScript must be vanilla code. It runs with root bound to this block, so query only inside root. When you attach listeners, observers, or timers, return a cleanup function that removes them.


Layout

Custom Code is grid-only and frame-driven, with a documented starting frame of 12 columns by 8 rows. Choose the frame from the intended composition, then make the inner CSS responsive. The demo uses the complete article width at every breakpoint and keeps an intentional eight-row frame.


Behavior

JavaScript is progressive enhancement after load. Essential meaning and primary actions must remain understandable without it. Avoid cookies, storage, global DOM mutation, external requests, dependency loaders, secrets, heavy loops, or unbounded timers unless the integration has been explicitly reviewed.


Style Panel

Custom Code Style Panel with responsive frame styling controls in a clear retina documentation capture

The Style Panel controls only the outer Frame. Inner elements remain styled by the block’s scoped CSS, so keep frame treatment and fragment styling conceptually separate.


Frame

Frame supports spacing, background, borders, and effects in its Default state. Its hover tab is disabled. Use the Frame for the block boundary; use scoped CSS for the markup rendered inside it.


Motion

Custom Code supports the standard block entrance effects. Keep entrance motion short and nonessential. Inner animation belongs in scoped CSS or JavaScript, must honor prefers-reduced-motion, and must never be required to understand or operate the fragment.


Property summary

HTML — trusted semantic markup rendered in the editor preview and published page.

CSS — block-scoped styles; external imports are not supported.

JavaScript — vanilla progressive enhancement with root scoped to this block and an optional cleanup function.

Animation Effects — the standard entrance motion applied to the outer block.


Responsive behavior

The outer grid frame is intentional at desktop, tablet, and mobile. Inside the frame, use fluid lengths, wrapping, minmax(), clamp(), and media or container queries so content does not depend on scale-down.

Verify the real View at 1440px, 991px, and 375px. Confirm that the fragment stays inside its frame, text remains readable, controls retain at least a 44px target, and neither the block nor the page creates horizontal overflow.


Accessibility

• Start with semantic HTML and give every control an accessible name.

• Preserve keyboard operation, a visible focus state, and a logical reading order.

• Announce meaningful asynchronous results with an appropriate live region, without creating repetitive interruptions.

• Respect prefers-reduced-motion and never rely on color, position, or animation alone.


Common mistakes

• Rebuilding text, buttons, cards, forms, media, or layout that standard Luna blocks already provide.

• Querying document instead of root, leaking global styles, or mutating page-wide DOM.

• Placing secrets, private keys, personal data, or untrusted third-party code in the browser.

• Adding listeners, observers, or timers without cleanup.

• Designing for one fixed width and relying on automatic scale-down instead of responsive inner CSS.

• Choosing an oversized frame with empty space or a frame too small for the intended interaction.

Questions, ideas, or bugs?

Explore what we’re building next, ask the Luna team for help, or send a focused bug report.