CSS only custom-styled select

by Walter Schwarz

HTML

<body>
 
  
  <h1>CSS only custom-styled select</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>Opera, Firefox and older IE don'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.</p>
  
    <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 selected>A very long option name to test wrapping and visual collisions</option>
        </select>
      </div>
    </label>
      
    <label class="wrapper" for="states">This label is stacked above the select</label>
      <div class="button dropdown" id="states">
        <select>
          <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...

CSS

body { 
      background-color: #fff;
      font-family: helvetica, sans-serif;
      margin: 4% 10%
    }
    

    label {
      display:block;
      margin-top:2em;
      font-size: 0.9em;
      color:#777;
    }

    .dropdown {
      position: relative;
      display:block;
      margin-top:0.5em;
      overflow:hidden;
      width:100%;
      max-width:100%;
    }

    select {
      /* Make sure the select is wider than the container so we can clip the arrow */
      width:110%;
      max-width:110%;
      min-width:110%;
      /* Remove select styling */
      appearance: none;
      -webkit-appearance: none;
      /* Ugly Firefox way of doing it */
      -moz-appearance: window;
      text-indent: 0.01px;
      text-overflow: "";
      /* Magic font size number to prevent iOS text zoom */
      font-size:16px;
      font-weight: bold;
      background:none;
      border: none;
      color: #444;
      outline: none;
      /* Padding works surpringly well */
      padding: .4em 19% .4em .8em;
      font-family: helvetica, sans-serif;
      line-height:1.2;
      margin:.2em;
    }
    
    /* This hides native dropdown button arrow in IE */
    select::-ms-expand {
      display: none;
    }

     /* Custom arrow - could be an image, SVG, icon font, etc. */
    .dropdown:after {
      background: none;
      color: #bbb;
      content: "\25BC";
      font-size: .7em;
      padding:0;
      position: absolute;
      right: 1em;
      top: 1.2em;
      bottom: .3em;
      z-index: 1;
      /* This hack makes the select behind the arrow clickable in some browsers */
      pointer-events:none;
    }
   
    /* Hover style - tricky because we're clipping the overflow */
    .dropdown:hover {
      border:1px solid #888;
    }
    
    /* Focus style */
    select:focus {
      outline: none;
      box-shadow: 0 0 3px 3px rgba(180,222,250, .85);
    }
    
    /* This hides focus around selected option in FF */
    select:-moz-focusring {
      color:...