Styling¶
The same form renders for three styles. Pick one with framework=:
from pydantic_schemaforms import Field, FormModel, render_form_html
class SignupForm(FormModel):
name: str = Field(title='Full name')
email: str = Field(title='Email', ui_element='email')
bootstrap_html = render_form_html(SignupForm, submit_url='/signup')
material_html = render_form_html(SignupForm, framework='material', submit_url='/signup')
plain_html = render_form_html(SignupForm, framework='none', submit_url='/signup')
The default. The form uses Bootstrap 5's classes (form-control,
form-select, invalid-feedback, ...), so it matches the rest of a
Bootstrap site, and validation states, icons and the grouped layouts
use Bootstrap's components.
Your page loads Bootstrap. The form HTML contains the markup, not Bootstrap itself, so add Bootstrap's CSS and JS to your page template:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
The tutorial's include_framework_assets=True, asset_mode="cdn" adds
these two tags to the form itself, which is handy for a page that has no
template.
A Material Design 3 look with floating labels, built into the library: the form carries its own styles, so your page needs nothing extra and no CSS framework. See Material Design 3 for the filled variant, the dark scheme and changing the colors.
framework="none" gives clean, semantic HTML with no framework classes,
ready for your own CSS.
Use the same framework= in validate() so a failed submit re-renders in the
same style. The live demo can show any page in either style: add
?style=material to its address.
Your own CSS¶
Every style keeps its markup predictable, so you can target it:
- the
<form>has the classpydantic-form(Material:md-form); - each input's
idis its field name (email,address.city), and its help and error messages are<id>-helpand<id>-error; ui_class="..."andui_style="..."on aField()add a class or inline style to that field's input.
Forms with no external files
self_contained=True inlines all of Bootstrap, its icons and the
library's scripts into the form HTML: no CDN, no static files. That's
useful for an offline app, an intranet without internet access or a
sandboxed iframe, but it adds several hundred kilobytes to every page.
See Assets and Self-Contained Forms.
Dark mode¶
Forms are light unless you opt in, and the switch is set by your page:
<html data-bs-theme="dark">
Bootstrap 5.3 recolors its own components, and the form's widgets, tabs, accordion and wizard follow it.
<html data-md-theme="dark">
Or declare color-scheme: dark on the page. See
Material Design 3.
framework="none" has no dark mode of its own.
Your own colors¶
Colors are CSS custom properties, so re-coloring needs no change to your Python. Put the rules in your page's stylesheet.
The form's widgets, tabs, accordion and wizard read --sf-* tokens:
:root {
--sf-primary: #00639b;
--sf-on-primary: #ffffff;
--sf-chip-bg: #d1e4ff;
--sf-chip-fg: #001d36;
}
Bootstrap's own buttons and inputs don't read these. Bootstrap's
.btn-primary sets its colors per class, so recolor those with
--bs-btn-* or your own Bootstrap build.
Set --md-sys-color-* on .md-form, and every control follows:
form.md-form {
--md-sys-color-primary: #00639b;
--md-sys-color-on-primary: #ffffff;
}
The token list is in Material Design 3.
Next: CSRF Protection.