Styling
If you are in client-rendered forms, React owns the visible UI and you should style your own components directly.
Import the Browser CSS
Server-rendered forms use the browser package theme:
import '@verbb/formie-browser/css/formie.css';Or split the layers if your app needs that separation:
import '@verbb/formie-browser/css/formie-base.css';
import '@verbb/formie-browser/css/formie-theme.css';Use Tokens First
Start with the --formie-* CSS variables provided by the browser package to change colours, spacing and other styles.
Use Browser → CSS variables for the full token reference.
Scope those tokens on a wrapper around the form:
.contact-form-shell {
--formie-color-primary: #0f766e;
--formie-color-primary-hover: #115e59;
--formie-button-border-radius: 999px;
}<div className="contact-form-shell">
<FormieForm
transport="rest"
endpoint="https://formie.test"
formHandle="contactForm"
/>
</div>Use themeConfig Second
If tokens are not enough, themeConfig lets you inject classes, attributes, and reset behaviour into the shipped server-rendered theme.
Browser-supplied theme config can set classes, supported attributes and CSS custom properties. To change tags, add HTML or attach event handlers, use server-side configuration or template overrides.
Add Classes and Attributes
Use this when you want to keep Formie's HTML structure but attach app-owned classes or data attributes at known theme hooks:
<FormieForm
transport="rest"
endpoint="https://formie.test"
formHandle="contactForm"
theme="formie"
themeConfig={{
field: {
attributes: {
class: ['starter-field', 'starter-field--spaced'],
'data-scenario': 'custom-styling',
},
},
fieldLabel: {
attributes: {
class: ['starter-label'],
},
},
fieldControl: {
attributes: {
class: ['starter-control'],
},
},
}}
/>Reset Selected Theme Layers
Use this when you want Formie to keep the HTML structure, but you want to rebuild specific visual layers yourself:
<FormieForm
transport="rest"
endpoint="https://formie.test"
formHandle="contactForm"
theme="formie"
themeConfig={{
field: {
resetClass: true,
attributes: {
class: ['rounded-2xl', 'border', 'p-4'],
},
},
fieldLabel: {
resetClass: true,
attributes: {
class: ['text-xs', 'font-semibold', 'uppercase'],
},
},
}}
/>Compose with Tokens
themeConfig and CSS tokens work well together. Use themeConfig for structural hooks, then use CSS for the visual system:
<div className="marketing-shell">
<FormieForm
transport="rest"
endpoint="https://formie.test"
formHandle="contactForm"
theme="formie"
themeConfig={{
field: {
attributes: {
class: ['marketing-field'],
},
},
fieldLabel: {
attributes: {
class: ['marketing-label'],
},
},
}}
/>
</div>.marketing-shell {
--formie-color-primary: #0f766e;
--formie-button-border-radius: 999px;
}
.marketing-field {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8);
}Use CSS Third
If tokens are not enough, add targeted CSS against the shipped server-rendered markup.
The safe rule is:
- tokens first
themeConfigsecond- targeted CSS third
- structural replacement only when you are leaving server-rendered forms behind
If you find yourself fighting the shipped HTML structure with heavier CSS, that is usually a sign the problem belongs in client-rendered forms instead.