Popup & drawer
<button id="contact-btn">Get in touch</button>
<script src="https://forms.justinjongstra.nl/formbuilder/asset/embed.js" data-fb-form="YOUR-FORM-ID" data-fb-mode="popup" data-fb-trigger="click" data-fb-trigger-selector="#contact-btn" async></script>The drawer
Section titled “The drawer”Same renderer, same config, one attribute different. It slides in from the side instead of opening in the middle:
<button id="contact-btn">Get in touch</button>
<script src="https://forms.justinjongstra.nl/formbuilder/asset/embed.js" data-fb-form="YOUR-FORM-ID" data-fb-mode="drawer" data-fb-position="right" data-fb-trigger="click" data-fb-trigger-selector="#contact-btn" async></script>Which to use is a layout decision rather than a functional one: a drawer leaves more of the page visible, which suits a form that supports what somebody is already reading. A popup takes the focus, which suits one that is the point of the visit.
Config sits on the script tag rather than a container because these modes have no container: there is nothing on the page to hang it off until the overlay opens.
| Attribute | Values |
|---|---|
data-fb-mode |
popup, drawer, button |
data-fb-trigger |
click, load, delay, scroll, exit |
data-fb-delay |
milliseconds, for delay |
data-fb-scroll |
percent of the page, for scroll |
data-fb-once |
session, forever, never |
data-fb-position |
right, left, for drawer |
data-fb-animation |
slide, scale, rise, fade, none |
data-fb-animation-duration |
any CSS duration, e.g. 400ms |
data-fb-animation-easing |
any CSS easing, e.g. ease-out |
The overlay’s chrome renders in its own shadow root on a body-level
element, so your page’s CSS cannot break the modal, while the form itself
stays in light DOM and inherits your fonts.
Motion
Section titled “Motion”A drawer slides in from its edge and a popup scales up; both take 260ms.
Set data-fb-animation to pick a different one, and the two timing
attributes to change how it feels.
<script src="https://forms.justinjongstra.nl/formbuilder/asset/embed.js" data-fb-form="YOUR-FORM-ID" data-fb-mode="drawer" data-fb-animation="slide" data-fb-animation-duration="420ms" data-fb-animation-easing="cubic-bezier(.16,1,.3,1)" async></script>You can also do it in CSS, which is the better option when the motion
should match the rest of your site rather than be configured per embed.
The overlay’s outer element carries data-formbuilder-overlay, and custom
properties set on it inherit through the shadow boundary:
[data-formbuilder-overlay] { --fb-anim-duration: 420ms; --fb-anim-easing: cubic-bezier(.16, 1, .3, 1); --fb-backdrop: rgba(10, 20, 40, 0.6);}
/* Only the drawer, only on wide screens. */[data-formbuilder-overlay='drawer'] { --fb-anim-distance: 60%;}| Property | Default | What it does |
|---|---|---|
--fb-anim-duration |
260ms |
Enter and exit timing |
--fb-anim-easing |
cubic-bezier(.22,.61,.36,1) |
Enter and exit curve |
--fb-anim-distance |
100% drawer, 20px rise |
How far the panel travels |
--fb-anim-scale |
.94 |
Starting scale, for scale |
--fb-backdrop |
rgba(15,15,20,.45) |
Backdrop colour |
--fb-panel-bg |
#fff |
Panel background |
--fb-radius / --fb-pad |
14px / 28px |
Panel shape |
An attribute wins over your CSS, so leave the attribute off when you want the stylesheet to be in charge.
Why it opens instantly
Section titled “Why it opens instantly”The form’s definition is fetched while the page is idle, not when somebody clicks, so by the time the panel opens the form is already in it. On a cold click over a slow connection you get a loading placeholder instead, and if the form genuinely cannot be reached you get a message and a Try again button. Never an empty panel.