In which we take a look at selection-dependent inputs, and see that they're a lot more simple to put together than they look.
Forms. They're often the bane of users' online lives. But it doesn't look like they're going away any time soon. So its up to us, UX designers, to make them as smooth and easy to use as possible for our users, while still reaching the best business outcomes.
If we prototype our forms, we can get them in front of users earlier and get feedback sooner, which we can use to iterate our designs. Previous posts in this series covered form layout and alignment, input types, and grouping and inline help.
In this, the fourth post in this series, we take a look at selection-dependent inputs. (I've also seen it referred to as "responsive enabling" and/or "responsive disclosure"). All this means is changing the fields that the user sees depending on some selection that they have made or some information that they have provided. For example, if we're asking the user for their postal address, we might have a field where they can enter (or select) the country that they live in. Then, depending on the country, we can change the other fields to match the standard address format for that country.
Note: "Responsive enabling" refers to having one or more fields that are disabled until the user makes a particular selection, in which case they become enabled, allowing the user to interact with them. "Responsive disclosure," on the other hand, hides the fields, and makes them appear if the user makes a particular selection. I don't recall seeing many forms that use responsive enabling of late, but I'm sure it's useful in some circumstances, so I'll include an example.
Responsive enabling
I think one of the reasons that this pattern has fallen out of favor in recent years is that it can be distracting. You have all these disabled fields, and they just take up space and draw the user's attention away from the stuff that matters unless they click on a particular checkbox (which may only be relevant for a small percentage of users).
One benefit is that things stay put. In you use responsive disclosure to make fields appear and disappear, the content below them suddenly jumps downward, which can be jarring and disorienting. But nowadays, it's easy to animate transitions like this, which can reduce the problem.
Anyway, in some cases, responsive enabling is going to be the right approach (where there aren't too many disabled fields, and where it would be confusing not to show them), so let's press on with an example.
In this example, we're going to let the user opt in to receiving text messages from us to let them know about special offers. You would typically find things like this at the bottom of an order form. We'll have a field where they can enter their mobile number, which will be disabled until they click the opt-in checkbox.
After you've set up a new Foundation project (this post explains how), add this HTML just after the opening <body>
tag. (We're not going to waste time prototyping the whole form—we'll just prototype the bit we're interested in.)
Somewhere within the page's <head>
tags, add this <style>
block:
The result looks like this:
What I've done here is not very complicated. Like in the previous posts, I've used Foundation's grid to lay out the form. In the second line of the HTML, I'm just squishing the form down into eight of Foundation's available twelve columns, and adding a two-column offset to center it on the page.
The first bit of actual content is a paragraph to show where the actual form fields and labels would go if this was a real form.
Then we've got a row containing a column that takes up all twelve columns. (small-12 columns
means it is twelve columns wide on small screen sizes and anything bigger, i.e., all screen sizes.) This contains the checkbox <input>
(with id
and name
) and its label (which uses for
to link it to the checkbox, so that you can click on it to toggle the checkbox too).
After that, there's another row that contains two columns, for the phone number <input>
and its <label>
. Notice how this divvies up the available space differently for small and medium (and bigger) screens.
For small screens, we've got a three/nine column split, so together they fill up all the available width. But on medium-and-up screens, they are three and six columns wide. This is to prevent the <input>
from being ridiculously wide on larger screens—Foundation makes each input 100% of the width of the column that it's in. (By default, if the number of columns doesn't add up to twelve, Foundation scoots the last column over so it is right-aligned. I've added the end
class to stop this happening.)
The label gets the right
class to right-align it, and the align
class to align it vertically with the <input>
. It also gets an ID so we can style it and do stuff to it. And the <input>
gets the appropriate type
(tel
) and the disabled
property to make it disabled initially.
The CSS in the <style>
block in <head>
just applies some styling to the placeholder text that shows where the real form fields would go and makes the "Mobile number" label grey so it looks disabled. (You can add the disabled
property to <input>
s, but not to <label>
s—you have to style these yourself so they'll look disabled.)
It looks OK so far. The phone number input is disabled, and its label looks disabled too. But it doesn't get enabled when you check the checkbox. For that, we need a bit of JavaScript. Not much, just a smidge.
At the bottom of the page, right before the closing </body>
tag, add this <script>
block:
This is pretty similar to what we saw in the last post. All the code is inside the jQuery $(document).ready()
function. So it will only get run after the page has finished loading.
Within $(document).ready()
, this part of the first line selects the checkbox:
that is, the element with the ID of cb
, then this part:
.on('change', function(){
calls the on()
function to detect when its state changes. The three lines within the curly braces ({}
) specify what happens when this change event is detected:
-
In the first line, this bit:
selects the label for the phone number field, which has an ID of mobilelabel
, then this bit:
calls toggleClass()
on it. This adds the disabled
class to the element if it doesn't already have it, and removes it if it does. This is the class that gives it the grey color, so removing it switches it back to its default color, black.
-
The second line declares a variable called checked
. Then this part:
selects the checkbox again and then checks whether it is checked or not like this:
This gives us an answer of true
or false
. The !
reverses this value. If it is true
, this makes it false
, and vice-versa. Then this value gets stored in our checked
variable. I'll explain why we need to reverse the value in a minute.
-
The third line selects the phone number input, which has an ID of mobile
, like this:
and calls prop()
on it to set the value of its disabled
property. And the value we give it is whatever we just stored in our checked
variable. This way, if the checkbox is checked, checked
gets a value of false
, which we use to set disabled
to false
. (Actually, I used trial and error to know whether I needed to reverse the value or not! I like to think of this kind of thing as being pragmatic.)
In fact, disabled
doesn't take a value—an element either has the property or it doesn't. But behind the scenes, jQuery correctly interprets us giving disabled
a value of false
and simply removes the property.
Now checking the checkbox enables the input, so it looks like this (and unchecking it disables it again):
You can see it in action here.
Responsive disclosure
For responsive disclosure, we're just going to take the previous example and change a couple of things. Here's the HTML:
The only changes that I've made here are to remove the disabled
attribute from the phone number <input>
and to remove the disabled
class from its <label>
. And I've added a new ID, mobile_container
, to the row <div>
that contains them so that I'll have something to attach behavior to.
The CSS is a bit different too:
Gone is the rule for styling the "disabled" label, and in its place is a rule that hides the row <div>
that contains the phone number input and its label by giving it a display
of none
.
As you can see, when the checkbox is unchecked, the phone number input and its label are nowhere to be seen:
To make them appear when you check the checkbox, we need to modify our JavaScript:
This is much simpler than it was before. All we've got now inside the function is one line, which toggles the visibility of the <div>
that contains the phone number field. Using the toggle()
function means that whenever the state of the checkbox changes, we either show or hide the phone number field. We don't have to check the value of anything, store things in variables, or any of that stuff.
Now when we check the checkbox, the phone number field appears:
(You can see a live example here.)
If we had additional content below these elements, it would jump down when the phone number field appears. It doesn't take up much space, so it doesn't jump very much. But imagine if what we were making appear was a whole sub-section of the form that takes up half the height of the page. Pushing the following content down by so much can be very disorienting.
It's worth taking a minute to look at how we can use animation to make changes like this more palatable. We'll add some more content after the phone number field, then add animation and see how it looks. Add another <div>
containing some text below the hidden one, so it looks like this:
Now let's change our JavaScript to include animation. Luckily, in this case, it is very easy indeed. All we need to do is replace the call to toggle()
with a call to slideToggle()
, so it looks like this:
Instead of just showing or hiding the element, slideToggle()
makes it appear by sliding it down from the top, or hides it by sliding it up. Try it out here.
We can control various aspects of how this animation happens. For example, we can make it faster or slower by putting a value (in milliseconds) in the parentheses, like this:
This example shows this slower version in action.
Another thing we can do is control the flow of the animation (what is referred to as its easing). By default, jQuery animations start out slow, speed up in the middle, then slow down again at the end. We can change this by doing something like this:
slideToggle({easing: easeInCubic})
Note that to use additional easings like this one, you need to include the jQuery UI library by adding these two lines near the bottom of the page (before the <script>
block that contains our code):
This starts off slow, like before, but speeds up and then doesn't slow down—it just stops abruptly, as if it had hit a wall. Try it here.
We're off on a bit of a tangent here, but I'll just show you one more before we move on to the next thing. There are 32 different easings available in jQuery, and each one gives the animation a slightly different feel.
For example, look what happens when we change the easing to easeOutBounce
:
slideToggle({easing: easeOutBounce})
Take a look here. Fun, isn't it?
More complex scenarios
Sometimes we are faced with more complex scenarios than just disabling or enabling part of a form, or showing and hiding it. Often these more complex scenarios involve replacing one set of inputs with another depending on what the user selects. The example that Luke Wroblewski uses in his book is a "contact me" form, where the user can choose to be contacted via email, phone, SMS, or IM. When the user makes a selection, the form changes to show just the relevant fields (email address for email, phone number for phone, and so on).
There are lots of different ways that a form like this could work. You could have the initial selection as tabs, with the appropriate form fields inside each tab. You could have a drop-down list for email, SMS, etc, with the form fields right below it. You could have radio buttons for the initial selection, with the relevant fields appearing either below the radio button group or below the selected option. You could even go with a progressive-enabling-style design, with a disabled set of fields after each radio button, with the appropriate set of controls being enabled when the user selects one of the options.
(And, of course, there are lots of other scenarios where one user selection changes something else. One that you see pretty often is two drop-down lists, where the first is for selecting a category and the second is for selecting a sub-category, or an item within the selected category. So on a site that lists second-hand cars, you might have one drop-down list for selecting the brand, and a second for selecting the model.)
I could show you how to prototype one of these, but that wouldn't help at all with any of the others. And if I were to show you how to prototype them all, you would soon lapse into a boredom-induced coma. So what to do?
Is there some common thread can we draw out of all these different scenarios? Maybe there's some technique can I show you that will be useful in prototyping all of these? Well, there isn't really. All I can do is give you some pointers, which will hopefully help you to avoid some wasted effort:
Be lazy.
There is the way that a proper programmer would do something, and then there are shortcuts. We're not writing production code here, so it doesn't matter if we cut corners. What matters is that it walks and quacks like the real thing. Or even just enough like the real thing to be moderately convincing. So going back to the example I just gave of a pair of drop-down lists, the proper way to build something like this would be to populate the first list dynamically using a list of car brands that you request from the server. Then, when the user selects a brand, you would make another server request for the list of models for the brand, and use that to dynamically build up the list.
But for a prototype, you might not even need all the possible car brands and their models. It might be enough to have half a dozen brands, and a few models for each. And instead of dynamically populating each <select>
element with the appropriate <option>
s, you can put six separate <select>
s in yout HTML, one for each brand, hide them all to start with, and just use JavaScript to show the right one depending on the brand that the user selects.
Learn a few key things in JavaScript/jQuery.
You don't need to know everything there is to know about JavaScript and jQuery to be able to do useful stuff with it. The ones I find myself using most often are:
-
Event handlers. Mostly, this means using jQuery's on()
function to detect when the user does something to some element, and performing some action when they do.
-
Chaining. Every function gives you something when it's done. (In programming parlance, it "returns" it.) You can then do something with the thing it returns. So if you call the find()
function on an element like this:
$('#myelement').find('li');
find()
returns the <li>
element that it found (if there was one within #myelement
for it to find). So then you can do stuff to the <li>
by chaining another function on the end, like this:
$('#myelement').find('li').hide();
hide()
returns the element that it just hid, so you could, if you wanted, tack on yet another function to the chain to do something else to it. (But we won't.)
-
Simple conditional branching. The if
and if ... else
constructs let you ask "is this thing true", and if it is, to perform some action. (else
lets you do something else if it isn't true.)
-
Slightly less simple conditional branching. When you've got something that can have multiple different outcomes, each with a different action to be performed, if
becomes an overly-complicated way of doing things. The JavaScript switch
statement is perfect in these situations. It's ideal when you've got something like a drop-down list with several options, and you want to do a different thing for each selected option.
-
Making stuff appear and disappear. We can use show()
, hide()
, and toggle()
, as we've seen, to make stuff appear and disappear. And we can either supply additional arguments to these functions to animate them (and to control things like the speed and direction of the animation) or use special functions like slideUp()
and slideDown()
(and slideToggle()
, which we saw above) to do the same thing. There's also the animate()
function, for when we want full control over every aspect of an animation.
Look stuff up.
The jQuery documentation is pretty good. If you know the name of the function you're trying to use, it tells you everything you need to know about how to use it. And if you don't know which function you need, it has category pages that list all the functions for, for example, getting from one element to another, or for inserting, removing, and manipulating elements. (Note that jQuery is an addition to JavaScript. Some things, like if
and switch
, are part of JavaScript, not jQuery, so you won't get very far searching for them in the jQuery docs.) And if you Google for the thing you're wrestling with, you'll usually end up at Stack Overflow, the Q&A site for programmers. 99.9% of the time, your question will have already been asked and answered. For example, I wanted to know the correct way to find out if a checkbox is checked or not. So I Googled jquery checkbox get value, clicked the first result, and got the information I needed from the top answer. Easy-peasy.
Don't be afraid of doing it "wrong".
For anything you want to do, there are going to be several (even many) different ways to do it. Does it matter which one you choose? For a (disposable) prototype, it doesn't. The only thing that matters is: does it work or not? If it works, it's "right". I'm sure a "real" programmer would take one look at most of my prototype code and snicker to himself under his beard. But it serves the purpose for which it is intended, so it doesn't matter.
Having said that, I do have a couple of examples that you can take a look at. The first shows a different form depending on what you select in a drop-down list. The second changes the contents of one drop-down list depending on what you select in another. Use the View Source option in your browser to see how they work—they don't do anything particularly clever.
Conclusion
Changing parts of a form depending on what the user selects is pretty powerful. We can use it to hide complexity from the user and make our forms more simple to use. It means we need to learn a bit of JavaScript, but we can do a lot with a little. I think it's well worth the effort.
This was originally published on Boxes & Arrows on 27 May 2014.
If you liked this post, you should really check out my upcoming book, Prototyping Forms. Just like this, only more and better!