How to Style a <select> Box Drop-Down with Only CSS?

Box drop-down styling

It has been hard for a long time to style the <select> element across all browsers.

A reasonable set of styles, as it turns out, can create a consistent and attractive selection box across new browsers while remaining just fine in older ones as well.

There are several elements of a select box that can be styled, particularly the height, width, font, border, color, padding, box-shadow and background color.

Example of styling a select box:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .box {
        width: 120px;
        height: 30px;
        border: 1px solid #999;
        font-size: 18px;
        color: #1c87c9;
        background-color: #eee;
        border-radius: 5px;
        box-shadow: 4px 4px #ccc;
      }
    </style>
  </head>
  <body>
    <p>An ordinary select box:</p>
    <select>
      <option>Coffee</option>
      <option>Tea</option>
      <option>Juice</option>
      <option selected>Cocktail</option>
    </select>
    <p>A styled select box:</p>
    <select class="box">
      <option>Coffee</option>
      <option>Tea</option>
      <option>Juice</option>
      <option selected>Cocktail</option>
    </select>
  </body>
</html>

Result

An ordinary select box:

A styled select box:

However, the annoying drop-down arrow continually stays the same. There is no direct way to style it, but there are some tricks that can be used to change the default drop-down arrow. Let’s discuss some methods below.

Use appearance: none;

To hide the default arrow of the <select> dropdown, set the CSS appearance property to its "none" value, then add your individual arrow with the help of the background shorthand property.

Note that the appearance property is still considered to be an experimental technology and you need to use -moz- (for Firefox) and -webkit- (for Chrome, Safari, Opera) prefixes for maximum browser compatibility.

Example of adding an individual arrow by using the appearance property:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      select {
        width: 140px;
        height: 35px;
        padding: 5px 35px 5px 5px;
        font-size: 18px;
        border: 2px solid #ccc;
        -webkit-appearance: none;
        -moz-appearance: none;
        appearance: none;
        background: url("/uploads/media/default/0001/02/f7b4d3d2ba3fe1d8518e6e63d7740e1e73921abf.png") 96% / 15% no-repeat #eee;
      }
    </style>
  </head>
  <body>
    <select>
      <option>Coffee</option>
      <option>Tea</option>
      <option>Juice</option>
      <option selected>Cocktail</option>
    </select>
  </body>
</html>

Use overflow: hidden;

First, put the <select> box element in a <divt> container with a fixed width and set the overflow to "hidden". Then, give the <select> element a width of more than 20 pixels larger than the <div> element. This will make the default drop-down arrow hidden (because of the overflow: hidden on the container), and now it is possible to apply a background image on the right side of the <div>.

This method is good to use because all browsers effectively support overflow: hidden.
Note that the disadvantage of this method is that the options are visually more extended than the select menu.

Example of adding an individual arrow by using the overflow property:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .mystyle select {
        background: transparent;
        width: 140px;
        height: 35px;
        border: 1px solid #ccc;
        font-size: 18px;
      }
      .mystyle {
        width: 120px;
        height: 34px;
        border: 1px solid #111;
        border-radius: 3px;
        overflow: hidden;
        background: url("/uploads/media/default/0001/02/f7b4d3d2ba3fe1d8518e6e63d7740e1e73921abf.png") 96% / 20% no-repeat #ddd;
      }
    </style>
  </head>
  <body>
    <div class="mystyle">
      <select>
        <option>Coffee</option>
        <option>Tea</option>
        <option>Juice</option>
        <option selected>Cocktail</option>
      </select>
    </div>
  </body>
</html>

Use pointer-events: none;

The CSS pointer-events property can be used to create individual <select> drop-downs, by overlaying an element over the native drop-down arrow (to create the custom one) and disallowing pointer-events on it.

This method works well and has excellent browser support.

Example of creating an individual drop-down by using the pointer-events property:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .mybox {
        position: relative;
        display: inline-block;
      }
      select {
        display: inline-block;
        height: 30px;
        width: 150px;
        outline: none;
        color: #74646e;
        border: 1px solid #ccc;
        border-radius: 5px;
        box-shadow: 1px 1px 2px #999;
        background: #eee;
      }
      /* Select arrow styling */
      .mybox .myarrow {
        width: 23px;
        height: 28px;
        position: absolute;
        display: inline-block;
        top: 1px;
        right: 3px;
        background: url("/uploads/media/default/0001/02/f7b4d3d2ba3fe1d8518e6e63d7740e1e73921abf.png") right / 90% no-repeat #eee;
        pointer-events: none;
      }
    </style>
  </head>
  <body>
    <div class="mybox">
      <span class="myarrow"></span>
      <select>
        <option>Coffee</option>
        <option>Tea</option>
        <option>Juice</option>
        <option selected>Cocktail</option>
      </select>
    </div>
  </body>
</html>

Use punctuation marks instead of the drop-down arrow

It is quite pretty to use your preferred marks instead of the annoying drop-down sign of the <select> box.

Set the marks in the content property and set the corresponding font to look good. Here, we set "Consolas" and "monospace". Then, you need to rotate the punctuation marks using the CSS transform property.

Here, the <select> box is inserted in a <label> element, so that we can set a cursor for it even if the pointer-events property is set to "none".

Example of using a punctuation mark instead of the drop-down arrow:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      select {
        width: 140px;
        height: 35px;
        padding: 4px;
        border-radius: 4px;
        box-shadow: 2px 2px 8px #999;
        background: #eee;
        border: none;
        outline: none;
        display: inline-block;
        -webkit-appearance: none;
        -moz-appearance: none;
        appearance: none;
        cursor: pointer;
      }
      label {
        position: relative;
      }
      label:after {
        content: '<>';
        font: 11px "Consolas", monospace;
        color: #666;
        -webkit-transform: rotate(90deg);
        -moz-transform: rotate(90deg);
        transform: rotate(90deg);
        right: 8px;
        top: 2px;
        padding: 0 0 2px;
        border-bottom: 1px solid #ddd;
        position: absolute;
        pointer-events: none;
      }
      label:before {
        content: '';
        right: 6px;
        top: 0px;
        width: 20px;
        height: 20px;
        background: #eee;
        position: absolute;
        pointer-events: none;
        display: block;
      }
    </style>
  </head>
  <body>
    <label>
      <select>
        <option>Coffee</option>
        <option>Tea</option>
        <option>Juice</option>
        <option selected>Cocktail</option>
      </select>
    </label>
  </body>
</html>