Skip to main content

Tailwind CSS 3Improved in 5.0+

The following example assumes you're including necessary Tailwind CSS 3 components. Due to the nature of Tailwind, this likely won't be useable as-is for most customers, but will serve as a good starting point for creating your own. 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

Templates

/tailwind-3/
{# CSS overrides #}
{% set cssPath = view.assetManager.publishedUrl('@freeform-formatting-templates/tailwind-3/_main.css', true) %}
{% do view.registerCssFile(cssPath) %}

{# JS overrides #}
{% set jsPath = view.assetManager.publishedUrl('@freeform-formatting-templates/tailwind-3/_main.js', true) %}
{% do view.registerJsFile(jsPath) %}

{% import "freeform/_templates/formatting/tailwind-3/_row.twig" as rowMacro %}

{# Render the opening form tag #}
{{ form.renderTag({
attributes: {
form: { class: "freeform-form", "data-freeform-tailwind": true },
row: { class: "flex flex-wrap -mx-2 mb-4" },
success: { class: "bg-green-100 border border-green-400 font-bold text-green-700 px-4 py-3 rounded relative mb-4" },
errors: { class: "bg-red-100 border border-red-400 font-bold text-red-700 px-4 py-3 rounded relative mb-4" },
novalidate: true,
},
buttons: {
attributes: {
container: { class: "flex flex-wrap -mx-2 mb-4" },
column: { class: "ml-2" },
buttonWrapper: {},
submit: { class: "bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mr-2" },
back: { class: "bg-gray-400 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded mr-2" },
save: { class: "bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mr-2" },
},
},
fields: {
"@global": {
attributes: {
container: { class: "w-full px-2" },
label: { class: "block text-slate-800 text-base font-medium mb-1" },
input: {
class: [
"md:mb-0 mb-4",
"appearance-none block w-full",
"text-slate-800 rounded py-2 px-3 leading-tight",
"placeholder:font-light placeholder:text-slate-400",
"border border-slate-400 focus:outline-none focus:bg-white focus:border-blue-600",
],
},
instructions: { class: "block text-slate-500 text-sm -mt-1.5 mb-1" },
error: { class: "freeform-errors block w-full text-sm text-red-500 mt-1" },
},
},
":required": {
attributes: {
label: { "+class": "required" },
},
},
":errors": {
attributes: {
input: { "+class": "border-red-500" },
},
},
"@checkbox, @checkboxes, @radios, @opinion-scale, @signature, @table": {
attributes: {
input: { "-class": "appearance-none block w-full" },
},
},
"@signature": {
attributes: {
input: { "+class": "rounded py-1 px-2 mr-1 hover:bg-slate-400" },
},
},
"@checkbox" : {
attributes: {
label: {
"-class": "block text-slate-800 text-base font-medium mb-1",
"+class": "ml-2 font-medium text-slate-700"
},
},
},
"@checkbox, @checkboxes, @radios": {
attributes: {
input: { "+class": "w-4 h-4 text-blue-600 bg-slate-100 border-slate-300 rounded" },
},
},
"@stripe": {
attributes: {
input: { "-class": "rounded py-2 px-3 leading-tight placeholder:font-light placeholder:text-slate-400 border border-slate-400 focus:outline-none focus:bg-white focus:border-blue-600" },
},
},
},
}) }}

{# Success and error message handling for non-AJAX forms #}
{% if not form.settings.ajax %}
{% if form.submittedSuccessfully %}
<div{{ form.attributes.success|raw }}>
<p>{{ form.settings.successMessage | t('freeform') }}</p>
</div>
{% endif %}
{% if form.hasErrors %}
<div{{ form.attributes.errors|raw }}>
<p>{{ form.settings.errorMessage | t('freeform') }}</p>

{% if form.errors|length %}
<ul class="mb-0">
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
{% endif %}

{# Render page tabs if multi-page #}
{% if form.pages|length > 1 %}
<ul class="flex border-b-2 border-slate-300 mb-6">
{% for page in form.pages %}
<li class="mr-1">
<span class="inline-block rounded-t py-2 px-5 {{ form.currentPage.index == page.index ? 'bg-slate-300 border-l border-t border-r border-slate-300 text-slate-800 font-semibold' : 'bg-white text-slate-500 font-normal' }}">{{ page.label }}</span>
</li>
{% endfor %}
</ul>
{% endif %}

{# Display form field rows and columns #}
{{ rowMacro.render(form.rows, form) }}

{# Render the closing form tag #}
{{ form.renderClosingTag }}
/tailwind-3/fields/
{{ field.render }}

Tailwind CSS is typically installed via CLI, but for the purposes of this example template, we use a CDN. The following CDN link for Tailwind CSS 3 is for v3.3.3, which may no longer be the latest version. Please see official Tailwind CSS 3 documentation for latest versions and CDN links.

<!-- Latest compiled and minified CSS -->
<script src="https://cdn.tailwindcss.com/3.3.3"></script>

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).