Skip to content
Fix Code Error

How do I style a dropdown with only CSS?

March 13, 2021 by Code Error
Posted By: Anonymous

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:

  • Internet Explorer 6, 7, and 8
  • Firefox
  • Safari

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.

Solution

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) {
    select {
        background-image:none9;
        padding: 5px9;
    }
}

All together:

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) {
    select {
        background: none9;
        padding: 5px9;
    }
}
<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).

Enter image description here

[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) {
  .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]-->
Answered By: Anonymous

Related Articles

  • In CSS Flexbox, why are there no "justify-items" and…
  • Generate a random point within a circle (uniformly)
  • Setting up EmberJS project directory structure?
  • How many files can I put in a directory?
  • Drop-down menu that opens up/upward with pure css
  • What does do?
  • Simple dynamic breadcrumb
  • Reference - What does this regex mean?
  • Excel formula to get ranking position
  • What are the currently supported CSS selectors…
  • Use of Jquery on scroll event
  • How to prevent scrolling the whole page?
  • Why is it that "No HTTP resource was found that…
  • Running Internet Explorer 6, Internet Explorer 7,…
  • Trying to keep dropdown menus flush to the edge of…
  • How to configure postgresql for the first time?
  • Remove HTML tags from string including &nbsp in C#
  • Cannot make table responsive
  • How to implement a Navbar Dropdown Hover in Bootstrap v4?
  • Reference — What does this symbol mean in PHP?
  • Is it possible to apply CSS to half of a character?
  • Adding Dynamic Input Fields With VueJs
  • Hide one dropdown in side menu when another opens
  • HTTP Status 500 - org.apache.jasper.JasperException:…
  • Check for special characters in string
  • Navbar not filling width of page when reduced to mobile view
  • Using CSS for a fade-in effect on page load
  • Replacing a 32-bit loop counter with 64-bit…
  • Use latest version of Internet Explorer in the…
  • Bootstrap 4: Multilevel Dropdown Inside Navigation
  • How to downgrade from Internet Explorer 11 to…
  • Having trouble with my nav bar/header, It used to…
  • After a little scroll, the sticky navbar just is not…
  • What does this symbol mean in JavaScript?
  • Vue.js dynamically appending HTML when clicking on a button
  • JavaScript TypeError: Cannot read property 'style' of null
  • Selenium using Java - The path to the driver…
  • What is the worst programming language you ever worked with?
  • Can't install via pip because of egg_info error
  • Polymer paper-dropdown-menu not rendered correctly…
  • How can I center text (horizontally and vertically)…
  • laravel vuejs/axios put request Formdata is empty
  • Adding a UserCreationForm to html in Django
  • Ember link-to throws error / does not clear screen…
  • How do SO_REUSEADDR and SO_REUSEPORT differ?
  • How does data binding work in AngularJS?
  • Error Stack Overflow when trying to hide buttons in…
  • How to detect Safari, Chrome, IE, Firefox and Opera browser?
  • Polymer - How to data-bind paper-dropdown menu…
  • Form field border-radius is not working only on the…
  • Adobe XD to responsive html
  • How to detect my browser version and operating…
  • Polymer 1.x: Two-way databinding for paper-dropdown-menu
  • Vuejs - Uncaught TypeError: Cannot redefine…
  • in responsive menu it puts two links on the same line
  • How to set `border-radius` of `paper-listbox` inside…
  • CSS customized scroll bar in div
  • Three.js: Cannot display mesh created with texture array
  • commandButton/commandLink/ajax action/listener…
  • How to align checkboxes and their labels…
  • The definitive guide to form-based website authentication
  • How can I find the product GUID of an installed MSI setup?
  • Bootstrap dropdown sub menu missing
  • How do I enable dropdown on hover in vue bootstrap?
  • Align nav-items to right side in bootstrap-4
  • What methods of ‘clearfix’ can I use?
  • Ukkonen's suffix tree algorithm in plain English
  • Why does C++ code for testing the Collatz conjecture…
  • Ubuntu apt-get unable to fetch packages
  • Vue js vuecli3 application does not work in ie11…
  • How to submit Polymer forms to PHP and display response
  • ssh: Could not resolve hostname [hostname]: nodename…
  • Regular expression to allow spaces between words
  • How do I add space between items in an ASP.NET…
  • Python selenium get contents of a webpage added by…
  • Why is Ember throwing "Uncaught Error: Assertion…
  • Scrollable Menu with Bootstrap - Menu expanding its…
  • Smart way to truncate long strings
  • AppCompat v7 r21 returning error in values.xml?
  • bootstrap-vue multi level drop down
  • Is it possible to move my text side by side with my icon
  • What is the maximum length of a URL in different browsers?
  • Identifying and solving…
  • How can I handle paper-dropdown-close event in my…
  • Typeerror: n is undefined in underscore.min.js
  • How to use Servlets and Ajax?
  • How to change visibility of layout programmatically
  • Internet Explorer 11 disable "display intranet sites…
  • Make paper-menu/paper-dropdown-menu required for…
  • How can I pass modelformset_factory validation in Django?
  • Active tab issue on page load HTML
  • List of Java class file format major version numbers?
  • Is there any "font smoothing" in Google Chrome?
  • Make Iframe to fit 100% of container's remaining height
  • Using XPATH to search text containing  
  • Python, creating objects
  • Why the value of input file missing when I input the…
  • Best way to extract messy HTML tables using BeautifulSoup
  • How to get data value from bookstrap dropdown-menu…
  • Force IE9 to emulate IE8. Possible?

Disclaimer: This content is shared under creative common license cc-by-sa 3.0. It is generated from StackExchange Website Network.

Post navigation

Previous Post:

Remove rows with all or some NAs (missing values) in data.frame

Next Post:

Writing a list to a file with Python

Leave a Reply Cancel reply

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

.net ajax android angular arrays aurelia backbone.js bash c++ css dataframe ember-data ember.js excel git html ios java javascript jquery json laravel linux list mysql next.js node.js pandas php polymer polymer-1.0 python python-3.x r reactjs regex sql sql-server string svelte typescript vue-component vue.js vuejs2 vuetify.js

  • you shouldn’t need to use z-index
  • No column in target database, but getting “The schema update is terminating because data loss might occur”
  • Angular – expected call-signature: ‘changePassword’ to have a typedeftslint(typedef)
  • trying to implement NativeAdFactory imports deprecated method by default in flutter java project
  • What should I use to get an attribute out of my foreign table in Laravel?
© 2022 Fix Code Error