Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<html>
<head>
  <title>Select styles with CSS only</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    /* Some basic page styles */
    body { 
      background-color: #fff;
      font-family: helvetica, sans-serif;
      margin: 4% 10%
    }
    
    /* Label styles: style as needed */
    label {
      display:block;
      margin-top:2em;
      font-size: 0.9em;
      color:#777;
    }
    /* Container used for styling the custom select, the buttom class adds the bg gradient, corners, etc. */
    .dropdown {
      position: relative;
      display:block;
      margin-top:0.5em;
      padding:0;
    }
    /* This is the native select, we're making everything the text invisible so we can see the button styles in the wrapper */
    .dropdown select {
      width:100%;
      max-width:100%;
      min-width:100%;
      margin:0;
      background:none;
      border: 1px solid transparent;
      outline: none;
      /* Remove select styling */
      appearance: none;
      -webkit-appearance: none;
      /* Magic font size number to prevent iOS text zoom */
      font-size:16px;
      /* General select styles: change as needed */
      font-family: helvetica, sans-serif;
      font-weight: bold;
      color: #444;
      padding: .6em 1.9em .5em .8em;
      line-height:1.3;
    }
    
    /* This hides native dropdown button arrow in IE 10/11+ so it will have the custom appearance, IE 9 and earlier get a native select */
    @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {  
       .dropdown select::-ms-expand {
        display: none;
      }
    }
    
    /* Custom arrow sits on top of the select - could be an image, SVG, icon font, etc. or the arrow could just baked into the bg image on the select */
    .dropdown:after {
      background: none;
      color: #bbb;
      content: "\25BC";
      font-size: .7em;
      padding:0;
      position: absolute;
      right: 1.2em;
      top: 1.3em;
      bottom: .3em;
      z-index: 2;
      /* These hacks make the select behind the arrow clickable in some browsers */
      pointer-events:none;
      background: url(#);
    }
    
    /* This selector targets Firefox only with the trick of making the select 110% but clipped by the container at 100% to hide the arrow. We have to do this because getting rid of select appearance isn't supported consistently */
    .dropdown, x:-moz-any-link, x:default {
      overflow:hidden;
      width:100%;
    }
    .dropdown select, x:-moz-any-link, x:default {
      width:110%;
      max-width:110%;
      min-width:110%;
      /* A zero right padding is needed or the native arrow can show up. Downside is the text will run over the arrow */
      padding: .6em 0 .5em .8em;
      /* Window is a Firefox way of hiding the arrow, sometimes works */
      -moz-appearance: window;
      text-indent: 0.01px;
      text-overflow: "";
    }
   
    /* Hover style */
    .dropdown:hover {
      border:1px solid #888;
    }
    
    /* Focus style - TODO: Fix in FF */
    select:focus {
      outline:none;
      box-shadow: 0 0 1px 3px rgba(180,222,250, 1);
      background-color:transparent;
      color: #222;
      border:1px solid #aaa;
    }
    
    /* Removes the odd blue bg color behind the text in IE 10/11 and sets the text to match the focus style text */
    select:focus::-ms-value {
      background: transparent;
      color: #222;
    }
    
    /* Firefox focus has odd artifacts around the text, this kills that */
    select:-moz-focusring {
      color: transparent;
      text-shadow: 0 0 0 #000;
    }
    
    option {
      font-weight:normal;
    }
    
    
     /* These are just demo button-y styles, style as you like */
    .button {
      border: 1px solid #bbb;
      border-radius: .3em;
      box-shadow: 0 1px 0 1px rgba(0,0,0,.04);
      background: #f3f3f3; /* Old browsers */
      background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); /* FF3.6+ */
      background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#e5e5e5)); /* Chrome,Safari4+ */
      background: -webkit-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* Chrome10+,Safari5.1+ */
      background: -o-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* Opera 11.10+ */
      background: -ms-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* IE10+ */
      background: linear-gradient(to bottom, #ffffff 0%,#e5e5e5 100%); /* W3C */
    }
    
  </style>
</head>
  
<body>
 
  
  <h1>CSS-only custom-styled selects v2</h1>
  <h4><a href="https://twitter.com/toddmparker">Todd Parker</a> - <a href="http://www.filamentgroup.com">Filament Group Inc.</a></h4>
  
  
  <p><Strong>How this works:</strong> This styles a native select consistently cross-platform with only minimal CSS. The native select is then styled so it is essentially invisible (no appearance, border, bg) leaving only the select's text visible. There is a wrapper around the select that has the majority of the button styles (gradient, shadow, border, etc.). We then add the custom arrow via a pseudo element to the right. </p>
  <p>Firefox doesn't allow you to consistently style away the select arrow so we're setting the select width to 110% and clipping it with <code>overflow:hidden</code> on the parent. We then add extra right padding on the native select so the text won't run over the custom arrow or be clipped by the wrapper. These style rules are targeted to Firefox with some pretty ugly scoping but it lets better browsers have a cruft-free experience. Older IE and Opera fall back to the native select.</p>
  
  
    <label>Native select</label>
    <select>
       <option>Apples</option>
       <option>Bananas</option>
       <option>Grapes</option>
       <option>Oranges</option>
       <option selected>A very long option name to test wrapping</option>
    </select>
    
  
    <label class="wrapper">This label wraps the select
      <div class="button dropdown">
        <select>
          <option>Apples</option>
          <option>Bananas</option>
          <option>Grapes</option>
          <option>Oranges</option>
          <option>A very long option name to test wrapping</option>
        </select>
      </div>
    </label>
      
    <label class="wrapper" for="states">This label is stacked above the select</label>
      <div class="button dropdown">
        <select id="states">
          <option value="AL">Alabama</option>
          <option value="AK">Alaska</option>
          <option value="AZ">Arizona</option>
          <option value="AR">Arkansas</option>
          <option value="CA">California</option>
          <option value="CO">Colorado</option>
          <option value="CT">Connecticut</option>
          <option value="DE">Delaware</option>
          <option value="FL">Florida</option>
          <option value="GA">Georgia</option>
          <option value="HI">Hawaii</option>
          <option value="ID">Idaho</option>
          <option value="IL">Illinois</option>
          <option value="IN">Indiana</option>
          <option value="IA">Iowa</option>
          <option value="KS">Kansas</option>
          <option value="KY">Kentucky</option>
          <option value="LA">Louisiana</option>
          <option value="ME">Maine</option>
          <option value="MD">Maryland</option>
          <option value="MA">Massachusetts</option>
          <option value="MI">Michigan</option>
          <option value="MN">Minnesota</option>
          <option value="MS">Mississippi</option>
          <option value="MO">Missouri</option>
          <option value="MT">Montana</option>
          <option value="NE">Nebraska</option>
          <option value="NV">Nevada</option>
          <option value="NH">New Hampshire</option>
          <option value="NJ">New Jersey</option>
          <option value="NM">New Mexico</option>
          <option value="NY">New York</option>
          <option value="NC">North Carolina</option>
          <option value="ND">North Dakota</option>
          <option value="OH">Ohio</option>
          <option value="OK">Oklahoma</option>
          <option value="OR">Oregon</option>
          <option value="PA">Pennsylvania</option>
          <option value="RI">Rhode Island</option>
          <option value="SC">South Carolina</option>
          <option value="SD">South Dakota</option>
          <option value="TN">Tennessee</option>
          <option value="TX">Texas</option>
          <option value="UT">Utah</option>
          <option value="VT">Vermont</option>
          <option value="VA">Virginia</option>
          <option value="WA">Washington</option>
          <option value="WV">West Virginia</option>
          <option value="WI">Wisconsin</option>
          <option value="WY">Wyoming</option>
        </select>
    </div>  
  
  <div style="width:50%; min-width:10em;">
    <label class="wrapper">In a container set to 50% width
        <div class="button dropdown">
          <select>
            <option>Apples</option>
            <option>Bananas</option>
            <option>Grapes</option>
            <option>Oranges</option>
            <option>A very long option name to test wrapping and visual collisions</option>
          </select>
        </div>
      </label>
  </div>
  
  
  <h2>Confirmed to work in the following browsers</h2>
  <p>This technique seems to be functional everywhere since we're still leaving the native select in place. Worst case, the native select styling and the custom arrow will both show up but in all popular platforms, this looks very good and consistent. One minor caveat: setting the select to 110% means the menu may open up a bit wider than expected in Firefox. We set a style to set it to 100% on focus, but this doesn't seem to take effect everywhere.</p>
  <ul>
    <li>iOS 4/5/6/7 - looks good, iOS3 even works fine but isn't quite as pretty</li>
    <li>Android 2.2/2.3 (Browser) - looks good</li>
    <li>Android 4.0/4.1/4.2 (Browser) - looks good</li>
    <li>Android 4.0/4.1/4.2/4.3/4.4 (Chrome) - looks good</li>
    <li>WP8 - looks good</li>
    <li>WP7.8 (missing arrow, double border but works)</li>
    <li>Kindle Fire 2/HD - looks good</li>
    <li>IE 10/11 - looks good</li>
    <li>IE 6/7/8/9 - native select</li>
    <li>Safari 5 - looks good</li>
    <li>Chrome latest - looks good</li>
    <li>Firefox 3.6-30 - looks good but text may run over arrow</li>
    <li>Firefox OS - shows custom and default arrows</li>
    <li>Opera - looks good from 15-22 (latest), 11/12 shows a double arrow</li>
    <li>Opera Mini - alignment of text and arrows is a bit off but it works</li>
    <li>Opera Mobile - custom and native arrows both appear</li>
    <li>Nokia Asha - Long options can break outside the box</li>
  </ul>
  
</body>
</html>
Output

This bin was created anonymously and its free preview time has expired (learn why). — Get a free unrestricted account

Dismiss x
public
Bin info
anonymouspro
0viewers