Skip to main content

Conversational

The Conversational formatting template will display 1 field at a time, and smoothly scroll down to the next question until complete. It will appear and behave similarly to how Typeform displays forms, and is also a great choice for survey forms. This formatting template example is not dependent on any frameworks, comes complete and does not require any additional styling unless you wish to do so. You can place the CSS and JS inside the formatting template or add to your site's CSS / JS files.

Please note that this formatting template example has some expectations and limitations:

  • You should typically only place 1 field per row. Multiple fields in the same row will otherwise appear stacked on the same page (which may be okay in some cases).
  • Do not include a Submit button in the form layout, as this template adds one automatically.
  • Multiple Select, Dynamic Recipients, Credit Card/Payments, and Save & Continue Later fields/buttons currently are not accounted for in this example. They can of course be added if you put in the work to support it.
  • Multipage forms are not recommended to be used with this formatting template example.

Preview

Video: Preview of Formatting Template Examples

Formatting

{# Opening <form> tag #}
{{ form.renderTag }}

{# Display Success or Error banner and general errors if applicable #}
<div id="freeform-success-error-banner">
{% if not form.ajaxEnabled and form.submittedSuccessfully %}
<div class="freeform-form-success">
{{ form.successMessage | t('freeform') }}
</div>
{% endif %}

{% if form.hasErrors %}
<div class="freeform-form-errors">
{{ form.errorMessage | t('freeform') }}

{% if form.errors|length %}
<ul>
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
</div>

{# Render form fields #}
{% for row in form %}
{% set questionId = loop.index %}
{% set questionTotal = loop.length %}
<div id="q{{ questionId }}" class="freeform-page {{ form.customAttributes.rowClass }}">
<div class="freeform-question">
{% for field in row %}
{% set columnClass = form.customAttributes.columnClass %}
{% if field.type == "submit" or field.type == "save" %}
{% set columnClass = columnClass ~ " freeform-column-content-align-" ~ field.position %}
{% endif %}
{% if field.type in ["radio_group", "checkbox_group"] %}
<div class="freeform-fields {{ columnClass }} freeform-fieldtype-{{ field.type }}"{{ field.rulesHtmlData }}>
{{ field.renderLabel({
labelClass: "freeform-label" ~ (field.required ? " freeform-required" : "")
}) }}
{{ field.renderInstructions({
instructionsClass: "freeform-instructions"
}) }}
{% if field.type == "checkbox_group" %}
<span>Choose as many as you like</span>
{% endif %}
{% for index, option in field.options %}
<input type="{{ field.type == "radio_group" ? "radio" : "checkbox" }}"
name="{{ field.handle }}{{ field.type == "radio_group" ? "" : "[]" }}"
value="{{ option.value }}"
id="{{ field.idAttribute }}-{{ index }}"
class="form-check-input{{ field.hasErrors ? " freeform-has-errors" }}"
{{ option.checked ? "checked" : "" }}
/>
<label class="option-label" for="{{ field.idAttribute }}-{{ index }}">
<span>{{ range('A','Z')[loop.index0] }}</span> {{ option.label|t('freeform')|raw }}
</label>
{% endfor %}
{{ field.renderErrors({
errorClass: "freeform-errors"
}) }}
</div>
{% elseif field.type in ["checkbox", "mailing_list"] %}
<div class="freeform-fields {{ columnClass }} freeform-fieldtype-{{ field.type }}"{{ field.rulesHtmlData }}>
<div class="freeform-checkbox">
<label for="{{ field.idAttribute }}" class="form-check-label {{ field.hasErrors ? "freeform-has-errors" }} {{ field.required ? "freeform-required" }}">
{{ field.renderInput({
class: " form-check-input" ~ (field.hasErrors ? " freeform-has-errors")
}) }}
<span class="freeform-checkbox-slider"></span>
<span class="freeform-checkbox-label {{ field.required ? "freeform-required" }}">{{ field.label|t('freeform') }}</span>
</label>
{{ field.renderInstructions({
instructionsClass: "freeform-instructions"
}) }}
{{ field.renderErrors({
errorClass: "freeform-errors"
}) }}
</div>
</div>
{% elseif field.type in ["multiple_select", "dynamic_recipients", "cc_details", "save"] %}
<div class="freeform-fields {{ columnClass }} freeform-fieldtype-{{ field.type }}"{{ field.rulesHtmlData }}>
<p class="freeform-warning">This template does not support the {{ field.type|replace({'_': " ", '-': " "})|title }} field type by default. The affected field handle is: <code>{{ field.handle }}</code></p>
</div>
{% elseif field.type == "submit" %}
<div class="freeform-fields {{ columnClass }} freeform-fieldtype-{{ field.type }}"{{ field.rulesHtmlData }}>
<p class="freeform-warning">In order for this template to work correctly, it expects that there isn't Submit button in the form layout in the form builder. Please remove this Submit button inside the form builder.</p>
</div>
{% else %}
<div class="freeform-fields {{ columnClass }} freeform-fieldtype-{{ field.type }}"{{ field.rulesHtmlData }}>
{{ field.render({
class: field.type not in ["submit", "save", "signature"] ? "freeform-input" : "",
labelClass: "freeform-label" ~ (field.required ? " freeform-required" : ""),
errorClass: "freeform-errors",
instructionsClass: "freeform-instructions",
}) }}
</div>
{% endif %}
{% endfor %}
<div class="freeform-buttons">
{% if questionId != questionTotal %}
<a href="#q{{ questionId + '1' }}">Next</a>
{% endif %}
{% if questionId == questionTotal %}
<button type="submit" class="submit-button" data-freeform-action="submit">Submit</button>
{% endif %}
{% if questionId > "1" %}
<a href="#q{{ questionId - '1' }}" class="previous">Previous</a>
{% endif %}
</div>
</div>
</div>
{% endfor %}

{# Closing </form> tag #}
{{ form.renderClosingTag }}

CSS

The following CSS is a supplemental starting point to get forms appearing robustly.

/* LAYOUT */
html,
body {
scroll-behavior: smooth;
}
.freeform-form-container {
font-family: sans-serif;
}
.freeform-page {
background: #212529;
padding: 0;
width: 100vw;
height: 100vh;
position: static;
display: flex;
align-items: center;
justify-content: center;
vertical-align: middle;
}
.freeform-question {
font: normal 25px sans-serif;
color: #ffffff;
background: transparent;
padding: 0;
width: 40vw;
height: 40vh;
display: flex;
align-items: left;
justify-content: center;
flex-flow: column nowrap;
}
.freeform-question > div.freeform-fields > label:first-child {
margin-bottom: 20px;
}
.freeform-fields {
margin-bottom: 30px;
display: flex;
flex-flow: column nowrap;
}
.freeform-warning {
font: normal 18px sans-serif;
line-height: 1.5;
color: #997404;
background-color: transparent;
border: 1px solid #997404;
border-radius: 5px;
width: 40vw;
display: block;
padding: 15px;
}
.freeform-warning code {
font: monospace;
}
#freeform-success-error-banner,
.freeform-ajax-form-success,
.freeform-ajax-form-errors {
margin-left: auto;
margin-right: auto;
width: 100%;
}
.freeform-form-success,
.freeform-ajax-form-success p,
.freeform-form-errors,
.freeform-ajax-form-errors p {
font: normal 18px sans-serif;
color: #ffffff;
line-height: 1.5;
text-align: center;
border-radius: 5px;
width: 40vw;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
padding: 15px;
position: relative;
justify-content: center;
}
.freeform-form-success,
.freeform-ajax-form-success p {
background-color: #198754;
border: 1px solid #198754;
}
.freeform-form-errors,
.freeform-ajax-form-errors p {
background-color: #dc3545;
border: 1px solid #dc3545;
}

/* BUTTONS */
button,
.freeform-buttons a {
font: 400 16px sans-serif;
line-height: 1.5;
color: #ffffff;
text-align: center;
text-decoration: none;
border: 1px solid #6c757d;
border-radius: 5px;
background-color: transparent;
padding: 5px 15px;
margin-right: 10px;
cursor: pointer;
display: inline-block;
vertical-align: middle;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out;
}
.freeform-buttons {
justify-content: center;
}
.freeform-buttons a,
.submit-button {
font: 400 22px sans-serif;
border: 1px solid #0d6efd;
background-color: #0d6efd;
padding: 10px 25px;
}
.freeform-buttons a:hover,
.submit-button:hover {
color: #ffffff;
background-color: #0b5ed7;
border-color: #0a58ca;
}
.freeform-buttons .previous {
font: 400 16px sans-serif;
color: #6c757d;
background-color: transparent;
border-color: transparent;
}
.freeform-buttons .previous:hover {
color: #ffffff;
background-color: transparent;
border-color: #6c757d;
}

/* BASIC FIELD STYLES */
label.freeform-required:after {
color: #dc3545;
content: '*';
margin-left: 5px;
}
.freeform-instructions {
font: 200 18px sans-serif;
color: #6c757d;
margin-bottom: 20px;
margin-top: -15px;
display: block;
}
.freeform-errors {
padding: 0 25px;
margin: 0;
}
.freeform-errors li {
font: 200 16px sans-serif;
color: #dc3545;
margin-top: 15px;
}
input,
textarea,
select {
font: normal 25px sans-serif;
color: #ffffff;
background-color: transparent;
border: 0;
border-bottom: 2px solid #767676;
padding: 15px 0;
width: 100%;
display: block;
resize: none;
}
input:focus,
textarea:focus,
select:focus {
border-bottom: 2px solid #0b5ed7;
outline: 0;
transition: border-color 0.15s ease-in-out;
}
input::placeholder,
textarea::placeholder {
font: italic 200 18px sans-serif;
color: #6c757d;
}
input.freeform-has-errors,
textarea.freeform-has-errors,
select.freeform-has-errors {
border-bottom: 2px solid #dc3545;
}

/* RADIO & CHECKBOX GROUP FIELDS */
input[type='radio'],
input[type='checkbox'] {
display: none;
}
.freeform-fieldtype-radio_group label:not(:first-child),
.freeform-fieldtype-checkbox_group label:not(:first-child) {
font: normal 20px sans-serif;
color: #ffffff;
background-color: #1d1f23;
border: 1px solid #767676;
border-radius: 5px;
padding: 15px;
margin-bottom: 5px;
cursor: pointer;
}
.freeform-fieldtype-radio_group label:not(:first-child):hover,
.freeform-fieldtype-checkbox_group label:not(:first-child):hover {
background-color: #262a2e;
border: 1px solid #0d6efd;
}
.freeform-fieldtype-checkbox_group span {
font: italic 15px sans-serif;
color: #6c757d;
margin-bottom: 15px;
}
.freeform-fieldtype-radio_group .option-label span,
.freeform-fieldtype-checkbox_group .option-label span {
font: bold 16px sans-serif;
color: #6c757d;
text-align: center;
background-color: #ffffff;
border: 1px solid #767676;
border-radius: 5px;
width: 17px;
height: 17px;
padding: 5px;
margin: 0 15px 0 0;
display: inline-block;
}
.freeform-fieldtype-radio_group .freeform-has-errors + label:not(:first-child),
.freeform-fieldtype-checkbox_group
.freeform-has-errors
+ label:not(:first-child) {
border: 1px dashed #dc3545;
}
input[type='radio']:checked + label,
input[type='checkbox']:checked + label {
color: #0d6efd;
background-color: #1a1d20;
border: 1px solid #0d6efd;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out;
}
input[type='radio']:checked + label:after,
input[type='checkbox']:checked + label:after {
font: normal 18px sans-serif;
color: #ffffff;
content: '✓';
margin-left: 15px;
}
input[type='radio']:checked + label span,
input[type='checkbox']:checked + label span {
color: #ffffff;
background-color: #0d6efd;
border: 1px solid #0d6efd;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out;
}

/* OPINION SCALE FIELDS */
.freeform-fieldtype-opinion_scale
.opinion-scale-scales
label:not(:first-child) {
font: normal 18px sans-serif;
color: #ffffff !important;
background-color: #1d1f23;
border: 1px solid #767676;
border-radius: 5px;
padding: 15px;
margin: 0;
cursor: pointer;
}
.freeform-fieldtype-opinion_scale .opinion-scale-scales li:not(:last-child) {
margin-right: 10px;
}
.freeform-fieldtype-opinion_scale
.opinion-scale-scales
label:not(:first-child):hover {
background-color: #262a2e;
border: 1px solid #0d6efd;
}
.freeform-fieldtype-opinion_scale input[type='radio']:checked + label,
.freeform-fieldtype-opinion_scale input[type='radio']:checked + label:hover {
font-weight: bold;
color: #0d6efd !important;
background-color: #ffffff;
border: 1px solid #0d6efd;
}
.freeform-fieldtype-opinion_scale input[type='radio']:checked + label:after {
content: '';
margin-left: 0;
}
.freeform-fieldtype-opinion_scale .freeform-has-errors + label {
border: 1px dashed #dc3545 !important;
}
.freeform-fieldtype-opinion_scale .opinion-scale-legends li {
font: normal 18px sans-serif;
color: #ffffff;
padding: 10px 0;
margin-top: 5px;
}

/* RATING FIELDS */
.freeform-fieldtype-rating .freeform-has-errors + label:not(:first-child) {
color: #dc3545;
}
.form-rating-field-wrapper input[type='radio'] + label {
background-color: initial;
border: initial;
border-radius: initial;
width: initial;
padding: initial;
margin-right: 15px;
}

/* FILE UPLOAD DRAG & DROP FIELDS */
.freeform-file-drag-and-drop {
background-color: #1d1f23 !important;
border: 1px dashed #767676 !important;
}
.freeform-file-drag-and-drop__placeholder {
font: italic 200 18px sans-serif;
color: #6c757d;
}
.freeform-file-drag-and-drop [data-messages] > li[data-error],
.freeform-file-drag-and-drop [data-field-errors] > li[data-error] {
font: 200 16px sans-serif;
color: #dc3545;
margin-top: 15px;
}
.freeform-file-drag-and-drop [data-field-errors] > li {
color: #dc3545;
}

/* SIGNATURE FIELDS */
.freeform-fieldtype-signature button {
font: 400 16px sans-serif;
color: #ffffff;
border: 1px solid #6c757d;
background-color: transparent;
}
.freeform-fieldtype-signature button:hover {
color: #fff;
background-color: #6c757d;
border-color: #6c757d;
}
.freeform-fieldtype-signature canvas {
border: 1px solid #767676;
border-radius: 5px;
}

/* TABLE FIELDS */
.freeform-fieldtype-table table thead tr th {
font: 400 16px sans-serif;
text-align: left;
}
.freeform-fieldtype-table table button[data-freeform-table-remove-row] {
font-size: 1px;
margin: 0;
padding: 0;
visibility: hidden;
}
.freeform-fieldtype-table table button[data-freeform-table-remove-row]:after {
font: 400 16px sans-serif;
color: #b02a37;
line-height: 1.5;
text-align: center;
text-decoration: none;
content: '✕';
border: 1px solid #b02a37;
border-radius: 5px;
background-color: transparent;
padding: 5px 15px;
margin-right: 10px;
display: inline-block;
vertical-align: middle;
cursor: pointer;
visibility: visible;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out;
}
.freeform-fieldtype-table
table
button[data-freeform-table-remove-row]:hover:after {
color: #ffffff;
background-color: #b02a37;
border-color: #b02a37;
}
.freeform-fieldtype-table button[data-freeform-table-add-row] {
color: #146c43;
content: '+';
border: 1px solid #146c43;
background-color: transparent;
margin: 10px 10px 0 0;
width: 100px;
}
.freeform-fieldtype-table button[data-freeform-table-add-row]:hover {
color: #ffffff;
background-color: #146c43;
border-color: #146c43;
}
.freeform-fieldtype-table button[data-freeform-table-add-row]:after {
content: '+';
margin-left: 5px;
}
.freeform-fieldtype-table input[type='checkbox'] {
display: block;
transform: scale(2);
}

/* CHECKBOX & MAILING LIST FIELDS */
.freeform-fieldtype-checkbox,
.freeform-fieldtype-mailing_list {
min-height: 75px;
}
.freeform-checkbox {
width: 60px;
height: 34px;
position: relative;
}
.freeform-checkbox input {
opacity: 0;
width: 0;
height: 0;
}
.freeform-checkbox-label {
padding-left: 100px;
width: 30vw;
cursor: pointer;
display: inline-block;
}
.freeform-checkbox-slider {
background-color: #6c757d;
border-radius: 5px;
top: 0;
left: 0;
right: 0;
bottom: 0;
position: absolute;
cursor: pointer;
transition: 0.4s;
}
.freeform-checkbox-slider:before {
content: '';
background-color: #ffffff;
border-radius: 5px;
height: 26px;
width: 26px;
position: absolute;
left: 4px;
bottom: 4px;
transition: 0.4s;
}
.freeform-fieldtype-checkbox input:checked + span,
.freeform-fieldtype-mailing_list input:checked + span {
background-color: #0d6efd;
}
.freeform-fieldtype-checkbox input:focus + span,
.freeform-fieldtype-mailing_list input:focus + span {
box-shadow: 0 0 1px #0d6efd;
}
.freeform-fieldtype-checkbox input:checked + span:before,
.freeform-fieldtype-mailing_list input:checked + span:before {
transform: translateX(26px);
}
.freeform-fieldtype-checkbox label.freeform-required:after,
.freeform-fieldtype-mailing_list label.freeform-required:after {
content: '';
margin-left: 0;
display: none;
}
.freeform-fieldtype-checkbox .freeform-checkbox-label.freeform-required:after,
.freeform-fieldtype-mailing_list
.freeform-checkbox-label.freeform-required:after {
color: #dc3545;
content: '*';
margin-left: 5px;
}
.freeform-fieldtype-checkbox .freeform-instructions,
.freeform-fieldtype-mailing_list .freeform-instructions {
margin: 5px 0 0 100px;
width: 30vw;
}
.freeform-fieldtype-checkbox .freeform-errors,
.freeform-fieldtype-mailing_list .freeform-errors {
margin: 5px 0 0 100px;
width: 30vw;
}
.freeform-fieldtype-checkbox
input[type='checkbox'].freeform-has-errors
+ .freeform-checkbox-slider {
background-color: #dc3545;
}

/* RESPONSIVE */
@media only screen and (max-width: 1600px) {
.freeform-question {
width: 50vw;
}
.freeform-form-success,
.freeform-ajax-form-success p,
.freeform-form-errors,
.freeform-ajax-form-errors p,
.freeform-warning {
width: 50vw;
}
.freeform-fieldtype-checkbox .freeform-instructions,
.freeform-fieldtype-mailing_list .freeform-instructions,
.freeform-fieldtype-checkbox .freeform-errors,
.freeform-fieldtype-mailing_list .freeform-errors,
.freeform-checkbox-label {
width: 40vw;
}
}
@media only screen and (max-width: 1300px) {
.freeform-question {
width: 70vw;
}
.freeform-form-success,
.freeform-ajax-form-success p,
.freeform-form-errors,
.freeform-ajax-form-errors p,
.freeform-warning {
width: 70vw;
}
.freeform-fieldtype-checkbox .freeform-instructions,
.freeform-fieldtype-mailing_list .freeform-instructions,
.freeform-fieldtype-checkbox .freeform-errors,
.freeform-fieldtype-mailing_list .freeform-errors,
.freeform-checkbox-label {
width: 60vw;
}
}
@media only screen and (max-width: 800px) {
.freeform-question {
width: 90vw;
}
.freeform-form-success,
.freeform-ajax-form-success p,
.freeform-form-errors,
.freeform-ajax-form-errors p,
.freeform-warning {
width: 80vw;
}
.freeform-fieldtype-checkbox .freeform-instructions,
.freeform-fieldtype-mailing_list .freeform-instructions,
.freeform-fieldtype-checkbox .freeform-errors,
.freeform-fieldtype-mailing_list .freeform-errors,
.freeform-checkbox-label {
width: 70vw;
}
}

/* SUBMIT LOADING INDICATOR */
button[type='submit'].ff-loading {
display: -ms-inline-flexbox;
display: inline-flex;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
-ms-flex-align: center;
align-items: center;
}
button[type='submit'].ff-loading:before {
content: '';
display: block;
-ms-flex: 1 0 11px;
flex: 1 0 11px;
width: 11px;
height: 11px;
margin-right: 10px;
border-style: solid;
border-width: 2px;
border-color: transparent transparent white white;
border-radius: 50%;
animation: ff-loading 0.5s linear infinite;
}
.mt-n1 {
margin-top: -0.5rem !important;
}
@keyframes ff-loading {
0% {
transform: rotate(0);
}
100% {
transform: rotate(1turn);
}
}

JS

The following JS is a supplemental starting point to handle additional elements in the form.

// Adjustments for Success and Errors classes
document.addEventListener('freeform-ready', function (event) {
event.options.errorClassBanner = 'freeform-ajax-form-errors';
event.options.errorClassList = 'freeform-errors';
event.options.errorClassField = 'freeform-has-errors';
event.options.successClassBanner = 'freeform-ajax-form-success';
});