Block: HTML, CSS, and JavaScript

What the HTML block is for

The HTML block lets you add custom markup, CSS, and interactive JavaScript behavior to a page. It is useful for small widgets, custom cards, calculators, switches, and other elements that are not available in the standard block catalog.

Use the HTML block when the standard blocks are not sufficient. An error in custom code can affect the appearance or behavior of the published page.

Block tabs

HTML and CSS

Place the element markup in the “HTML and CSS” tab. CSS can be included in a <style> tag. Use a unique wrapper class and start every selector with that class so the styles do not affect other parts of the site.

<script> tags inserted into the HTML are not executed. Put JavaScript in the separate “JavaScript” tab.

JavaScript

Code from the “JavaScript” tab runs only on the published site after the current block HTML has been mounted in the DOM. It does not run in the page editor, block catalog preview, or block settings window.

The script receives three variables:

  • root — the root DOM element of the current HTML block. Use root.querySelector(...) to work with elements in this block.
  • block — the current block data, including its id and options.
  • site — the current site data available to the public application.

Standard browser objects such as window and document are also available. The root variable is a convenient scope, not a security sandbox, and does not technically prevent access to the rest of the page.

Working example

Add this in the “HTML and CSS” tab:

<div class="my-click-demo">
  <button type="button" data-demo-button>Show message</button>
  <p data-demo-result hidden>JavaScript works!</p>
</div>

Add this in the “JavaScript” tab:

const button = root.querySelector("[data-demo-button]");
const result = root.querySelector("[data-demo-result]");

if (!button || !result) return;

const handleClick = () => {
    result.hidden = false;
    button.textContent = "Done";
};

button.addEventListener("click", handleClick);

return () => {
    button.removeEventListener("click", handleClick);
};

Save the block and open the published page. The message appears after the button is clicked.

Cleaning up listeners and timers

Mobitsa can reuse a Vue component during navigation or run the code again after the block changes. The script can therefore return a cleanup function. It is called before the next run and when the block is unmounted.

The cleanup function should remove everything created by the script:

  • event listeners with removeEventListener;
  • timers with clearTimeout and clearInterval;
  • MutationObserver, ResizeObserver, and other observers with disconnect();
  • global subscriptions or DOM elements created outside the block.

If the script returns a Promise, Mobitsa waits for its result. The Promise may also resolve to a cleanup function. Execution and cleanup errors are caught and written to the browser console so custom code does not interrupt the Vue page mount.

Security warning

JavaScript in an HTML block is trusted site-owner code, not an isolated widget.

The code can access the public page, DOM, browser storage, and network requests allowed by the browser. Untrusted third-party code may read data entered by visitors, change the page, redirect users, load more code, or degrade site performance.

  • Insert code only from a trusted and reviewed source.
  • Never place passwords, private API keys, or other secrets in client-side code because visitors can inspect it.
  • Review external request and asset URLs.
  • Avoid infinite loops and heavy synchronous work.
  • Do not modify global styles or page elements unless required.

Cookies and external analytics

HTML-block JavaScript runs immediately when the published block is displayed and does not automatically wait for analytics or marketing cookie consent. For analytics counters and global integrations that require consent, use the site-wide HEAD/footer settings and configure the cookie consent mechanism.

How to test the code

  1. Save or add the HTML block.
  2. Open the published page because JavaScript intentionally does not run in the editor.
  3. Test the interaction on desktop and mobile.
  4. Navigate away and return to confirm that handlers are not duplicated.
  5. If the element does not work, open the browser developer console and look for “HTML block JavaScript error”.

Existing HTML blocks without JavaScript continue to work as before. Existing global HEAD and footer fields are not changed by this runtime.