Forms
Styling forms with CSS
The script embed renders your form as plain DOM on your own page, so your stylesheet can restyle every part of it. This page is the styling contract: the class names you can target, the design-token custom properties, and copy-paste recipes for the common jobs.
Which modes support custom CSS
| Mode | Custom CSS | Notes |
|---|---|---|
| Script embed | Full | Inline DOM on your page; every .mnx-* selector below is yours to style |
| Hosted page | Theme tokens only | Rendered on forms.mailnix.ch; use the designer's Theme tab |
| Iframe embed | Theme tokens only | Wraps the hosted page; the iframe boundary blocks outside CSS |
| Headless API | Not applicable | You build the whole UI; there is no mailnix DOM |
The stability contract
Class names and custom properties are frozen within embed major v1: a selector documented here keeps working for as long as you load /embed/v1.js. New classes may be ADDED (new field types, new widgets); documented ones are never renamed or removed within the major. Breaking changes would ship as /embed/v2.js, which no page loads until you change the snippet yourself.
Two internals are exempt and must not be styled or unhidden: the honeypot wrapper (.mnx-hp-wrap) is an anti-spam trap that must stay off-screen, and the injected style element id mnx-form-style-v1 is not a styling surface.
Design tokens (CSS custom properties)
All tokens live on the .mnx-form root element and cascade from there. Override them in your stylesheet for broad restyling before reaching for per-class rules:
| Token | Default | Drives |
|---|---|---|
--mnx-primary | #0ea5e9 | Button background, focus outline, radio/checkbox accent, links in info text, active step |
--mnx-bg | transparent | Root background behind the card |
--mnx-surface | #ffffff | Card and input backgrounds |
--mnx-text | #111827 | Body text |
--mnx-muted | #6b7280 | Help text, captions, inactive steps |
--mnx-border | #d1d5db | Card, input, and divider borders |
--mnx-error | #dc2626 | Error text, banner accent, required marker |
--mnx-radius | 8px | Corner rounding on card, inputs, buttons |
--mnx-font | system stack | Font family for everything |
One precedence caveat: tokens you set in the designer's Theme tab are applied as inline styles on the root and beat your stylesheet. If you want your CSS to own a token (for example to follow your site's dark mode), leave that token unset in the designer theme.
Selector reference
The DOM shape is .mnx-form > .mnx-card > form, with a .mnx-banner for form-level errors, an optional .mnx-stepper, one .mnx-page per step, and a .mnx-nav button row at the end.
| Selector | What it wraps | Safe to change |
|---|---|---|
.mnx-form | Root container; carries the tokens and .mnx-dark in dark mode | Tokens, font, max-width, background |
.mnx-card | The bordered card around the whole form | Border, background, padding, shadow, radius |
.mnx-page | One step's fields (flex row, wraps) | Gap, direction |
.mnx-field | One field: label + control + help + error | Margin, flex-basis |
.mnx-label | Field label | Typography, color |
.mnx-req | The required marker inside the label | Color, content spacing |
.mnx-help | Help text under the label | Typography, color |
.mnx-input, .mnx-select, .mnx-textarea | The controls | Border, background, padding, typography, :focus outline |
.mnx-choice | One radio/checkbox row (label wrapping the input) | Spacing, typography |
.mnx-rating | Rating field wrapper (contains .mnx-choice items) | Layout, gap |
.mnx-computed | Read-only computed value | Typography |
.mnx-heading | heading structure field | Typography, margins |
.mnx-info | info_text block (sanitized markdown) | Typography, link color |
.mnx-image | image structure field | Size, radius, borders |
.mnx-caption | Image caption | Typography |
.mnx-divider | divider structure field (an <hr>) | Border, margins |
.mnx-error-msg | Per-field validation message | Typography, color |
.mnx-banner | Form-level error banner above the fields | Colors, border, padding |
.mnx-btn | Submit and Next buttons | Everything a button allows |
.mnx-btn-ghost | Back button (also carries .mnx-btn) | Same |
.mnx-nav | The Back/Next/Submit row | Layout, alignment |
.mnx-stepper | Multi-step progress header | Layout, gap |
.mnx-step | One step entry (with .mnx-step-active / .mnx-step-done states) | Typography, colors |
.mnx-step-dot | The numbered circle | Size, colors |
.mnx-step-line | Connector between steps | Color, thickness |
.mnx-grid-row | A 12-column layout row (grid) | Gap; spans come from .mnx-span-1 through .mnx-span-12 |
.mnx-w-half, .mnx-w-third, .mnx-w-two-thirds | Width-token fields outside grid rows | Flex-basis |
.mnx-repeat-item | One entry of a repeating group | Border, background, spacing |
.mnx-repeat-remove | The remove button on a repeat entry | Typography, color |
.mnx-thanks | The post-submit thank-you screen | Typography, spacing |
.mnx-captcha | CAPTCHA widget wrapper (when enabled) | Margins only |
Specificity: make your rules win
The embed injects its stylesheet into <head> at render time, which is usually after your own stylesheets, so a bare .mnx-btn rule in your CSS can lose the tie. Scope your overrides under a parent for higher specificity and you never need !important:
#contact .mnx-btn { background: #16a34a; }
/* or */
.mnx-form .mnx-btn { background: #16a34a; }Recipes
Brand the button:
.mnx-form { --mnx-primary: #16a34a; --mnx-radius: 999px; }
.mnx-form .mnx-btn { font-weight: 700; letter-spacing: 0.01em; }Restyle inputs and focus:
.mnx-form .mnx-input,
.mnx-form .mnx-select,
.mnx-form .mnx-textarea {
border: 0;
border-bottom: 2px solid var(--mnx-border);
border-radius: 0;
background: transparent;
padding-left: 0;
}
.mnx-form .mnx-input:focus,
.mnx-form .mnx-select:focus,
.mnx-form .mnx-textarea:focus {
outline: none;
border-bottom-color: var(--mnx-primary);
}Match your site's dark mode (works when the designer theme leaves these tokens unset; see the precedence caveat above):
@media (prefers-color-scheme: dark) {
.mnx-form {
--mnx-surface: #1f2937;
--mnx-text: #f9fafb;
--mnx-muted: #9ca3af;
--mnx-border: #4b5563;
}
}Full-bleed layout (drop the card so the fields sit directly on your page):
.mnx-form .mnx-card {
border: 0;
background: transparent;
padding: 0;
}Custom error styling:
.mnx-form { --mnx-error: #b91c1c; }
.mnx-form .mnx-error-msg { font-weight: 600; }
.mnx-form .mnx-banner {
border-left-width: 6px;
background: #fef2f2;
}Where to go further
Layout (columns, spans, steps) belongs in the designer, not in CSS: the grid rows and width tokens ship with the form definition so every consumption mode renders them. Colors, radius, and fonts that should apply on the HOSTED page too belong in the Theme tab, since your stylesheet never reaches forms.mailnix.ch. Your own CSS is the right tool exactly when the form must sit seamlessly inside your site's design system.