Join James Williamson for an in-depth discussion in this video Creating responsive inputs and labels, part of Building Responsive Forms with Flexbox.
- It's now time to start making our form responsive. We'll start by using Flexbox to make our text inputs and labels responsive. So currently, our form isn't responsive at all. What I'd really like is if these text inputs would flex, or stretch, to fit more of the width of their container, and I'd love it if I made the size of it smaller. At a certain point, it'd be nice if the labels would stack on top of the form elements, instead of trying to remain beside them. As you can see, it creates kind of a mess. So to do that, I'm going to jump back into the forms.htm file this time, found in the 02-04 directory.
And before we go into writing our styles, I want to take a closer look at the structure of our form and get a feel for how we're going to do this. So you'll notice that all of our different form elements are typically grouped in an unordered list. In this case, the top here, you'll see we have an unordered list with a class of form-fields. Inside that, we have the individual list items themselves, and inside the list item, there is a label and an input, in this case, a text input. That's repeated all the way throughout the form.
Now that means we can take advantage of the structure, and if we made these list items, for example, flex containers, that means that the labels in the inputs themselves will be flex items. So having this sort of repeating structure, and consistent structure, makes it a lot easier to use Flexbox. So if I scroll back up just a little bit into the head of my document, I can see right down here, I've got another little comment that says flex it, and that's where we're going to write all of our Flexbox styles. Now we certainly could integrate all of our styles together.
Now I really like sort of segregating the layout styles down here by themselves, because it allows us to focus on the layout itself. It also shows us how very little code is required using Flexbox to achieve some pretty complicated results. So the first thing I'm going to do is write a selector that targets those list items. Every unordered list that we want to target that uses these text input fields uses a class name of form-fields. So I'm going to start with that. So I'm going to do .form-fields li so that's going to target all of the list items inside of any unordered list with the class of form-fields.
Inside that, I'm going to change the display to flex, and I'm going to set flex-wrap to wrap so that when space allows, they can appear side-by-side, but if not, I want those flex items to wrap. Now if I save this and refresh my window, there's a slight change. You may have noticed that the labels now sort of line up towards the top of the form elements instead of in the middle, but if I resize them, we don't really get any wrapping or anything going on, and that's because we really haven't constrained their size at all or told them sort of how to fit within that space.
So we're going to do that by styling the individual elements themselves. Going back into my code, I need to write a selector that targets all those form input types. Now I could certainly write it from scratch, but I kind of have one already, and so instead of rewriting this all over again, I'm just going to copy the same selector that I've used up here, so it's the selector that targets all of these different input types, and then I'll just paste it in here all by itself. So essentially, it's a group selector that targets all of these different input types as well as the select element.
Inside the selector, I'm going to set the flex property for these flex items to flex grow of one, flex shrink of zero, and then I'm going to give it a flex basis of 230 pixels. So remember, 230 pixels is the size that it's going to start at. Because we have wrap turned on, it's not going to get any smaller than that. So it's almost like a minimum width, if you will. But I've told it I do want it to flex, so go ahead and take up any remaining available space. Now underneath that, I need to target the labels.
So I'm going to type in .form-fields label and that's going to target the individual labels themselves. And inside that, I'm also going to set the flex properties. So here we're going to do flex, we're going to do one for flex grow, so we're going to tell the labels it's okay if you stretch. Now it's not going to stretch the text. It's going to stretch the element itself. Flex shrink is going to be zero. And flex basis, it's going to be 90 pixels. Now you may be wondering where I got those values from. Well, think about 230 plus 90.
That's going to give me a total width of 320 for those two elements if they're side-by-side. 320 is kind of the smallest grain size that I might want to target, or smallest viewport. When I'm thinking about devices, 320 pixels wide is really small. And it's older series phones, things like that, might be at 320 pixels. So I'm really thinking about, what's the smallest size that these might need to go down to. All right, so if I save this, go back into Firefox and refresh, you can see that a dramatic change occurs in our form.
Notice the form, the text input fields themselves, stretch, so they're flexible now. They're all the same size, which is beautiful. And then our labels are stretching as well. Now it doesn't really appear like they are, but if we had a background color applied to them, the background color would stretch all the way to the inputs themselves. Now at smaller sizes, this is really kind of nice, you can see, and at still smaller sizes, you'll notice we get to a certain size, and it triggers that wrapping, because the 230 pixel wide text inputs can no longer fit side-by-side with the labels at 90 pixels.
When that occurs, it goes ahead and wraps. And now the labels appear on top of the text inputs instead of beside them. The one downside to that is at really wide screen widths, like we have here at 1280 pixels, there's this really sort of unnecessary space in between them, and there's a really easy way to fix this. Currently we're telling our labels and our input text fields to flex at a one-to-one ratio. So we're saying, I want you each to take up and grow into the available space of the parent, and share that equally at one-to-one.
Now I could mess around with ratios all day long and finally get it to where I want it, but I don't really know ever how big somebody's monitor might be. And to come up with a ratio that's going to look great across all different monitor sizes or screen resolution sizes, is pretty difficult. So what I'm going to do is just set a maximum width for the label. So I'm telling the label, yeah, you can go ahead and grow the space you're in, but I don't want you to grow any taller than X. And when that happens, the text input fields will go ahead and take up the rest of the space. So if I go back into my label selector, underneath the flex property, I'm going to go ahead and set a maximum width.
And I'm going to set the maximum width to 200 pixels. Now again, I didn't just come up with that. I tested it, and I found the width that I thought fit the best. So I'm going to go ahead and save that. Go back into Firefox, and now when I refresh, notice that the inputs grow to take up the remaining space, and the labels are only 200 pixels wide. As we shrink our size down, that's certainly much more realistic, and we still get that nice break based upon the flex basis size of the labels and the text inputs themselves.
Okay, so that's really three lines of code that takes care of all of our text inputs and their labels. And next up, we're going to tackle a slightly more tricky element type as we make our checkbox groups responsive.
In this course, senior staff author James Williamson shows how to use flex containers, flex child items, and responsive design techniques to create responsive layouts for two forms: a short search form and a longer registration form with sections. He demonstrates how to style the form structures, fields, labels, and buttons; control the alignment of different elements; and enhance the responsiveness of both forms with media queries.