Accessible CSS-Only Floating Labels

Looks matter, but accessibility does too.

Floating labels are a simple design pattern that can help make your forms livelier and more dynamic, in the right conditions. Today we will be looking at how to make CSS-only floating labels without losing readability by accessibility tools.

Image for post
Image for post
CSS-Only Floating Labels

Our final result

Here is the Codepen (there is an advanced, prettier version at the end, so keep on reading).

Image for post
Image for post

Our HTML

We will set up our form in such a way where both our <input> and <label> tags are in the same container. It is of utmost importance that our <label> comes our <input>. We will add a . class to our container to work our CSS with it, and add a property to our inputs.

To make it accessible, we make sure our inputs have the property and our labels have the property set for their specific input, so that screen readers have no trouble processing our markup.

Image for post
Image for post
Our markup

And that’s it ! That’s all we need for our markup. (I know our Codepen version is prettier, but we’ll keep it simple here).

Our CSS

Like my mother would say, “¡Achis Achis Los Mariachis!”. Here comes the “difficult” part. It is not difficult at all but it requires some CSS knowledge, and that’s why we are here.

We style our input however we want. For this input I went for a single bottom-border thin line. I fix the height on the vertical padding plus the font-size so our input stays put.

Image for post
Image for post
Input’s basic CSS

Next, we add the basic styling to our label. For this demo, we will set a 12.5px font size.

Image for post
Image for post
Label’s basic styling

Next, using our .selector, we set “position: relative;”. This is important because we will position our label with “position: absolute; for the transform.

We position our label on the middle with using the selector and the “top: calc(50% + );” property. The opacity is also needed so that the label only shows after the the user has inputed text, and we add a transition for a nicer effect.

The next two selectors are what make most of the magic work:

Remember we had a 20px padding on top and a 20px padding on bottom (40px sum) of our input? Well, we are going to shift the padding so that our input size remains the same, while we make a safe space for the label to be floated on.

We use the selector to set the new padding when the placeholder is not shown. We’ll set 28px on top and 12px on bottom (still adds to 40 pixels).

Finally, when the label is not shown, we will also select the adjacent label to change its opacity and transform its vertical position, with the selector.

Image for post
Image for post
Floating label styling

And that’s pretty much it ! You can get a lot more creative with selectors. We will cover it in the next section.

Advanced version

Lets get creative now! We can do even better stuff with SVGs:

Image for post
Image for post
The GIF

Codepen here

In this version I only added a .icon container with an inline SVG. We absolutely position the SVG inside the parent container

Image for post
Image for post
New markup for our icon

Now lets take a look at our advanced styles. This time I’ll be using SCSS:

Here we add an .icon class to our styles. We will be using position: absolute; for our icon container, and set it to top: 0 and left: 0. We will set an arbitrary width, and the same height as our input, as well as initial styles.

We will set a width for our form, say 300px, and an input width of “calc(100% - )”.

Image for post
Image for post
New styles for our icon

Next, when our placeholder is hidden, we transition the values in our SVG to full opacity, and to match our primary color.

Image for post
Image for post
Our SVG transition

This makes our icons look toned down when no input is on the field. And also makes them look “on” when there is a value in our input.

Image for post
Image for post
The Screenshot

Not the end...

We could actually 1up this form, and make it even better. Want the icon to ONLY show when the input’s value is valid? Then chain a :valid selector:

Image for post
Image for post
Turning our icon on ONLY when there is a valid value in our input.
Image for post
Image for post
Image for post
Image for post
Non-valid input vs valid input

This will make our input[type=“email”] to only lit up when there is a valid value on our field.

STILL NOT THE END

Want to SLAAAAAAAY the CSS game? We will now add behavior, CSS only. When our field gets unfocused, we will SHAKE our email icon so that it indicates an invalid value.

Easy-peasy: We chain an input:not(:valid):not(:focus) + label + icon selector to shake our input when we lose focus and has no valid value.

Image for post
Image for post
Shake our icon when our input has an invalid value.

BOOM. There we have it. Not a single line of JavaScript was written today.

Image for post
Image for post
There we have it !

Our advanced Codepen link, again. :)

The Not End

With a little bit of knowledge you can make nice designs, interactions and animations without JavaScript.

Thanks for reading!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store