How to style radio button in a muti steps Formidable Form
Formidable Form is a freemium plugin to build simple or complex forms on the WordPress CMS. It has a lot of cool features allowing to build the form you need. But sometimes, you need more.
The problem
We stumble upon this problem with a multi step form by wanting to:
- style radio buttons when an option is selected and not lose the styles if we go back
- change the title and description of the form in the last step
To do that, we add some styles (css), some javascript and a bit of PHP with Formidable form hook.
The solution
We’ll do some changes in several files and parts of the website.
The process is:
- Style the radio button
- we will style the elements through a css class
- we will add or remove this class based on change event on the input / label with some vanilla js code to add this class
- Modify title and form description at the last step with some javascript detecting the color changing of the progress bar of the last step element
- the javascript code is added to each step using a Formidable Form hook on the submit buttons in the functions.php file
The CSS
On this website, we worked with Elementor. We put the custom css code in the Site settings > Custom CSS tab directly through Elementor interface. You can of course include these styles directly in the style.css of your child theme (because you have a child theme, and if not, do one).
The CSS Code to do this:
form label input {
display: none;
}
form .frm_radio label {
cursor: pointer;
}
form .frm_radio.highlight {
background: #6EA151;
color: white;
}
form .frm_form_field.frm_two_col .frm_radio {
border: 1px solid green;
padding: 15px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
margin: 10px 0
}
form .frm_form_field.frm_two_col .frm_radio label {
text-align: center;
}
- we hide the input button
- we transform the cursor to pointer to be easier for the user to understand where to click (the label)
- we style the highlight class which will be add to the element when selected
- .frm_radio targeted elements have display: flex. We use the align-items and justify-content to center vertically and horizontally the content. We add bottom and top margins to separate the buttons.
We style the element with .frm_radio class and not the label element because the .frm_radio corresponds to the container.
The javascript
Now, we have to apply these styles on click on the radio button with some vanilla javascript
var inputs = document.querySelectorAll('.frm_radio label');
for(var i=0;i<inputs.length;i++) {
inputs[i].addEventListener('click',function(){
for(var j=0; j<inputs.length; j++) {
inputs[j].parentNode.classList.remove('highlight');
}
this.parentNode.classList.add('highlight'); // put hightlight on the one clicked (this)
});
}
What we do here:
- get all the inputs elements on the current step of the form
- loop on these elements to add a click event listener
- in the click event, loop on all the elements to remove the highlight class in all the parents of the input elements
- add the highlight class to the current element
- add also code to highlight the element which is checked. It’s used when you click on “Previous” to go back to the previous step. In this case, there will be a checked input.
We also have to add some javascript to style the radio button when we go back to the previous step where a choice has already been made, i.e. an input element has a checked state.
var input = document.querySelector('.frm_radio label input:checked');
if(input !== null && input !== '') {
input.parentNode.parentNode.classList.add('highlight');
}
The PHP
Why do we need PHP here? Because it’s a multi steps form. In this cas, we have to call the javascript functions on each step. If we just include javascript code one time, it will not be applied to each steps.
We couldn’t directly change the onClick() function on the Submit buttons (Submit, Next, Previous) because we will lose the programmed action on these buttons. You could code your own function to call the two functions but the problem here is that you don’t know what Formidable forms is doing on the submit actions.
The solution is to use a hook called frm_submit_button_action where we are going to call the javascript code.
This way, the code will be applied to each step and the radio buttons will be styled, even when we go back through the steps.
add_action('frm_submit_button_action', 'styleRadioButtons');
function styleRadioButtons($form){
... YOUR CODE ...
}
Bonus: change the last step title and description
We also needed to have a different title and description of the form in the next step in order to have a better message to make the user wants to fill and send the form.
The first part is to identify that we are on the last step of the form. We decided to do that by checking the color of the input element of the progress bar of the last step.
If the color is the one which means the step is complete, we :
- remove the description
- change the legend element
- change the title and add a sentence before and after the title
var bgStep5 = window.getComputedStyle(document.querySelector('input.frm_page_5')).backgroundColor
if(bgStep5 == 'rgb(110, 161, 81)') {
var legendElt = document.querySelector('#frm_form_2_container .frm_form_fields.frm_page_num_5 legend');
var h3Elt = document.querySelector('#frm_form_2_container .frm_form_fields.frm_page_num_5 h3.frm_form_title');
var descElt = document.querySelector('#frm_form_2_container .frm_form_fields.frm_page_num_5 .frm_description');
// Remove the description
descElt.parentNode.removeChild(descElt);
// Change the legend
legendElt.innerHTML = 'Thank you for your reply';
// Change the title
h3Elt.innerHTML = 'between 1,350$ and 2,700$';
// Insert a new introduction
var startElt = document.createElement('div');
startElt.classList.add('laststeptitledescription');
startElt.innerHTML = 'Thank you for your reply. Our clients save ';
var endElt = document.createElement('div');
endElt.classList.add('laststeptitledescription');
endElt.innerHTML = ' per year';
h3Elt.parentNode.insertBefore(startElt, h3Elt);
h3Elt.after(endElt);
}
The complete code
Add this code to the functions.php file.
add_action('frm_submit_button_action', 'styleRadioButtons');
function styleRadioButtons($form){
if($form->id == 2){
echo " ?>
<script>
var inputs = document.querySelectorAll('.frm_radio label');
for(var i=0;i<inputs.length;i++) {
inputs[i].addEventListener('click',function(){
for(var j=0; j<inputs.length; j++) {
inputs[j].parentNode.classList.remove('highlight');
}
this.parentNode.classList.add('highlight'); // put hightlight on the one clicked (this)
});
}
var input = document.querySelector('.frm_radio label input:checked');
if(input !== null && input !== '') {
input.parentNode.parentNode.classList.add('highlight');
}
var bgStep5 = window.getComputedStyle(document.querySelector('input.frm_page_5')).backgroundColor
console.log('couleur : ' + bgStep5);
if(bgStep5 == 'rgb(110, 161, 81)') {
var legendElt = document.querySelector('#frm_form_2_container .frm_form_fields.frm_page_num_5 legend');
var h3Elt = document.querySelector('#frm_form_2_container .frm_form_fields.frm_page_num_5 h3.frm_form_title');
var descElt = document.querySelector('#frm_form_2_container .frm_form_fields.frm_page_num_5 .frm_description');
// Remove the description
descElt.parentNode.removeChild(descElt);
// Change the legend
legendElt.innerHTML = 'Thank you for your reply';
// Change the title
h3Elt.innerHTML = 'between 1,350$ and 2,700$';
// Insert a new introduction
var startElt = document.createElement('div');
startElt.classList.add('laststeptitledescription');
startElt.innerHTML = 'Thank you for your reply. Our clients save ';
var endElt = document.createElement('div');
endElt.classList.add('laststeptitledescription');
endElt.innerHTML = ' per year';
h3Elt.parentNode.insertBefore(startElt, h3Elt);
h3Elt.after(endElt);
}
</script>
<?php ";
}
}
Resume
Despite all the impressive features of Formidable Form, they don’t allow to style buttons easily.
Multisteps forms are currently heavily used, especially with mobile devices.