Custom element
<formbuilder-form form="YOUR-FORM-ID"></formbuilder-form><script type="module" src="https://forms.justinjongstra.nl/formbuilder/asset/element.js"></script>The tag is a custom element, so the browser owns its lifecycle. That is why
there is no @formbuilder/react, /vue or /svelte package: four wrapper
packages would mean four build artifacts and four version matrices to keep
in step, and the browser already does the job.
Attributes
Section titled “Attributes”| Attribute | Default | What it does |
|---|---|---|
form |
required | The form id |
lang |
the form’s own | Render a specific translation |
api |
the script’s origin | Point at a different host |
isolate |
auto |
shadow to seal the form off from page CSS |
Object values go on the property rather than an attribute, because an attribute can only carry a string:
document.querySelector('formbuilder-form').prefill = { email: 'ada@example.com' };Why the script is a module
Section titled “Why the script is a module”element.js is type="module" so the browser can fetch the renderer’s
chunks in parallel and cache them independently. That also means it is
fetched with CORS. The host serves it with Access-Control-Allow-Origin,
which is worth knowing if you ever self-host the bundle behind a proxy that
strips headers.
When your page’s CSS fights the form
Section titled “When your page’s CSS fights the form”The form renders in your page’s DOM, which is what lets it inherit your fonts and colours. The price is that a broad enough selector on your side can reach inside it.
This documentation hit exactly that. Starlight styles prose with a rule that adds a top margin to any element following a sibling:
.sl-markdown-content :not(a, strong, em, …) + :not(a, strong, em, …) { margin-top: var(--sl-content-gap-y);}Aimed at paragraphs, but the form’s labels and inputs are descendants of that container too, so one field in a row picked up a content gap its neighbour did not, and sat a line lower. It looked like a bug in the form and was not.
Two ways out, depending on whose CSS it is.
If you control the page, exempt the form from the offending rule.
Starlight has not-content for precisely this, and most systems have an
equivalent:
<div class="not-content"> <formbuilder-form form="YOUR-FORM-ID"></formbuilder-form></div>If you do not (a CMS theme, a page builder, anything you cannot edit), seal the form off instead:
<formbuilder-form form="YOUR-FORM-ID" isolate="shadow"></formbuilder-form>isolate="shadow" renders the form in a shadow root. No selector on the
page can reach it, and nothing it does leaks out.