Exposing Additional Form Fields via Checked Radio Buttons

There is a :checked pseudo class in CSS. I often think of it in connection with the “checkbox hack”, in which you use it on a hidden checkbox with the ~ general sibling combinator to do simulate toggling behavior without any JavaScript. It’s a hack because now you have these stray form elements on the page that really aren’t for a form. Not a huge deal, as I’m sure you can work around it accessibility wise, but there is a way to use this same concept in a totally non-hacky way, on an actual form!

I used this technique on the CodePen job posting form to only reveal additional form fields as needed.

Let’s get to the point with a demo:

The HTML

Let’s say we’re using radio buttons here. Either a checkbox or a radio button can be “checked” (:checked). The div we’re going to reveal has to be after it, and a sibling element (within the same parent).

<input type="radio" name="choice-animals" id="choice-animals-dogs">
<label for="choice-animals-dogs">I like dogs more</label>
    
<div class="reveal-if-active">
  Anything you want in here.
</div>

The CSS

By default, that “reveal-if-active” div will be hidden. We’re going to do that in a number of different ways. They aren’t all required just to hide it, but they will play a factor in how it reveals itself.

.reveal-if-active {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

Now when a radio button or checkbox at the same level as it becomes checked, it reveals:

input[type="radio"]:checked ~ .reveal-if-active,
input[type="checkbox"]:checked ~ .reveal-if-active {
  opacity: 1;
  max-height: 100px; /* little bit of a magic number :( */
  overflow: visible;
}

That works, but let’s transition everything fancy style, and Sass it up:

.reveal-if-active {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transform: scale(0.8);
  transition: 0.5s;
  input[type="radio"]:checked ~ &,
  input[type="checkbox"]:checked ~ & {
    opacity: 1;
    max-height: 100px;
    overflow: visible;
    padding: 10px 20px;
    transform: scale(1);
  }
}

That’ll do the trick.

What about required fields?

This gets a little tricker. Let’s say in the “reveal-if-active” divs you’re putting more form fields (that’s the whole point really). You might want to require a field if it’s revealed, but not if it’s not. A required field that is hidden is still required, and so you can’t just put the required attribute on those hidden fields and forget about, lest get yourself in a nasty UX situation.

I handle this by putting a “require-if-active” class on the input, and a data-* attribute which references the ID it’s paired with.

... 

<div class="reveal-if-active">
  <label for="which-dog">Good call. What's the name of your favorite dog?</label>
  <input class="require-if-active" type="text" id="which-dog" name="which-dog" data-require-pair="#choice-animals-dogs">
</div>

Then, when the page loads, and whenever a checkbox or radio button changes value, you run some JavaScript to determine whether that input should be required or not.

var FormStuff = {
  
  init: function() {
    // kick it off once, in case the radio is already checked when the page loads
    this.applyConditionalRequired();
    this.bindUIActions();
  },
  
  bindUIActions: function() {
    // when a radio or checkbox changes value, click or otherwise
    $("input[type='radio'], input[type='checkbox']").on("change", this.applyConditionalRequired);
  },
  
  applyConditionalRequired: function() {
    // find each input that may be hidden or not
    $(".require-if-active").each(function() {
      var el = $(this);
      // find the pairing radio or checkbox
      if ($(el.data("require-pair")).is(":checked")) {
        // if its checked, the field should be required
        el.prop("required", true);
      } else {
        // otherwise it should not
        el.prop("required", false);
      }
    });
  }

};

FormStuff.init();

Yep, little JavaScript required. We could do the hide/showing through JavaScript as well, but CSS is quite well suited for it. You might even say it’s a design concern, so it belongs in CSS.

 

We will be happy to hear your thoughts

      Leave a Comment

      Web Training Guides
      Compare items
      • Total (0)
      Compare
      0