CSS to the rescue: Improving UX in forms

Lately webmaster and web designer are obsessed about User Experience and how to improve it. Tasks such as reducing the website loading time or finding a good font combination are always in the to-do list. However we are forgetting about focussing on the elements where the real contact between the user and the website happens: the forms.

Designing pages and sections with contact forms properly is challenging because you have to guide your users through each field to get them filled correctly. Moreover, if the info added by the user doesn’t fit the field’s pattern, you should let the user know what he/she is doing wrong. And this has to be clear for all users, included non-tech visitors.

Fortunately, new HTML5 specs for forms have helped to improve the validation before sending the form without using server-side requirements nor JavaScript. By default inputs type like email or tel (telephone) use a pattern that checks that the info filled is correct and forms can be submitted when the user clicks on the submit bottom.

The key questions are: Could we improve this behaviour getting a live check? Could we also get an extra info about how to fill out a form if we get stuck? Does this help get a better UX? Yes to all, and we will do it with CSS.

Knowing CSS pseudo-class and HTML elements and attributes to improve a form

Improving UX in forms with CSS
Demo with some inputs (text, mail and url) with different patterns and placeholders

Let’s revise some CSS pseudo-class and HTML elements we are going to use in our demo. Some of them are very well-known but others have been added recently in the last CSS updates.

input and textarea

The classics. They will define the fields the users are going to fill out. The typology of input is defined by the type attribute in the HTML, and this is important, as we said above, for custom HTML5 browser validation

<input type="text"> <!-- for name and surname -->
<input type="email"> <!-- for email -->
<input type="url"> <!-- for website -->


This HTML attribute can be used with input and textarea. It indicates that the field should be filled out before the form is submitted. It is very useful to let user know that we need that information, for example the email or the phone number.

<input type="email" required>

The required attribute is directly related with two pseudo-classes we can use through our CSS to know if the input is required or optional. They are :required y :optional, vary semantic as you can see.


Another HTML attribute to check the information added by users. In that case we can build our own pattern or use one of the patterns by default. It depends on the type attribute. For example, if we use the email type, it will looking for an email string (with @ in the middle and a valid domain extension such as .com, .org or whatever.) The same for tel or url. Here you have the complete list of input type attributes.

HTML forms with CSS to improve UX
Styling an HTML form is challenging. Colours should not be only decorative but offer a real User Experience improvement.

However, the power of this attribute is that we can create our own pattern, excluding numbers for instance or any character we want to avoid. The pattern attribute requires a regular expression in order to work properly.

<input type="text" pattern="^[^0-9]+$" required>


The most useful attribute in this collection for UX. It helps user to understand what kind of info we are looking for. It can also display an example data that will disappear when the user starts filling out the input (typing a character) and not when the input is :focus.


Pseudo-element related with above attribute. It helps us style the placeholder, so we can change the text colour or other font properties to let users know that this is an example and not a real text.

Placeholder in HTML forms
Simple placeholder with “name*” text.

Browser compatibility is good enough, however, we can add some alternative prefixed rules for each browser: ::placeholder, ::-moz-placeholder, ::-webkit-input-placeholder and :-ms-input-placeholder.


A basic pseudo-class that runs when the user is focusing an input or textarea. It is necessary that the user click on it or navigate with the keyboard to considerate the input as focused.


This pseudo-selector will let us know if the string added in the input is correct and check with the pattern we have set. So basically we can style the input if the info is correct.


The opposite of valid. The question here is: What happens when no value is added to the input? Will it be :valid or :invalid? Well, the answers in that case depends on the required attribute. If it exists for that input and no value has been added, then is an :invalid element. Otherwise it will be :valid.

Valid vs invalid CSS pseudo-selectors in forms
Difference between :invalid and :valid CSS pseudo-selectors


The new kid in town. It is still in the draft of CSS level 4 specification, but the compatibility with browsers is quite reliable at this moment (except on IE and Edge).

This is a pseudo-class that runs only when placeholder is being shown. It means that it will be enabled when the input is not focused and when it is focused but the user has not typed any character yet.

So the possibilities here are thrilled. Now, we can know if users get stuck in one of the inputs. For example, if an user has clicked on an input but doesn’t know what to write, we can show a notice after 5 seconds that helps the user complete it, and all of this only with CSS!

Another possibility: the user is filling the input, but 30 second has passed and the input is still invalid. Maybe the user has not understand what pattern we are looking for. Time to help with a message or something similar!

Different states for an input element
Showcase of different styles an input element can have.

Putting in practice. A form with CSS validation

For this example we have built a simple form with some inputs (two text type for name and surname, an email type and finally an url type) and a textarea. It could be valid for a blog comment section or a short contact form.

There are four required elements (all of them except the url because maybe the user doesn’t have a website) and some placeholders with the information we are looking for. Easy.

As you can see in the example, when you click on an element, the placeholder disappears and the field keeps empty waiting for your data. To help users remain where they are, we have set the label element above the user data, as a “false” placeholder.

To help user recognise if the data added is correct, we have used the classic colour palette of green-correct and red-invalid. The border colour of the inputs will change to red or green depending on the string, and when users will move on other input, the background will be filled with soft green or red.

Finally, we have used some CSS animations to show a notice if the user gets stuck. We can know this using a combination of :valid, :focus and :placeholder-shown. The animation is quite simple: it shows the text after x seconds. We encourage you explore the example filling out the form with some wrong data or just keeping still to see how the form react and try to help you.

We hope this article help you to design and build forms with a solid UX. Let us know your thoughts and questions in the comment section. Good CSS-luck!

Leave a Reply

Your email address will not be published. Required fields are marked *