Is there a CSS-only way to style a <select>
dropdown?
I need to style a <select>
form as much as humanly possible, without any JavaScript. What are the properties I can use to do so in CSS?
This code needs to be compatible with all major browsers:
I know I can make it with JavaScript: Example.
And I'm not talking about simple styling. I want to know, what the best we can do with CSS only.
I found similar questions on Stack Overflow.
And this one on Doctype.com.
There are many ways to design a <select> dropdown menu using CSS. The Dropdown Menu is mainly used to select an element from the list of elements. Each menu option can be defined by an <option> element that can nested inside the <select> element.
To change the selected option background-color CSS style, we can set the style attribute of the select and option elements. to set the whole select element to background color 009966 and color FFF . Then we override the the styles in the option elements with style="background: white; color: black;" .
Here are three solutions:
Solution #1 - appearance: none - with Internet Explorer 10 - 11 workaround (Demo)
--
To hide the default arrow set appearance: none
on the select element, then add your own custom arrow with background-image
select { -webkit-appearance: none; -moz-appearance: none; appearance: none; /* Remove default arrow */ background-image: url(...); /* Add custom arrow */ }
Browser Support:
appearance: none
has very good browser support (caniuse) - except for Internet Explorer.
We can improve this technique and add support for Internet Explorer 10 and Internet Explorer 11 by adding
select::-ms-expand { display: none; /* Hide the default arrow in Internet Explorer 10 and Internet Explorer 11 */ }
If Internet Explorer 9 is a concern, we have no way of removing the default arrow (which would mean that we would now have two arrows), but, we could use a funky Internet Explorer 9 selector.
To at least undo our custom arrow - leaving the default select arrow intact.
/* Target Internet Explorer 9 to undo the custom arrow */ @media screen and (min-width:0\0) { select { background-image:none\9; padding: 5px\9; } }
select { margin: 50px; width: 150px; padding: 5px 35px 5px 5px; font-size: 16px; border: 1px solid #CCC; height: 34px; -webkit-appearance: none; -moz-appearance: none; appearance: none; background: url(https://stackoverflow.com/favicon.ico) 96% / 15% no-repeat #EEE; } /* CAUTION: Internet Explorer hackery ahead */ select::-ms-expand { display: none; /* Remove default arrow in Internet Explorer 10 and 11 */ } /* Target Internet Explorer 9 to undo the custom arrow */ @media screen and (min-width:0\0) { select { background: none\9; padding: 5px\9; } }
<select> <option>Apples</option> <option selected>Pineapples</option> <option>Chocklate</option> <option>Pancakes</option> </select>
This solution is easy and has good browser support - it should generally suffice.
If browser support for Internet Explorer is needed, read ahead.
Solution #2 Truncate the select element to hide the default arrow (demo)
--
(Read more here)
Wrap the select
element in a div with a fixed width and overflow:hidden
.
Then give the select
element a width of about 20 pixels greater than the div.
The result is that the default drop-down arrow of the select
element will be hidden (due to the overflow:hidden
on the container), and you can place any background image you want on the right-hand-side of the div.
The advantage of this approach is that it is cross-browser (Internet Explorer 8 and later, WebKit, and Gecko). However, the disadvantage of this approach is that the options drop-down juts out on the right-hand-side (by the 20 pixels which we hid... because the option elements take the width of the select element).
[It should be noted, however, that if the custom select element is necessary only for mobile devices - then the above problem doesn't apply - because of the way each phone natively opens the select element. So for mobile, this may be the best solution.]
.styled select { background: transparent; width: 150px; font-size: 16px; border: 1px solid #CCC; height: 34px; } .styled { margin: 50px; width: 120px; height: 34px; border: 1px solid #111; border-radius: 3px; overflow: hidden; background: url(https://stackoverflow.com/favicon.ico) 96% / 20% no-repeat #EEE; }
<div class="styled"> <select> <option>Pineapples</option> <option selected>Apples</option> <option>Chocklate</option> <option>Pancakes</option> </select> </div>
If the custom arrow is necessary on Firefox - prior to Version 35 - but you don't need to support old versions of Internet Explorer - then keep reading...
Solution #3 - Use the pointer-events
property (demo)
--
(Read more here)
The idea here is to overlay an element over the native drop down arrow (to create our custom one) and then disallow pointer events on it.
Advantage: It works well in WebKit and Gecko. It looks good too (no jutting out option
elements).
Disadvantage: Internet Explorer (Internet Explorer 10 and down) doesn't support pointer-events
, which means you can't click the custom arrow. Also, another (obvious) disadvantage with this method is that you can't target your new arrow image with a hover effect or hand cursor, because we have just disabled pointer events on them!
However, with this method you can use Modernizer or conditional comments to make Internet Explorer revert to the standard built in arrow.
NB: Being that Internet Explorer 10 doesn't support conditional comments
anymore: If you want to use this approach, you should probably use Modernizr. However, it is still possible to exclude the pointer-events CSS from Internet Explorer 10 with a CSS hack described here.
.notIE { position: relative; display: inline-block; } select { display: inline-block; height: 30px; width: 150px; outline: none; color: #74646E; border: 1px solid #C8BFC4; border-radius: 4px; box-shadow: inset 1px 1px 2px #DDD8DC; background: #FFF; } /* Select arrow styling */ .notIE .fancyArrow { width: 23px; height: 28px; position: absolute; display: inline-block; top: 1px; right: 3px; background: url(https://stackoverflow.com/favicon.ico) right / 90% no-repeat #FFF; pointer-events: none; } /*target Internet Explorer 9 and Internet Explorer 10:*/ @media screen and (min-width: 0\0) { .notIE .fancyArrow { display: none; } }
<!--[if !IE]> --> <div class="notIE"> <!-- <![endif]--> <span class="fancyArrow"></span> <select> <option>Apples</option> <option selected>Pineapples</option> <option>Chocklate</option> <option>Pancakes</option> </select> <!--[if !IE]> --> </div> <!-- <![endif]-->
It is possible, but unfortunately mostly in WebKit-based browsers to the extent we, as developers require. Here is the example of CSS styling gathered from Chrome options panel via built-in developer tools inspector, improved to match currently supported CSS properties in most modern browsers:
select { -webkit-appearance: button; -moz-appearance: button; -webkit-user-select: none; -moz-user-select: none; -webkit-padding-end: 20px; -moz-padding-end: 20px; -webkit-padding-start: 2px; -moz-padding-start: 2px; background-color: #F07575; /* Fallback color if gradients are not supported */ background-image: url(../images/select-arrow.png), -webkit-linear-gradient(top, #E5E5E5, #F4F4F4); /* For Chrome and Safari */ background-image: url(../images/select-arrow.png), -moz-linear-gradient(top, #E5E5E5, #F4F4F4); /* For old Firefox (3.6 to 15) */ background-image: url(../images/select-arrow.png), -ms-linear-gradient(top, #E5E5E5, #F4F4F4); /* For pre-releases of Internet Explorer 10*/ background-image: url(../images/select-arrow.png), -o-linear-gradient(top, #E5E5E5, #F4F4F4); /* For old Opera (11.1 to 12.0) */ background-image: url(../images/select-arrow.png), linear-gradient(to bottom, #E5E5E5, #F4F4F4); /* Standard syntax; must be last */ background-position: center right; background-repeat: no-repeat; border: 1px solid #AAA; border-radius: 2px; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); color: #555; font-size: inherit; margin: 0; overflow: hidden; padding-top: 2px; padding-bottom: 2px; text-overflow: ellipsis; white-space: nowrap; }
When you run this code on any page within a WebKit-based browser it should change the appearance of the select box, remove standard OS-arrow and add a PNG-arrow, put some spacing before and after the label, almost anything you want.
The most important part is the appearance
property, which changes how the element behaves.
It works perfectly in almost all WebKit-based browsers, including mobile ones, though Gecko doesn't support appearance
as well as WebKit, it seems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With