123

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <!--
  https://24ways.org/2018/inclusive-considerations-when-restyling-form-controls/
-->

<div class="wrap">
  <h1>
    Visually comparing form elements
  </h1>
  <button type="button" id="swch" data-switch-btn aria-pressed="true" data-switch-btn-labels>
      Enable Custom Styles
    </button>
  <details>
  <p>Toggle between default browser rendering and styled/partially versions of each control.</p>
  <p>
    The CSS for the "styled" examples utlize various browser prefixes to showcase what about these inputs can be targetted. You can see a different <a href="https://codepen.io/scottohara/pen/wQZoWN" target="_blank">side by side comparison here (opens in new window)</a>.
  </p>
    <p>
      Note that some components, may look differently, or even odd (e.g. color picker and date & time field in Edge), depending on the browser viewed.  With Edge's recent announcment in switching to Chromium, style parity for that browser should be seen as less of a priority, as styling will likely fall more in line with current Chrome styles.
    </p>
    <p>
      The styles represented on this page are for testing how close these controls can be made to look cross browser.  Further exploration of styles, including the styling of control states (disabled, required, invalid, etc.) would be next steps beyond this comparative baseline.
    </p>
  </details>
  <div class="styled" id="target">
  <div class="flex">
    <div class="flex__child flex-child--s">
      <div>
        <label>
          Name
          <input type="text">
        </label>
      </div>
      <div>
        <label>
          Search for
          <input type="search">
        </label>
      </div>
      <div>
        <label>
          Your website
          <input type="url">
        </label>
      </div>
      <div>
        <label>
          Your Email
          <input type="email">
        </label>
      </div>
      <div>
        <label>
          Mobile Phone
          <input type="tel">
        </label>
      </div>
      <div>
        <label>
          Password
          <input type="password">
        </label>
      </div>
    </div>

    <div class="flex__child">
      <fieldset>
        <legend>Do you agree?</legend>
        <div>
          <label class="radio-label">
            <input type="radio" name="r" checked>
            Yes
          </label>

          <label class="radio-label">
            <input type="radio" name="r">
            No
          </label>
        </div>
      </fieldset>

      <div class="flex flex--center">

        <div class="flex__child">
          <div style="margin: 1.5em 0;">
            <label>
              <input type="checkbox">
              I need a nap
            </label>
          </div>

          <div>
            <label>
              Pick a color
              <input type="color">
            </label>
          </div>
        </div>

        <div class="flex__child">
          <div style="margin-bottom: .5em">
            <label>
              Standard Select<br>
<small>(won't show drop arrow in iOS without further styling)</small>
              <select class="standard">
                <option>hi</option>
                <option>bye</option>
                <option>aloha</option>
              </select>
              
            </label>
          </div>

          <label for="ex_custom_select">
            Custom Pattern Select
          </label>
          <div class="select">
            <select id="ex_custom_select">
              <option>Option 1</option>
              <option>Option 2</option>
              <option disabled>Option 3</option>
              <option>Option 4</option>
            </select>
          </div>
        </div>


      </div>

      <div class="flex no-mobile">
        <div class="flex__child">
          <div>
            <label>
              Date
              <input type="date">
            </label>
          </div>
          <div>
            <label>
              Month
              <input type="month">
            </label>
          </div>
        </div>
        <div class="flex__child">
          <div>
            <label>
              Week
              <input type="week">
            </label>
          </div>
          <div>
            <label>
              Time
              <input type="time">
            </label>
          </div>
        </div>
        <div class="flex__child">
          <div>
            <label>
              Date & Time
              <input type="datetime-local">
            </label>
          </div>
        </div>
      </div>

      <div class="flex">
        <div class="flex__child">
          <div>
            <label>
              Add a file
              <input type="file">
            </label>
          </div>
        </div>
        <div class="flex__child">
          <div>
            <label>
              Choose a number
              <input type="number">
            </label>
          </div>
          <div>
            <label>
              Gauge it
              <input type="range">
            </label>
          </div>
        </div>
      </div>
    </div>
  </div>



  <div class="flex">
    <div class="flex__child">
      <button>
        CTA!
      </button>
      <input type="submit">
      <input type="reset">
    </div>
    <div class="flex__child">
      Image
      <input type="image" src="https://picsum.photos/g/150/50" alt="img btn">
    </div>
  </div>
</div>

</div>



            
          
!
            
              /**
  Demo styling
*/
*,
*:before,
*:after {
  box-sizing: border-box;
}

h1 {
  margin-top: 0;
}

body {
  background: #efefef;
  font-family: arial;
  font-size: 1.2em;
  line-height: 1.4;
  margin: 0;
  overflow-x: hidden;
  padding: 1.4em 2em;
}

@media screen and ( min-width: 50em ) {
  .flex {
  display: flex;
  flex-wrap: wrap;
}

.flex--center {
  align-items: center;
}

.flex__child {
  flex: 1 0 auto;
  max-width: 100%;
  padding: .5em 0;
}
  .flex__child { padding: .5em .75em; }
}



/**
 * Selected rulesets from normalize.css
 * https://necolas.github.io/normalize.css/8.0.1/normalize.css
 */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */

html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}

/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */

button,
input { /* 1 */
  overflow: visible;
}

/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */

button,
select { /* 1 */
  text-transform: none;
}

/**
 * Correct the inability to style clickable types in iOS and Safari.
 */

button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}

/**
 * Remove the inner border and padding in Firefox.
 */

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

/**
 * Restore the focus styles unset by the previous rule.
 */

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}

/**
 * Correct the padding in Firefox.
 */

fieldset {
  padding: 0.35em 0.75em 0.625em;
}

/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *    `fieldset` elements in all browsers.
 */

legend {
  box-sizing: border-box; /* 1 */
  color: inherit; /* 2 */
  display: table; /* 1 */
  max-width: 100%; /* 1 */
  padding: 0; /* 3 */
  white-space: normal; /* 1 */
}

/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */

progress {
  vertical-align: baseline;
}

/**
 * Remove the default vertical scrollbar in IE 10+.
 */

textarea {
  overflow: auto;
}

/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */

[type="checkbox"],
[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */

[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */

[type="search"] {
  -webkit-appearance: none; /* 1 */
  outline-offset: -2px; /* 2 */
}

/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */

[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}





/* ***********
  Styled controls
************ */
.styled fieldset {
  border: 1px solid;
  margin: 0;
}

.styled input,
.styled select,
.styled textarea {
  color: inherit;
  font: inherit;
  position: relative;
}

.styled input[type="text"],
.styled input[type="search"],
.styled input[type="url"],
.styled input[type="email"],
.styled input[type="tel"],
.styled input[type="password"],
.styled input[type="date"],
.styled input[type="month"],
.styled input[type="week"],
.styled input[type="time"],
.styled input[type="datetime-local"],
.styled input[type="file"],
.styled input[type="number"],
.styled textarea,
.styled select,
.styled .unsupported {
  background: transparent;
  border-radius: 4px;
  border: 1px solid rgba(10,10,10,.5);
  border-bottom: 4px solid;
  display: block;
  margin-bottom: .625em;
  margin-top: .125em;
  outline-offset: 3px;
  padding: .25em;
  width: 100%;
}

.styled input[type="number"] {
  /*-moz-appearance: textfield;*/
  /* this will get rid of the number spinner. but moz has no good way
     of reintroducing it without JavaScript.  */
}

.styled input[type="search"] {
  /* stops iOS from forcing rounded corners */
  -webkit-appearance: none;
}


/**
 * Checkbox specific
 */
.styled input[type="checkbox"] {
  -moz-appearance: none;
  -o-appearance: none;
  -webkit-appearance: none;
  background: #fff;
  border: 1px solid;
  border-radius: 4px;
  height: 2em;
  width: 2em;
  font-size: inherit;
  line-height: 1;
  vertical-align: bottom;
  position: relative;
}

.styled input[type="checkbox"]:before,
.styled input[type="checkbox"]:after {
  border-bottom: 3px solid green;
  border-right: 3px solid green;
  bottom: 0;
  content: "";
  height: 1em;
  margin: auto;
  position: absolute;
  right: .5em;
  top: -.5em;
  transform: rotate(45deg) scale(0);
  transition: transform .2s ease-in-out;
  width: .625em;
}

.styled input[type="checkbox"]:checked {
  box-shadow: inset 0 0 20px 3px rgba(green, .05)
}

.styled input[type="checkbox"]:checked:before {
  transform: rotate(45deg) scale(1);
}

.styled input[type="checkbox"]:checked:after {
  animation: expand .8s;
}

.styled input[type="checkbox"]:focus {
  box-shadow: 0 0 0 1px;
  border: 2px solid;
  outline: none;
  /*
    can use outline none here because revised box-shadow
    and border-width adjustments are made to replace
    the default outline indicator.
  */
}


@keyframes expand {
  0% {
    transform: rotate(45deg) scale(0);
    opacity: 1;
  }
  50% {
    top: -30px;
    transform: rotate(45deg) scale(2.25);
    opacity: 1;
  }
  100% {
    opacity: 0;
    top: -30px;
    transform: rotate(45deg) scale(2.25);
  }
}

/* -ms-check will affect both checkboxes and radio buttons, so you have to be specific */
.styled input[type="checkbox"]::-ms-check {
   border: 2px solid #888;
   border-radius: 2px;
   color: green;
  /*
    disabled and required/invalid
    styles would be good to add too!
  */
 }

/**
 * Radio Button Specific
 */
.styled .radio-label {
  display: inline-block;
  padding: .5em .5em 0 0;
}

.styled input[type="radio"] {
  -moz-appearance: none;
  -webkit-appearance: none;
  appearance: none;
  background: #fff;
  border-radius: 100%;
  border: 1px solid transparent;
  box-shadow:
    0 0 0 2px rgba(13,81,146, 1),
    inset 0 0 0 0px rgba(13,81,146, 0);
  display: inline-block;
  height: 1.25em;
  margin-right: .25em;
  transition:
    border-color .2s ease-in-out,
    box-shadow .2s ease-in-out;
  vertical-align: text-bottom;
  width: 1.25em;
}

.styled input[type="radio"]:focus {
  border-color: transparent;
  box-shadow:
    0 0 0 2px rgba(13, 81, 146, 1),
    inset 0 0 0 0px rgba(13, 81, 146, 1);
}

.styled input[type="radio"]:checked {
  border-color: #fff;
  box-shadow:
    0 0 0 2px rgba(34, 139, 236, 1),
    inset 0 0 0 6px rgba(13, 81, 146, 1);
}

.styled input[type="radio"]:checked:focus {
  box-shadow:
    0 0 0 3px rgba(34, 139, 236, 1),
    inset 0 0 0 3px rgba(13, 81, 146, 1);
}

.styled input[type="radio"][disabled],
.styled input[type="radio"][disabled] + span {
  opacity: .4;
}

@media screen and (-ms-high-contrast: active) {
  .styled input[type="radio"]:checked {
    border: 6px solid;
    box-shadow: none;
  }
}



/**
 * Range Slider Specific
 */
/**
 * General Input styling
 *
 * As all ranges in a UI should probably look the same, there
 * is no need to use a class here, and the specific type of
 * input, [range], can instead be the selector to specifically
 * target the form control.
 */
.styled input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: none;
  font-size: inherit;
  margin: 1em 0;
  width: 100%;
}

.styled input[type="range"][disabled] {
  opacity: .625;
}


/**
 * Track
 */
.styled input[type="range"]::-webkit-slider-runnable-track {
  background: #eee;
  border: 1px solid #999;
  border-radius: 4px;
  box-shadow:
    inset 0 1px 3px rgba(0,0,0,.2),
    0 0 0 0px #333;
  height: .5em;
  width: 100%;
}

.styled input[type="range"]::-moz-range-track {
  background: #eee;
  border: 1px solid #999;
  border-radius: 4px;
  box-shadow:
    inset 0 1px 3px rgba(0,0,0,.2),
    0 0 0 0px #333;
  height: .35em;
  width: 100%;
}

.styled input[type="range"]::-moz-range-progress {
  background: rgba(0, 255, 0, .5);
  height: .4em;
  border-radius: 4px;
}

.styled input[type="range"]::-ms-track {
  background: transparent;
  border-color: transparent;
  border-width: 1em 0;
  color: transparent;
  height: .4em;
  width: 100%;
}

@media screen and (-ms-high-contrast: active) {
  .styled input[type=range]::-ms-track {
    border: 0;
    margin: 1em 0;
  }
}

.styled input[type=range]::-ms-fill-lower {
  background: #eee;
  border: 1px solid #999;
  border-radius: 4px;
  box-shadow:
    inset 0 1px 3px rgba(0,0,0,.2),
    0 0 0 0px #333;
}

.styled input[type=range]::-ms-fill-upper {
  background: #eee;
  border: 1px solid #999;
  border-radius: 4px;
  box-shadow:
    inset 0 1px 3px rgba(0,0,0,.2),
    0 0 0 0px #333;
}


/**
 * Focus Styles
 */
.styled input[type=range]:focus {
  outline: 0;
}

.styled input[type=range]:focus::-webkit-slider-runnable-track {
  background: #168be8;
}

.styled input[type=range]::-moz-focus-outer {
  border: 0;
}

.styled input[type=range]:focus::-moz-range-track {
  background: #168be8;
}

.styled ::-ms-ticks-after,
.styled ::-ms-ticks-before {
  color: #000;
  display: block;
}

.styled input[type=range]:focus::-ms-fill-lower {
  background: #168be8;
}

.styled input[type=range]:focus::-ms-fill-upper {
  background: #168be8;
}

.styled input[type=range]:focus::-webkit-slider-thumb {
  background: #fff;
  box-shadow: 0 0 0 2px rgba(60,60,60,.8);
}

.styled input[type=range]:focus::-moz-range-thumb {
  background: #fff;
  box-shadow: 0 0 0 2px rgba(60,60,60,.8);
}

.styled input[type=range]:focus::-ms-thumb {
  background: #fff;
  box-shadow: 0 0 0 2px rgba(60,60,60,.8);
}


/**
 * Thumbs
 */
.styled input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  background: #eee;
  border: 1px solid rgba(0,0,0,.5);
  border-radius: 2px;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  cursor: grab;
  height: 2em;
  margin: -.825em 0 0;
  position: relative;
  width: 1.25em;
  z-index: 3;
}

.styled input[type=range][disabled]::-webkit-slider-thumb {
  cursor: not-allowed;
}

.styled input[type=range]::-moz-range-thumb {
  background: #eee;
  border: 1px solid rgba(0,0,0,.5);
  border-radius: 2px;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  cursor: grab;
  height: 1.825em;
  position: relative;
  width: 1.125em;
  z-index: 3;
}

.styled input[type=range][disabled]::-moz-range-thumb {
  cursor: not-allowed;
}

/**
 * Edge respects the webkit styling here (odd), but
 * IE11 doesn't (correct). To get both browsers
 * to be correctly styled, this is still necessary
 * and the negative margin of the webkit styling
 * needs to be removed.
 */
.styled input[type=range]::-ms-thumb {
  background: #eee;
  border: 1px solid rgba(0,0,0,.5);
  border-radius: 2px;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  cursor: grab; /* ms doesn't currently support */
  height: 1.825em;
  margin: 0;
  position: relative;
  width: 1.125em;
  z-index: 3;
}

.styled input[type=range][disabled]::-ms-thumb {
  cursor: not-allowed;
}

/**
 * When a user specifically 'grabs' the
 * thumb/knob/whatever, change the cursor
 * to the active state.
 */
.styled input[type=range]:not([disabled])::-webkit-slider-thumb:active {
  cursor: grabbing;
}
.styled input[type=range]:not([disabled])::-moz-range-thumb:active {
  cursor: grabbing;
}
.styled input[type=range]:not([disabled])::-ms-thumb:active {
  cursor: grabbing; /* ms doesn't currently support */
}



/**
 * Color Specific
 */
.styled input[type="color"]:not(.unsupported) {
  background: none;
  border: 1px solid;
  border-radius: 100%;
  height: 2.25em;
  width: 2.25em;
  padding: 0;
  margin: 0 .4em;
  vertical-align: middle;
}
.styled input::-moz-color-swatch {
  border-radius: 100%;
  border: 2px solid transparent;
  height: 1.75em;
  padding: 0;
  width: 1.75em;
}

.styled input:focus::-moz-color-swatch,
.styled input:hover::-moz-color-swatch{
  box-shadow: 0 0 4px 1px #000;
}

.styled input[type="color"]:focus {
  background: rgba(255,255,255,.9);
  border-color: transparent;
  box-shadow: 0 0 0 4px #fff,
              0 0 0 6px #036FE2;
  outline: 3px solid transparent;
}

.styled input[type="color"]:-moz-focusring::-moz-focus-inner {
  border: 0
}


.styled input::-webkit-color-swatch-wrapper {
  border-radius: 100%;
  border: 2px solid transparent;
  height: 1.75em;
  margin: .2em auto 0;
  padding: 0;
  width: 1.75em;
}

.styled input::-webkit-color-swatch {
  border: 1px solid;
  border-radius: 100%;
  padding: 0;
  margin: 0;
}

.styled input:hover::-webkit-color-swatch-wrapper,
.styled input:focus::-webkit-color-swatch-wrapper {
  border-color: black;
}


/**
 * Styles for the wrapping element and
 * the custom down arrow / background
 */
.styled .select {
  background-color: #2a2a2a;
  position: relative;
}

.styled .select:after,
.styled .select:before {
  bottom: 0;
  content: "";
  pointer-events: none;
  position: absolute;
  top: 0;
}

.styled .select:before {
  right: 0;
  width: 1.85em;
}

.styled .select:after {
  border-bottom: 2px solid #fff;
  border-right: 2px solid #fff;
  height: .5em;
  margin: auto;
  right: .75em;
  transform-origin: center right;
  transform: rotate(45deg);
  width: .5em;
  z-index: 2;
}

.styled .select:focus-within:before {
  background-color: #015f9f;
}

/**
 * Target only select elements that are
 * child elements of the custom style.
 * These styles could really mess up other
 * selects that aren't within the parent wrapper.
 */
.styled .select select {
  -moz-appearance: none;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border-radius: 0;
  border: 1px solid #000;
  color: #fff;
  line-height: normal;
  max-width: 100%;
  padding: .75em 2em .75em .75em;
  width: 100%;
}

/*.styled .select select:focus-visible*/
.styled .select select:-moz-focusring {
  color: transparent;
  text-shadow: 0 0 0 #fff;
}

.styled .select select:focus {
  border-color: #015f9f;
  box-shadow: inset 0 0 0 1px #015f9f, 0 0 0 2px #015f9f;
  outline: none;
}

.styled .select select[disabled] {
  color: rgba(255,255,255,.75);
  cursor: not-allowed;
  opacity: .75;
}

/**
 * 1. remove background focus style from IE11 while keeping
 *    focus style available on option elements
 * 2. remove the default down arrow in IE/Edge
 */
.styled .select select::-ms-value {
  background: transparent; /* 1 */
}

.styled .select select::-ms-expand {
  display: none; /* 2 */
}


/**
 * Child elements of the select
 */
.styled .select select:focus option:not([disabled]),
.styled .select select:focus optgroup:not([disabled]) {
  color: #111;
  text-shadow: none;
}

.styled .select option[disabled],
.styled .select optgroup[disabled] {
  color: rgba(50,50,50,.75);
}


/**
 * Hover because why not?
 */
.styled input:hover,
.styled select:hover,
.styled textarea:hover,
.styled .unsupported:hover {
  box-shadow: 0 0 0 3px  rgba(3, 111, 200, .9);
}


/**
 * Focus
 */
.styled input[type="text"]:focus,
.styled input[type="search"]:focus,
.styled input[type="url"]:focus,
.styled input[type="email"]:focus,
.styled input[type="tel"]:focus,
.styled input[type="password"]:focus,
.styled input[type="date"]:focus,
.styled input[type="month"]:focus,
.styled input[type="week"]:focus,
.styled input[type="time"]:focus,
.styled input[type="datetime-local"]:focus,
.styled input[type="file"]:focus,
.styled input[type="number"]:focus,
.styled textarea:focus,
.styled .unsupported:focus {
  background: rgba(255,255,255,.9);
  border-color: transparent;
  box-shadow: 0 0 0 4px #fff;
  outline: 3px solid #036FE2;
}

.styled input[type="checkbox"]:focus {
  background: rgba(255,255,255,.9);
  border-color: transparent;
  box-shadow: 0 0 0 2px #fff,
              0 0 0 6px #036FE2;
}

/**
 * Invalid
 */
.styled input[type="text"]:invalid,
.styled input[type="search"]:invalid,
.styled input[type="url"]:invalid,
.styled input[type="email"]:invalid,
.styled input[type="tel"]:invalid,
.styled input[type="password"]:invalid,
.styled input[type="date"]:invalid,
.styled input[type="month"]:invalid,
.styled input[type="week"]:invalid,
.styled input[type="time"]:invalid,
.styled input[type="datetime-local"]:invalid,
.styled input[type="file"]:invalid,
.styled input[type="number"]:invalid,
.styled textarea:invalid {
  box-shadow: 0;
  outline: 2px solid red;
}



/**
 * Buttons
 */
.styled button,
.styled input[type="image"],
.styled input[type="submit"],
.styled input[type="reset"] {
  background: #036FE2;
  color: #fff;
  line-height: 2;
  border: 2px solid transparent;
  border-radius: 6px;
  margin: 0;
  width: 100%;
}

.styled button:not(:first-child),
.styled input[type="image"]:not(:first-child),
.styled input[type="submit"]:not(:first-child),
.styled input[type="reset"]:not(:first-child) {
  margin-top: .25em;
}

.styled button:not(:last-child),
.styled input[type="image"]:not(:last-child),
.styled input[type="submit"]:not(:last-child),
.styled input[type="reset"]:not(:last-child) {
  margin-bottom: .25em;
}

.styled button:focus,
.styled button:hover,
.styled input[type="submit"]:focus,
.styled input[type="submit"]:hover,
.styled input[type="image"]:focus,
.styled input[type="image"]:hover,
.styled input[type="reset"]:focus,
.styled input[type="reset"]:hover {
  background: #03366D;
  color: #fff;
  outline: 3px solid #036FE2;
  outline-offset: 2px;
}

/**
 * Upload File
 */
.styled input[type="file"] {
  padding-left: 1.5em;
}

.styled ::-webkit-file-upload-button {
  border: 1px solid transparent;
  background: #036FE2;
  color: #fff;
  box-shadow: none;
  margin-left: -1.25em;
}

.styled input:hover::-webkit-file-upload-button,
.styled input:focus::-webkit-file-upload-button,
.styled input::-webkit-file-upload-button:active {
  background: #03366D;
  outline: 3px solid #036FE2;
  outline-offset: 2px;
}

.styled ::-ms-browse {
  border: 1px solid transparent;
  background: #036FE2;
  color: #fff;
}


.styled ::-ms-browse:hover,
.styled ::-ms-browse:focus {
  background: #03366D;
  outline: 3px solid #036FE2;
  outline-offset: 2px;
}






/**
 * webkit date fields
 */
.styled input::-webkit-datetime-edit-text {
  display: none;
  /* the "/" that natively shows up
     in between mm/dd/yyyy
  */
}


.styled ::-webkit-datetime-edit-fields-wrapper {
  margin-left: 1em;
}

.styled ::-webkit-datetime-edit-month-field,
.styled ::-webkit-datetime-edit-week-field,
.styled ::-webkit-datetime-edit-day-field,
.styled [type="datetime-local"]::-webkit-datetime-edit-year-field {
  border-right: 1px solid rgba(0,0,0,.25);
  padding: .25em
}

.styled ::-webkit-datetime-edit-ampm-field,
.styled ::-webkit-datetime-edit-year-field,
.styled ::-webkit-datetime-edit-hour-field,
.styled ::-webkit-datetime-edit-minute-field {
  padding: .25em
}

.styled ::-webkit-datetime-edit-hour-field:focus,
.styled ::-webkit-datetime-edit-hour-field:hover,
.styled ::-webkit-datetime-edit-minute-field:focus,
.styled ::-webkit-datetime-edit-minute-field:hover,
.styled ::-webkit-datetime-edit-ampm-field:focus,
.styled ::-webkit-datetime-edit-ampm-field:hover,
.styled ::-webkit-datetime-edit-week-field:focus,
.styled ::-webkit-datetime-edit-week-field:hover,
.styled ::-webkit-datetime-edit-month-field:focus,
.styled ::-webkit-datetime-edit-day-field:focus,
.styled ::-webkit-datetime-edit-year-field:focus,
.styled ::-webkit-datetime-edit-month-field:hover,
.styled ::-webkit-datetime-edit-day-field:hover,
.styled ::-webkit-datetime-edit-year-field:hover {
  background: #03366D;
  color: #fff;
}



/**
 * additional webkit style hooks
 */
.styled ::-webkit-inner-spin-button,
.styled ::-webkit-calendar-picker-indicator {
  opacity: 1;
}

.styled ::-webkit-inner-spin-button:hover,
.styled ::-webkit-calendar-picker-indicator:hover {
  border-radius: 6px;
  box-shadow: 0 0 0 1px #036FE2;
}

input::-webkit-clear-button,
input[type="search"]::-webkit-search-cancel-button  {
  /*-webkit-appearance: none;*/ /*can't fully edit otherwise*/
  /*background: #f00;*/ /* could include a bg img */
  /*border: 1px solid;
  border-radius: 100%;
  height: 1em;
  opacity: 1;
  width: 1em;*/
}

/* just showing off how these selectors can be targeted
   though styling of some will still require an
   appearance: none of their own to fully reset
*/
.styled ::-webkit-textfield-decoration-container,
.styled ::-webkit-datetime-edit {}
.styled input::-webkit-clear-button:active,
.styled input[type="search"]::-webkit-search-cancel-button:active {}


/**
 * force layout for iOS
 */
.styled input[type="date"],
.styled input[type="month"],
input[type="week"],
.styled input[type="time"],
.styled input[type="datetime-local"] {
  -webkit-appearance: textfield;
  min-height: 2em;
  min-width: 95%;
}




/**
 * Just a listing of selectors
 */
input[type="text"] {}
input[type="search"] {}
input[type="url"] {}
input[type="email"] {}
input[type="tel"] {}
input[type="password"] {}
input[type="radio"] {}
input[type="checkbox"] {}
input[type="date"] {}
input[type="month"] {}
input[type="week"] {}
input[type="time"] {}
input[type="datetime-local"] {}
input[type="file"] {}
input[type="number"] {}
input[type="range"] {}
input[type="submit"] {}
input[type="reset"] {}
textarea {}



/**
 * Other MS selecotrs
 */
/* microsoft stuffs */
.styled ::-ms-clear {
  /*border: 1px solid;
  display: block;*/
}

.styled ::-ms-reveal {
 /* border: 1px solid;
  display: block;*/
}

.styled ::-ms-check {
  /*border-color: red;
  color: blue;
  height: 2em;
  width: 2em;*/
}

.styled ::-ms-value {
   /*color: #f00;*/
}


/**
 * States
 * CSS Selectors Level 4
 * Form States
 */

:enabled {}
.styled :disabled {
  opacity: .5;
}
:indeterminate {}
:read-write {}
:read-only {}
:placeholder-shown {}
:default {}
:checked {}
:blank {}
:valid {}
:invalid {}
:user-invalid {}
:in-range {}
:out-of-range {}
:required {}
:optional {}










/* containing label */
.toggle-switch {
  background: none;
  border: 3px solid #000;
  box-shadow: 0 0 0px #2196f3;
  display: block;
  font-size: inherit;
  line-height: 1;
  overflow: hidden;
  margin: 1em 0 0;
  padding: .5em;
  position: relative;
  text-align: left;
  transition: box-shadow .2s ease-in-out;
  width: 100%;


  width: 16em;
  padding-right: 4em;
  margin-bottom: 1em;
  margin-top: -1em;
}

.toggle-switch:hover {
  box-shadow: 0 0 2px #2196f3;
}

.toggle-switch:focus {
  outline: none;
}

/* negate 'flash' of text color when pressing a button in some browsers */
.toggle-switch:active {
  color: inherit;
}

/* using the before/after pseudo elements of the span to create the "switch" */
.toggle-switch__ui:before,
.toggle-switch__ui:after {
  border: 1px solid #565656;
  content: "";
  display: block;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

/* styling specific to the knob of the switch */
.toggle-switch__ui:after {
  background: #fff;
  border-radius: 100%;
  height: 1.5em;
  right: 1.5em;
  transition: right .1825s ease-in-out;
  width: 1.5em;
}

/* styling specific to the knob "container" */
.toggle-switch__ui:before {
  background: #eee;
  border-radius: 1.75em;
  height: 1.75em;
  right: .25em;
  transition: background .2s ease-in-out;
  width: 2.75em;
}

.toggle-switch span {
  pointer-events: none;
}

.toggle-switch:focus .toggle-switch__ui:before {
  outline: 2px solid #2196f3;
}

/* change the position of the knob to indicate it has been checked*/
.toggle-switch[aria-pressed="true"] .toggle-switch__ui:after {
  right: .25em;
}

/* update the color of the "container" to further visually indicate state */
.toggle-switch[aria-pressed="true"] .toggle-switch__ui:before {
  background: #2196f3;
}

/**
 * Toggle switch modifications for displaying On/Off labels
 */
.toggle-switch--labels span:before {
  content: "Off";
  color: rgba(10, 10, 10, 1);
  line-height: 1.6;
  text-indent: 1.625em;
  width: 3.5em;
}

.toggle-switch--labels[aria-pressed="false"] span:after {
  right: 2.2em;
}

.toggle-switch--labels[aria-pressed="true"] span:before {
  color: rgba(255 ,255 ,255 ,1);
  content: "On";
  text-indent: .25em;
  text-shadow: 0 0 1px #000;
}

@media screen and (-ms-high-contrast: active) {
  .toggle-switch__ui:after {
    background-color: windowText;
  }
}

            
          
!
            
              /**
check for support and then add class to not style
color input for unsupported browsers
*/
(function () {
  var color = document.querySelector('[type="color"]');
  var i = document.createElement('input');
  i.setAttribute('type', 'color');

  if ( i.type === 'text' ) {
    color.classList.add('unsupported')
  }
})();

(function () {
  var color = document.querySelector('[type="week"]');
  var i = document.createElement('input');
  i.setAttribute('type', 'week');

  if ( i.type === 'text' ) {
    color.classList.add('unsupported')
  }
})();

/**
A quick list of what's exposed to Webkit:

Hook to style the file upload button
::-webkit-file-upload-button


Hook to style the Color swatch wrapper
::-webkit-color-swatch-wrapper
::-webkit-color-swatch


Number and Search input inner wrappers
::-webkit-textfield-decoration-container


Range
::-webkit-slider-runnable-track
::-webkit-slider-thumb


Dates and times
::-webkit-datetime-edit
::-webkit-datetime-edit-fields-wrapper
::-webkit-datetime-edit-month-field
::-webkit-datetime-edit-day-field
::-webkit-datetime-edit-text
::-webkit-datetime-edit-year-field
::-webkit-datetime-edit-week-field
::-webkit-datetime-edit-ampm-field
::-webkit-datetime-edit-minute-field


Inner input buttons:
Calendar popup buttons
::-webkit-calendar-picker-indicator

clear buttons
::-webkit-clear-button

spinner buttons
::-webkit-inner-spin-button


And here's Firefox's User Agent stylesheet for forms.
You must be view this in Firefox:
resource://gre-resources/forms.css

Here are the major selectors of note:
::-moz-color-swatch

input[type=range]::-moz-range-track 
	input[type=range][orient=block]::-moz-range-track 
	input[type=range][orient=horizontal]::-moz-range-track 
	input[type=range][orient=vertical]::-moz-range-track
input[type=range]::-moz-range-progress 
input[type=range]::-moz-range-thumb 


::-moz-meter-bar
	:-moz-meter-optimum::-moz-meter-bar
	:-moz-meter-sub-optimum::-moz-meter-bar
	:-moz-meter-sub-sub-optimum::-moz-meter-bar
::-moz-progress-bar

input::placeholder,
textarea::placeholder
  
input[type="color"]:-moz-focusring::-moz-focus-inner,
input[type=range]::-moz-focus-outer 
  
// can't appear to style
input[type=number]::-moz-number-wrapper
input[type=number]::-moz-number-text
input[type=number]::-moz-number-spin-box
input[type=number]::-moz-number-spin-up
input[type=number]::-moz-number-spin-down

*/



/*
  -ms- specific

::-ms-browse - file upload browse button
::-ms-clear  - text field
::-ms-reveal - password
::-ms-check  - checkboxes and radios

::-ms-expand - selects

::-ms-fill - progress

range slider
::-ms-fill-upper
::-ms-fill-lower 
::-ms-thumb
::-ms-ticks-after
::-ms-ticks-before
::-ms-track
::-ms-tooltip   -- only display and visibility
::-ms-value

*/







(function ( w, doc, undefined ) {
	'use strict';
	var A11yToggleButton;

	A11yToggleButton = function ( ) {
		/**
		 * Author: Scott O'Hara
		 * Version: 0.1.0
		 * License: https://github.com/scottaohara/a11y_styled_form_controls/blob/master/LICENSE
		 */
		var el;

		/**
		 * Initialize the instance, run all setup functions
		 * and attach the necessary events.
		 */
		this.init = function ( elm ) {
			el = elm;
			checkState ( el );
			setPressed ( el );
			setButton ( el );
			setClasses ( el );
			setSwitchUI ( el );
			attachEvents ( el );
		};

		/**
		 * Check default state of element:
		 * A toggle button is not particularly useful without JavaScript,
		 * so ideally such a button would be set to hidden or disabled, if JS wasn't
		 * around to make it function.
		 */
		var checkState = function ( el ) {
			// Unless a toggle button is specifically meant to be disabled,
			// when JS is available, remove the disabled attribute so these
			// buttons can be used.
			if ( el.getAttribute('data-toggle-btn') !== "disabled" ) {
				el.removeAttribute('disabled');
			}

			// reveal any hidden instances
			el.removeAttribute('hidden');
		};

		/**
		 * A toggle button won't register as a toggle button if an aria-pressed
		 * isn't present prior to user interaction.
		 *
		 * e.g. a button that is pressed, and then acquires an aria-pressed='true'
		 * attribute will NOT always be announced as a toggle button.
		 *
		 * Check for the presence of aria-pressed and if not there, run additional
		 * checks to determine if this button should be set to true or false by default.
		 */
		var setPressed = function ( el ) {
			if ( !el.hasAttribute('aria-pressed') ) {
				el.setAttribute('aria-pressed', el.hasAttribute('data-toggle-btn-pressed'))
			}
		}

		/**
		 * Enhance elements to buttons
		 * If the element is not a button, then add a role button.
		 * If it is not an a[href], or already have a tabindex, then
		 * provide a tabindex=0 so it can be keyboard focusable.
		 */
		var setButton = function ( el ) {
			if ( el.tagName !== 'BUTTON' ) {
				el.setAttribute('role', 'button');

				if ( !el.hasAttribute('href') && !el.hasAttribute('disabled') ) {
					el.tabIndex = 0;
				}
			}
		}

		/**
		 * Create Switch UI
		 * If a button is missing an inner element to
		 * wrap the accessible name and serve as the
		 * basis for the switch UI, then create a span
		 * and append it to the button element.
		 */
		var setSwitchUI = function ( el ) {
			var switchUI = el.querySelector('[data-toggle-btn-ui]') || el.querySelector('.toggle-switch__ui');

			if ( !switchUI ) {
				var newUI = doc.createElement('span');
				el.appendChild(newUI);
				switchUI = el.querySelector('span');
			}

			if ( !switchUI.classList.contains('toggle-switch__ui') ) {
				switchUI.classList.add('toggle-switch__ui');
			}

			// after confirming a switchUI element exists:
			switchUI.setAttribute('aria-hidden', 'true');
		};

		/**
		 * Setup the classes for the toggle buttons
		 */
		var setClasses = function ( el ) {
			// if the default class for this component doesn't exist, add it
			if ( !el.classList.contains('toggle-switch') ) {
				el.classList.add('toggle-switch');
			}

			// if a switch ui should display the text 'on' and 'off'
			if ( el.hasAttribute('data-switch-btn-labels') || el.classList.contains('toggle-switch--labels') ) {
				el.classList.add('toggle-switch--labels');
			};
		}

		/**
		 * Toggle the Button's state (aria-pressed=t/f)
		 */
		var toggleState = function ( e ) {
			this.setAttribute('aria-pressed', this.getAttribute('aria-pressed') === 'true' ? 'false' : 'true');
		};

		/**
		 * Attach keyEvents to toggle buttons
		 */
		var keyEvents = function ( e ) {
			var keyCode = e.keyCode || e.which;

			/**
			 * If the element is not a real button, then
			 * map the appropriate key commands.  If it is,
			 * well buttons' already know how to do this then :)
			 */
			if ( e.target.tagName !== 'BUTTON' ) {
				switch ( keyCode ) {
					case 32:
					case 13:
						e.stopPropagation();
						e.preventDefault();
						e.target.click();
						break;

					default:
						break;
				}
			}
		};

		/**
		 * Events for toggle buttons
		 */
		var attachEvents = function ( el ) {
			el.addEventListener('click', toggleState, false);
			el.addEventListener('keypress', keyEvents, false);
		};

		return this;
	}; // A11yToggleButton()

	w.A11yToggleButton = A11yToggleButton;
})( window, document );


 // some other file.js
var selector = '[data-switch-btn]';
var elList = document.querySelectorAll(selector);
var i;
var target = document.getElementById('target');
var swch = document.getElementById('swch');

for ( i = 0; i < elList.length; i++ ) {
  var a11ybtn = new A11yToggleButton();
  a11ybtn.init( elList[i] );
};

swch.addEventListener('click', function () {
  target.classList.toggle('styled')
})




            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console