Flexbox
The Flexbox formatting template implementation includes a lot more CSS to style it correctly. You can place the CSS and JS inside the formatting template or add to your site's CSS / JS files.
Preview
Video: Preview of Formatting Template Examples
Formatting
{# Opening <form> tag #}
{{ form.renderTag }}
{# Display page tabs if Multi-page form #}
{% if form.pages|length > 1 %}
<ul class="freeform-pages">
{% for page in form.pages %}
<li>
{% if form.currentPage.index == page.index %}
<b>{{ page.label }}</b>
{% else %}
{{ page.label }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{# Display Error banner and general errors if applicable #}
{% if form.hasErrors %}
<div class="freeform-form-has-errors">
{{ "Error! Please review the form and try submitting again."|t('freeform') }}
{% if form.errors|length %}
<ul>
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
{# Render form fields #}
{% for row in form %}
<div class="freeform-row {{ form.customAttributes.rowClass }}">
{% for field in row %}
{% set columnClass = "freeform-column " ~ form.customAttributes.columnClass %}
{% if field.type == "submit" %}
{% set columnClass = columnClass ~ " freeform-column-content-align-" ~ field.position %}
{% endif %}
<div class="{{ columnClass }}"{{ field.rulesHtmlData }}>
{{ field.render({
class: field.type not in ["submit", "signature"] ? "freeform-input" : "",
labelClass: "freeform-label" ~ (field.inputOnly ? " freeform-input-only-label" : "") ~ (field.required ? " freeform-required" : ""),
errorClass: "freeform-errors",
instructionsClass: "freeform-instructions",
}) }}
{# FOR FREEFORM PAYMENTS #}
{% if field.layoutRows is defined %}
{% for layoutRow in field.layoutRows %}
<div class="freeform-row {{ form.customAttributes.rowClass }}">
{% for layoutField in layoutRow %}
<div class="{{ columnClass }}">
{{ layoutField.render({
class: "freeform-input",
labelClass: "freeform-label" ~ (layoutField.inputOnly ? " freeform-input-only-label" : "") ~ (layoutField.required ? " freeform-required" : ""),
errorClass: "freeform-errors",
instructionsClass: "freeform-instructions",
}) }}
</div>
{% endfor %}
</div>
{% endfor %}
{% endif %}
</div>
{% endfor %}
</div>
{% endfor %}
{# Closing </form> tag #}
{{ form.renderClosingTag }}
CSS
The following CSS is a supplemental starting point to get forms appearing robustly.
button[type='submit'].ff-loading {
display: inline-flex;
flex-wrap: nowrap;
align-items: center;
}
button[type='submit'].ff-loading:before {
content: '';
display: block;
flex: 1 0 11px;
width: 11px;
height: 11px;
margin-right: 10px;
border-style: solid;
border-width: 2px;
border-color: transparent transparent #fff #fff;
border-radius: 50%;
animation: ff-loading 0.5s linear infinite;
}
@keyframes ff-loading {
0% {
transform: rotate(0);
}
100% {
transform: rotate(1turn);
}
}
.freeform-pages {
display: flex;
padding: 0;
margin: 0 0 10px;
list-style: none;
}
.freeform-pages li {
margin: 0 10px 0 0;
}
.freeform-row {
display: flex;
justify-content: space-between;
margin: 0 -15px;
}
.freeform-row .freeform-column {
flex: 1 0;
padding: 10px 0;
margin: 0 15px;
box-sizing: border-box;
}
.freeform-row .freeform-column > .freeform-row:first-child {
margin-top: -10px;
}
.freeform-row .freeform-column label {
display: block;
}
.freeform-row .freeform-column .input-group-one-line {
display: flex;
flex-wrap: wrap;
}
.freeform-row .freeform-column .input-group-one-line label {
padding-right: 10px;
}
.freeform-row .freeform-column .freeform-label {
font-weight: bold;
}
.freeform-row .freeform-column .freeform-label.freeform-required:after {
content: '*';
margin-left: 5px;
color: red;
}
.freeform-row .freeform-column .freeform-input {
width: 100%;
display: block;
box-sizing: border-box;
}
.freeform-row .freeform-column .freeform-input[type='checkbox'],
.freeform-row .freeform-column .freeform-input[type='radio'] {
width: auto;
display: inline;
margin-right: 5px;
}
.freeform-row .freeform-column .freeform-input.StripeElement {
padding: 4px 2px;
border: 1px solid #ccc;
height: 30px;
}
.freeform-row .freeform-column .freeform-input-only-label {
font-weight: normal;
}
.freeform-row .freeform-column .freeform-input-only-label > .freeform-input {
display: inline-block;
width: auto;
margin-right: 5px;
}
.freeform-row .freeform-column .freeform-errors,
.freeform-row .freeform-column .ff-errors {
list-style: none;
padding: 0;
margin: 5px 0 0;
}
.freeform-row .freeform-column .freeform-errors > li,
.freeform-row .freeform-column .ff-errors > li {
color: red;
}
.freeform-row .freeform-column .freeform-instructions {
margin: 0 0 5px;
font-size: 13px;
color: #aba7a7;
}
.freeform-row .freeform-column.freeform-column-content-align-left {
display: flex;
justify-content: flex-start;
}
.freeform-row
.freeform-column.freeform-column-content-align-left
> button:not(:first-of-type) {
margin-left: 5px;
}
.freeform-row .freeform-column.freeform-column-content-align-center {
display: flex;
justify-content: center;
}
.freeform-row
.freeform-column.freeform-column-content-align-center
> button:not(:first-of-type) {
margin-left: 5px;
}
.freeform-row .freeform-column.freeform-column-content-align-right {
display: flex;
justify-content: flex-end;
}
.freeform-row
.freeform-column.freeform-column-content-align-right
> button:not(:first-of-type) {
margin-left: 5px;
}
.freeform-row .freeform-column.freeform-column-content-align-spread {
display: flex;
justify-content: space-between;
}
.freeform-row
.freeform-column.freeform-column-content-align-spread
> button:not(:first-of-type) {
margin-left: 5px;
}
.ff-form-errors {
padding: 15px;
border: 1px solid #f5c6cb;
background: #f8d7da;
border-radius: 5px;
color: #721c24;
}
.ff-form-errors > p {
margin: 0;
}
.freeform-form-has-errors {
color: #721c24;
}
JS
The following JS is a supplemental starting point to handle additional elements in the form.
// Styling for Stripe Payments field
document.addEventListener('freeform-stripe-styling', function (event) {
event.detail.base = {
fontSize: '16px',
fontFamily:
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"',
};
});
Live Demo
The demo below is a live demo site that shows most of what the Demo Templates include (some sections and data has been limited).