WordPress Snippets

Gravity Forms Bootstrap 5 Markup and Styles

5 October 2021
Gravity Forms Bootstrap 5 Markup and Styles

Gravity Forms Bootstrap 5 Styling

By default, Gravity Forms does not support Bootstrap classes out of the box, so the two don’t end up working very well together. The included Gravity Forms CSS includes too many styles that need to be overridden, this is why instead of applying Bootstrap styles directly, we tweaked Gravity Forms to add default Bootstrap markup.

<?php
/**
* @snippet Gravity Form Bootstrap 5 Markup
* @author Prosvit Design Team
* @website https://prosvit.design
*/
/**
* Filters form field containers
* Adds Bootstrap Grid classes to containers
*/
add_filter('gform_get_form_filter', 'prosvit_design_add_bootstrap_grid_row_markup', 10, 2);
function prosvit_design_add_bootstrap_grid_row_markup($form_string, $form)
{
return str_replace('gform_fields', 'gform_fields row', $form_string);
}
add_filter('gform_field_container', 'prosvit_design_add_bootstrap_grid_columns_markup', 10, 6);
function prosvit_design_add_bootstrap_grid_columns_markup($field_container, $field, $form, $css_class, $style, $field_content)
{
if (is_admin()) {
return $field_container;
}
$css_class .= ' col-12 mb-3';
if (!strpos($css_class, 'gfield--width-full')) {
$css_class .= ' col-md';
}
return '<div class="' . $css_class . '">' . $field_content . '</div>';
}
/**
* Filters form fields
* Adds Bootstrap classes to input, textarea, select, radio
*/
add_filter('gform_field_content', 'prosvit_design_add_bootstrap_fields_markup', 10, 2);
function prosvit_design_add_bootstrap_fields_markup($field_content, $field)
{
if (is_admin()) {
return $field_content;
}
$bootstrap_classes = array(
'text' => [
'tag' => 'form-control',
'label' => 'form-label',
'text' => 'form-text',
],
'number' => [
'tag' => 'form-control',
'label' => 'form-label',
'text' => 'form-text',
],
'textarea' => [
'tag' => 'form-control',
'label' => 'form-label',
'text' => 'form-text',
],
'name' => [
'tag' => 'form-control',
'label' => 'form-label',
'text' => 'form-text',
],
'select' => [
'tag' => 'form-select',
'label' => 'form-label',
'text' => 'form-text',
],
'checkbox' => [
'tag' => 'form-check-input',
'label' => 'form-check-label',
'text' => 'form-text',
],
'radio' => [
'tag' => 'form-check-input',
'label' => 'form-check-label',
'text' => 'form-text',
],
);
$tags = array(
'text' => 'input',
'number' => 'input',
'checkbox' => 'input',
'radio' => 'input',
'name' => 'input',
'textarea' => 'textarea',
'select' => 'select'
);
$dom = new DOMDocument();
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $field_content);
// Labels - add "form-label/form-check-label" class
$labels = $dom->getElementsByTagName('label');
if ($labels) {
foreach ($labels as $label) {
$class_label = $label->getAttribute('class');
$class_label_new = (array_key_exists($field->type, $bootstrap_classes)) ? $bootstrap_classes[$field->type]['label'] : '';
$label->setAttribute('class', $class_label_new . ' ' . $class_label);
}
}
// Divs
// Descriptions - add "form-text/invalid-feedback" class
$divs = $dom->getElementsByTagName('div');
foreach ($divs as $div) {
$class = $div->getAttribute('class');
$class_new = [];
$class_new[] = $class;
// Descriptions
if (strpos($class, 'gfield_description') !== false) {
$class_new[] = (array_key_exists($field->type, $bootstrap_classes)) ? $bootstrap_classes[$field->type]['text'] : '';
}
// Validation
if ($field->failed_validation) {
$class_new[] = 'is-invalid';
}
if (strpos($class, 'gfield_validation_message') !== false) {
$class_new[] = 'invalid-feedback';
}
// Checkboxes & Radios
if (strpos($class, 'gchoice') !== false) {
$class_new[] = 'form-check';
}
$div->setAttribute('class', implode(' ', $class_new));
}
// Tags - add "form-control/form-select/form-check-input" class
$field_type_tag = (array_key_exists($field->type, $tags)) ? $tags[$field->type] : null;
$field_tags = !empty($field_type_tag) ? $dom->getElementsByTagName($field_type_tag) : null;
if (!empty($field_tags)) {
foreach ($field_tags as $field_tag) {
$class = $field_tag->getAttribute('class');
$class_new = [];
$class_new[] = $class;
// Tag class
if (array_key_exists($field->type, $bootstrap_classes)) {
$class_new[] = $bootstrap_classes[$field->type]['tag'];
}
// Validation class
if ($field->failed_validation) {
$class_new[] = 'is-invalid';
}
$field_tag->setAttribute('class', implode(' ', $class_new));
// Checkboxes & Radios required tag
if ($field->isRequired) {
$field_tag->setAttribute('required', 'required');
}
}
}
return $dom->saveHtml();
}
/**
* Filters the next, previous and submit buttons.
* Replaces the forms <input> buttons with <button> while maintaining attributes from original <input>.
* Adds Bootstrap btn and btn-primary classes
*/
add_filter('gform_next_button', 'prosvit_design_add_button_bootstrap_markup', 10, 2);
add_filter('gform_previous_button', 'prosvit_design_add_button_bootstrap_markup', 10, 2);
add_filter('gform_submit_button', 'prosvit_design_add_button_bootstrap_markup', 10, 2);
function prosvit_design_add_button_bootstrap_markup($button, $form)
{
$dom = new DOMDocument();
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $button);
$input = $dom->getElementsByTagName('input')->item(0);
$new_button = $dom->createElement('button');
$new_button->appendChild($dom->createTextNode($input->getAttribute('value')));
$input->removeAttribute('value');
foreach ($input->attributes as $attribute) {
// Add class btn btn-primary
if ($attribute->name == 'class') {
$attribute->value .= ' btn btn-primary';
}
$new_button->setAttribute($attribute->name, $attribute->value);
}
$input->parentNode->replaceChild($new_button, $input);
return $dom->saveHtml($new_button);
}
/**
* Bootstrap Form Validation
*/
add_action('wp_footer', 'prosvit_design_add_bootstrap_js_validation');
function prosvit_design_add_bootstrap_js_validation()
{ ?>
<script>
jQuery(document).bind('gform_post_render', function(e, formID) {
if (!jQuery('.gform_validation_errors').length) {
return;
}
const form = document.getElementById('gform_' + formID);
form.classList.add('was-validated');
});
</script>
<?php }

Features

  • Applies Bootstrap classes to common field types – input, select, textarea, checks & radios ( .form-control, .form-select, .form-label, etc. )
  • Applies Bootstrap classes to the submit button ( .btn, .btn-primary, etc. )
  • Applies Bootstrap classes to columns ( .col, .col-md, etc. )
  • Supports Gravity Forms validation

Usage and Settings

A. Disable the output of the default Gravity Forms CSS.

  1. Set Output CSS to No
  2. Set Output HTML5 to Yes

B. Requires Bootstrap to be in use by the theme – https://getbootstrap.com/docs/5.0/getting-started/download/.

Does this snippet (still) work?

Please let us know in the comments if everything worked as expected. We would be happy to revise the snippet if you report otherwise (please provide screenshots).

Leave a Reply

Your email address will not be published. Required fields are marked *

Some of Our Clients

Join clients who enjoy 96% satisfaction

Schedule a Free Strategy Call with a WordPress Expert