• Home
  • blog
  • Quick Tip: Style Form Elements With Pseudo Selectors

Quick Tip: Style Form Elements With Pseudo Selectors

Category: Articles, CSS3, Tip

Ever since CSS was invented, web developers everywhere have wished for a way to style the built-in browser controls. This is straightforward for simple elements like buttons and text inputs, but difficult for some of the more complex elements like select and range. In this quick tip, we will show you how to do it.

Why pseudo selectors?

There is no standard way for customizing the appearance of the built-in browser elements yet. For example, the search input shows a small “x” witch you can press to cancel your search. This is implemented as a separate element internally, but you can’t reach it with regular CSS. Browser makers have taken notice, and they’ve added vendor specific selectors that you can use. For that “x”, the selector to use is input[type=search]::-webkit-search-cancel-button.

There is a huge list of the known selectors here. All browsers provide some selectors for customizing built in elements, but the bad news is that support is all over the place. Hopefully in the future there will be a standard that brings consistency to this mess. For now though, we have to target each browser individually.

If you use Google Chrome, there is an easy way to find out which selector you’re supposed to be using. After you enable Shadow DOM support, you can see the internal structure of the built in browser elements. Here is how to do it, as taken from our Chrome DevTools Tips and Tricks article:

 Shadow DOM

Shadow DOM

Open up the developer tools and go to Settings. There, in General, under Elements check Show user agent shadow DOM. Now when you inspect elements you will see their #shadow-root. When you select an element in the #shadow-root, in the Styles tab you will see which selectors are used by the user agent stylesheet to style them. Most of the time this is the selector you are looking for.

Keep in mind that most of the following experiments only work in Chrome and Safari. Firefox and IE don’t support many of the pseudo selectors that are necessary to customize built-in elements, so they show the regular versions. Someday when we have standards in place, customizations like these will work everywhere.

1. Checkboxes

There is not a lot you can do with checkboxes in CSS, apart from giving them a width and height. But Chrome and Safari support :before and :after pseudo elements on inputs, so you can have some fun. Notice that the check mark is made entirely with CSS and is even animated with a fade in transition.

By setting -webkit-appearance to none, we prevent the default browser style from being applied, which leaves the doors open to our custom CSS. Also thanks to the em units, we made the checkbox scale with the font size of its parent. Try increasing it.

(Play with our code editor on

2. Radio Buttons

We can use the same technique on radio buttons. Here it is simpler, as we don’t need to make a check mark out of CSS. This still only works in Chrome and Safari. Other browsers display the regular radio button.

(Play with our code editor on

3. Select Elements

The select element is notoriously difficult to style with CSS. Even today we are limited to what we can change. To customize the downward arrow, we can use a background image and a bit of padding. For the dropdown list you can specify a font size and a background on the option elements, but not much more.

(Play with our code editor on

4. Range elements

Range is one of the newer form elements supported by browsers. It also is one of the most customizable. Chrome, Safari and Firefox all give us a large number of CSS pseudo selectors that we can use to style specific parts of the element. Even IE has support for some, although we haven’t implemented them in our example. See this list to learn what is available.

(Play with our code editor on

5. Progress Bars

The progress element also gives us a good deal of customizability. Although for a simple element like this, you could just as easily nest two divs and make your own version.

(Play with our code editor on


It is great that we can finally modify the built-in browser controls, but there is still a long way to go in terms of standardization. Google Chrome is a clear leader here, and if you write Chrome apps or extensions you can go ahead and use everything that we showed here. But if you want consistent cross-browser support, the best solution is still relying on JavaScript libraries and jQuery plugins like Chosen.