Styling
If you are in client-rendered forms, Vue 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;
}<template>
<div class="contact-form-shell">
<FormieForm
transport="rest"
endpoint="https://formie.test"
form-handle="contactForm"
/>
</div>
</template>When you use useFormieHtml(), wrap the element bound to rootRef the same way.
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:
<script setup lang="ts">
import { FormieForm } from '@verbb/formie-vue';
</script>
<template>
<FormieForm
transport="rest"
endpoint="https://formie.test"
form-handle="contactForm"
theme="formie"
:theme-config="{
field: {
attributes: {
class: ['starter-field', 'starter-field--spaced'],
'data-scenario': 'custom-styling',
},
},
fieldLabel: {
attributes: {
class: ['starter-label'],
},
},
fieldControl: {
attributes: {
class: ['starter-control'],
},
},
}"
/>
</template>Reset Selected Theme Layers
Use this when you want Formie to keep the HTML structure, but you want to rebuild specific visual layers yourself:
<script setup lang="ts">
import { FormieForm } from '@verbb/formie-vue';
</script>
<template>
<FormieForm
transport="rest"
endpoint="https://formie.test"
form-handle="contactForm"
theme="formie"
:theme-config="{
field: {
resetClass: true,
attributes: {
class: ['rounded-2xl', 'border', 'p-4'],
},
},
fieldLabel: {
resetClass: true,
attributes: {
class: ['text-xs', 'font-semibold', 'uppercase'],
},
},
}"
/>
</template>Compose with Tokens
themeConfig and CSS tokens work well together. Use themeConfig for structural hooks, then use CSS for the visual system:
<script setup lang="ts">
import { FormieForm } from '@verbb/formie-vue';
</script>
<template>
<div class="marketing-shell">
<FormieForm
transport="rest"
endpoint="https://formie.test"
form-handle="contactForm"
theme="formie"
:theme-config="{
field: {
attributes: {
class: ['marketing-field'],
},
},
fieldLabel: {
attributes: {
class: ['marketing-label'],
},
},
}"
/>
</div>
</template>.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.