Skip to the content

Form 03

A contact form that opens in a dialog over the page.

Become a member to unlock the full effect today.

Join now

Already a member? Sign in

Documentation

  1. Copy to Webflow

    Add Geist and Geist Mono to your site's fonts (Site settings, Fonts, Google Fonts) before pasting: Webflow removes any font your site has not installed.

  2. Add custom CSS

    The look of the preview is the form-03-* and form-set-* classes of the paste: the page behind, the sheet, the fields at rest and the buttons. The width of the sheet is the max-width of form-03-panel, which it loses on the Mobile portrait breakpoint to take the whole width. The Embed holds what moves: the slide of the sheet, under [data-form-set-dialog="sheet"] (take the value sheet off the layer and the panel rises in the middle instead), and the veil over the page, the background-color and the backdrop-filter of [data-form-set-dialog][data-form-set-state="open"]. The states read their colours from five variables, --form-set-ink, --form-set-ground, --form-set-rule, --form-set-accent and --form-set-error, which the first Embed turns over for the sheet, cream on ink, in the rule on [data-form-set-dialog="sheet"]: for a sheet of another colour change them there, with the colours of the classes. The three buttons are Link blocks, because Webflow has no button that holds layers; the script makes them open, close and send. Do not hide the layer with display: none or an interaction: it would never show.
  3. Add custom JS

  4. Use it on your own elements

    Custom attributes
    Select the element on the canvas and open the Settings panel. Under Custom attributes, add a pair: the name on the left, the value on the right.
    Custom attributeWhat it does
    data-form-set Marks the form. It takes no value: leave the value field empty. In the paste it is on the Form inside the Form block, in the panel of the dialog. The settings below go on the same element.
    data-form-set-dialog="sheet" On the layer that covers the page and holds the sheet, the sheet holding the form. Its value sheet makes the panel slide in from the right; with no value the panel rises in the middle of the window instead. The stylesheet lays the layer over the window and hides it until it is opened; on the Webflow canvas, which runs no Embed, it sits in the flow of the section, where it is edited. [ Required ]
    data-form-set-open On what opens the dialog: any button or link, anywhere on the page, as many as you like. It takes no value, or the id of the dialog when the page has several: data-form-set-open="quote". [ Required ]
    data-form-set-close="cross" On what closes the dialog, inside it. It takes no value, or cross to draw a cross in place of its word, which stays its name for a screen reader. Escape and a click outside the panel close it too, and so does the form, the time of the setting closeAfter after it was sent. [ Optional ]
    data-form-set-field On the box of one field: one label and one control (a text, email or phone input, a select, a textarea), with its hint when it has one. It takes no value. The engine writes the state on it and adds what it draws inside it. A control outside such a box is sent with the form but has no state and is not checked. [ Required ]
    data-form-set-submit On the send button: a submit button in plain HTML, a Link block in Webflow, which has no button that can hold layers. It takes no value. Without it the form is still checked when it is sent, by Enter for one, but nothing shows it leaving. [ Required ]
    data-form-set-hint On the line of help under a control. It takes no value. The reason takes its place while the field is wrong, then the hint comes back. A field without one gets a line from the engine, dressed like the first hint of the form. [ Optional ]
    data-form-set-required="Your name, please." On one field: its own words for a reason, in place of the form's. The same goes for email, tel, short, pattern and check. [ Optional ]
    data-form-set-select="native" On one field: leaves its select to the list of the system, in place of the list the engine draws. On the form it is the setting select, for every select at once. A touch screen gets the system's picker either way, and the native select is what the form sends in both cases. [ Optional ]
    data-form-set-state Written by the engine. On a field: up, focus, filled, valid, error, disabled, several at once. On the send button: loading, done or failed. On the form: done. On a dialog: open. A field whose list is open also carries data-form-set-list="open". Never written by hand; the stylesheet reads them, and so can a rule of yours. [ Optional ]
    Settings
    Every setting is a custom attribute too, added the same way and on the same element. An attribute always wins over the defaults written in the code.
    AttributeDefaultWhat it is
    data-form-set-send auto How the form leaves once every field is right. Options: auto lets a Webflow Form block send it to Webflow, and anywhere else posts the form to its action the usual way, the page changing; fetch posts the values to the action without leaving the page and reads the status of the answer.
    data-form-set-sending Sending The word on the button while the form is on its way. Options: any text, in the language of the page.
    data-form-set-sent Sent The word on the button once the form has left, beside the tick. Options: any text.
    data-form-set-failed Try again The word on the button when the send failed; the button can be pressed again. Options: any text.
    data-form-set-required This field is required. The reason under a required field left empty. Options: any text; data-form-set-required on one field gives it its own, "Your name, please.".
    data-form-set-email Enter a valid email address. The reason under a field of type email that does not hold an address. Options: any text.
    data-form-set-tel Enter a valid phone number. The reason under a field of type tel that does not hold a phone number, six digits at least. Options: any text.
    data-form-set-short A little more, please. The reason under a text shorter than the minlength of its control. Options: any text.
    data-form-set-pattern Check the format. The reason under a text the pattern of its control refuses. Options: any text; say the format expected, "Two letters, then four digits.".
    data-form-set-check Please tick this box. The reason under a required checkbox left empty. Options: any text.
    data-form-set-select drawn The list a select opens. Options: drawn, a list the engine draws under the control in the colours of the form, the native select staying underneath; native, the list of the system, which a touch screen gets either way. data-form-set-select="native" on one field leaves that select alone.
    data-form-set-close-after 2400 How long a dialog stays on the answer once its form is sent, in milliseconds. Only read by a form in a dialog.
    The way the form is sent
    Nothing to connect: the paste is a native Webflow Form block, and Webflow receives what it sends. The entries are listed in Site settings, Forms, each field under the name of its label, and the address told of a new entry is set in the same place, under Form notifications. Entries only arrive from a published site, its webflow.io address included: the Designer and its preview send nothing. Once Webflow has the entry it hides the form and shows its Success message; when it could not, it shows its Error message and the button says Try again. Both are Webflow's own blocks, under the Form in the Navigator: select the Form block, open its settings and choose the state to see, restyle and rewrite each one. To add a field, duplicate a field block and give the new field its own name in its settings; to remove one, delete its block; Required is a switch in the same settings. Leave the Action of the form empty, or Webflow receives nothing. Only when the form is not a Webflow Form block do the attributes below apply. In the dialog, Webflow's Success message takes the place of the form, the dialog closes a moment later, and opened again it shows that message until the page is loaded again.
    Custom attributeWhat it does
    action="https://..." On the form: the address the values are posted to, an endpoint of your own or one of a form service such as Formspree or Basin. Not a custom attribute in Webflow, where it is the Action field of the Form settings, to leave empty for Webflow to receive the entries.
    data-form-set-send="fetch" On the form: posts the values to the action without leaving the page, as FormData, with the header Accept: application/json. An answer in the 200s shows Sent, anything else Try again. It is the setting send, so it may also be set for the whole site.
    method="post" On the form: how the values are sent, POST when nothing is written. With GET and fetch they travel in the address.

What it does

Form 03 is an animated form for Webflow and vanilla JavaScript, with no library. Also called slide in contact form, modal contact form or side panel form.

A contact form that opens in a dialog over the page. Any button or link marked for it opens the dialog: the page behind darkens and blurs while a sheet of ink, the whole height of the window, slides in from the right, slow at first, then settling; its label, its heading and the fields of the form come in one after the other once it is nearly there. On a phone the sheet takes the whole width. Escape, a click outside the sheet or the cross close it, Tab stays inside it, the page behind does not scroll, and the focus goes back to the button that opened it. Inside, the fields are the underline fields of the Form set, cream on ink, one a row: the label rests in the line of its field and floats up on focus, a line is drawn under the field, a tick draws itself when the field is right, a wrong field turns red and says why under it. The fields are checked as the visitor leaves them, with what the controls already say: required, an email, a minimum length. The send button shakes its head once when a field is still wrong, runs a bar while the form leaves, then says Sent with a tick, and the dialog closes by itself a moment later. It is a real form: pasted in Webflow it is a native Form block whose entries land in the site's Forms tab, and the dialog sits on the canvas where it can be edited; elsewhere the form posts to its action, with fetch or the usual way, or hands the values to the page. Several dialogs can share a page. Reduced motion respected. No library. Form 03 of the Form set. Pattern type modal form, popup contact form, dialog.

Updated

Questions

Paste the section: it holds a layer marked data-form-set-dialog="sheet" with a sheet and a native Webflow Form block inside, and a Link block marked data-form-set-open. On the published site the layer is hidden until that link is clicked, then the sheet slides in from the right over the darkened page. Nothing to wire, and no Webflow interaction to build.

Yes. Add the custom attribute data-form-set-open, with an empty value, to any button or link, in the navigation or the footer for one, as many as you like. With several dialogs on a page, give each layer an ID and write it as the value, data-form-set-open="quote".

It is not hidden on the canvas. What lays the dialog over the window, hides it and slides it in lives in the Embed, which the Designer does not run, so the layer, the sheet, the heading and the Form block sit in the flow of the section, where each one is selected, restyled and rewritten like any block.

The cross, the Escape key, a click outside the sheet, and the form itself 2.4 seconds after it was sent, a time set by data-form-set-close-after (or off). While it is open Tab stays inside the sheet, the page behind does not scroll, and the focus returns to the button that opened it. The layer carries role="dialog" and aria-modal, and the cross keeps the word Close as its name.

Yes. The form inside the dialog is a real Form block with no action, so Webflow receives it and lists the entries in Site settings, Forms. Outside Webflow the form posts to its action, with data-form-set-send="fetch" to stay on the page, or hands the values to a listener on formset:submit.