FormFactor

Efficient, semantic, screen-reader-friendly form elements.

Ingredients:
<input>, <label>
  • HTML
    <label>
      Text
      <input type="text">
    </label>
    
    CSS
    /* Text Base */
    
    [type=text] {
      background: none;
      border-radius: 6px;
      border: 4px solid #403132;
      cursor: pointer;
      display: block;
      font: normal 400 24px/1.4 sans-serif;
      max-width: 100%;
      padding: 6px 12px;
      width: 15em;
    }
    
    /* Text States */
    
    [type=text]:focus {
      background: rgba(black, 0.1);
      transform: scale(1.05);
    }
    [type=text]:focus:hover {
      cursor: text;
    }
    [type=text]:hover {
      background: rgba(255, 255, 255, 0.4);
    }
    
    Animation
    /* Text Animation */
    
    [type=text] {
      transition: background 250ms ease-out, transform 150ms 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    
  • HTML
    <label>
      <input type="email">
    </label>
    
    CSS
    /* Email Base */
    
    [type=email] {
      background: none;
      border-radius: 6px;
      border: 4px solid #403132;
      cursor: pointer;
      display: block;
      font: normal 400 24px/1.4 sans-serif;
      max-width: 100%;
      padding: 6px 12px;
      width: 15em;
    }
    
    /* Email States */
    
    [type=email]:focus {
      background: rgba(black, 0.1);
      transform: scale(1.05);
    }
    [type=email]:focus:hover {
      cursor: text;
    }
    [type=email]:hover {
      background: rgba(255, 255, 255, 0.4);
    }
    
    Animation
    /* Email Animation */
    
    [type=email] {
      transition: background 250ms ease-out, transform 150ms 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    
  • HTML
    <label>
      <input type="number">
    </label>
    
    CSS
    /* Number Base */
    
    [type=number] {
      background: none;
      border-radius: 6px;
      border: 4px solid #403132;
      cursor: pointer;
      display: block;
      font: normal 400 24px/1.4 sans-serif;
      max-width: 100%;
      padding: 6px 12px;
      width: 7em;
    }
    
    /* Number States */
    
    [type=number]:focus {
      background: rgba(black, 0.1);
      transform: scale(1.05);
    }
    [type=number]:focus:hover {
      cursor: text;
    }
    [type=number]:hover {
      background: rgba(255, 255, 255, 0.4);
    }
    
    Animation
    /* Number Animation */
    
    [type=number] {
      transition: background 250ms ease-out, transform 150ms 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    
  • HTML
    <input type="checkbox" id="check" class="form-checkbox">
    <label for="check">Checkbox Label</label>
    
    CSS
    /* Checkbox Base */
    
    .form-checkbox {
      display: block;
      height: 0;
      position: absolute;
      right: 100%;
    }
    
    .form-checkbox + label {
      cursor: pointer;
      display: block;
      position: relative;
    }
    
    .form-checkbox + label::before {
      border-radius: 3px;
      box-shadow: 0 0 0 3px #403132;
      content: "";
      display: inline-block;
      height: 0.75em;
      margin-right: 0.5em;
      width: 0.75em;
    }
    
    .form-checkbox + label::after {
      background-color: #403132;
      border-radius: 2px;
      box-shadow: 0;
      color: #e7f4b4;
      content: "";
      display: block;
      height: calc(0.75em - 4px);
      left: 2px;
      opacity: 0;
      overflow: hidden;
      position: absolute;
      top: 0.3125em;
      transform: scale(0.4);
      width: calc(0.75em - 4px);
      z-index: 2;
    }
    
    /* Checkbox States */
    
    .form-checkbox + label:hover::before {
      background: rgba(255, 255, 255, 0.6);
    }
    
    .form-checkbox:active + label::before {
      background: rgba(0, 0, 0, 0.2);
      transform: scale(1);
    }
    
    .form-checkbox:focus + label::before {
      background: rgba(255, 255, 255, 0.6);
      transform: scale(1.2);
    }
    
    .form-checkbox:checked + label::after {
      transform: scale(1);
      opacity: 1;
    }
    
    Animation
    .form-checkbox + label::before {
      transition: background-color 250ms ease-out, transform 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    
    .form-checkbox + label::after {
      transition: opacity 100ms linear, transform 100ms ease-out;
    }
    
  • HTML
    <fieldset role="radiogroup">
      <input class="form-checkbox" id="radio" name="radio" type="radio">
      <label for="radio">Radio Label</label>
    </fieldset>
    
    CSS
    /* Radio Base */
    
    .form-radio {
      display: block;
      height: 0;
      position: absolute;
      right: 100%;
    }
    
    .form-radio + label {
      cursor: pointer;
      display: block;
      position: relative;
    }
    
    .form-radio + label::before {
      border-radius: 50%;
      box-shadow: 0 0 0 3px rgba(64, 49, 50, 0.2);
      content: "";
      display: inline-block;
      height: 0.75em;
      margin-right: 0.5em;
      width: 0.75em;
    }
    
    .form-radio + label::after {
      border-radius: 50%;
      box-shadow: inset 0 0 0 0 #403132, 0 0 0 2px #403132;
      content: "";
      display: inline-block;
      height: 0.75em;
      left: 0;
      opacity: 0;
      overflow: hidden;
      position: absolute;
      top: 0.25em;
      width: 0.75em;
      z-index: 2;
    }
    
    /* Radio States */
    
    .form-radio:checked + label::before {
      box-shadow: 0 0 0 3px #403132;
    }
    
    .form-radio:checked + label::after {
      box-shadow: inset 0 0 0 5px #403132, 0 0 0 2px #403132;
      opacity: 1;
    }
    
    .form-radio:focus + label::before {
      -webkit-transform: scale(1.2);
      transform: scale(1.2);
    }
    
    .form-radio:hover + label::before {
      background-color: #f8fce8;
      box-shadow: 0 0 0 3px #403132;
    }
    
    .form-radio:active + label::before{
      background-color: rgba(0, 0, 0, 0.2);
    }
    
    Animation
    /* Radio Animation */
    
    .form-radio + label::before {
      transition: background-color 100ms ease-out, box-shadow 150ms ease-out, -webkit-transform 100ms cubic-bezier(0, 0.5, 0.5, 1);
      transition: background-color 100ms ease-out, box-shadow 150ms ease-out, transform 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    .form-radio + label::after {
      transition: box-shadow 150ms ease-out, opacity 100ms linear;
    }
    
  • HTML
    <input class="form-switch" id="switch" type="text" value="on">
    <label for="switch">Switch Below</label>
    
    CSS
    /* Switch Base */
    
    .form-switch {
      display: block;
      height: 0;
      position: absolute;
      right: 100%;
    }
    
    .form-switch + label {
      display: block;
      margin-bottom: 2em;
      position: relative;
      visibility: visible;
    }
    
    .form-switch + label::before {
      background: rgba(0, 0, 0, 0.2);
      border-radius: 2em;
      border: 4px solid #403132;
      content: "Off";
      display: block;
      font-size: 50%;
      height: 2em;
      left: 0;
      line-height: 2;
      padding: 0 1em 0 3em;
      position: absolute;
      text-align: center;
      top: 100%;
      width: 2em;
      z-index: 10;
    }
    
    .form-switch + label::after {
      background: #e7f4b4;
      border-radius: 1em;
      border: 4px solid #403132;
      content: "";
      display: block;
      height: 1em;
      left: 0;
      position: absolute;
      top: 100%;
      width: 1em;
      z-index: 11;
    }
    
    /* Switch States */
    
    .form-switch + label:hover {
      cursor: pointer
    }
    
    .form-switch:checked + label::before {
      background: white;
      content: "On";
      padding: 0 3em 0 1em;
    }
    
    .form-switch:checked + label::after {
      transform: translateX(2em);
    }
    
    .form-switch:focus + label::after,
    .form-switch + label:hover::after {
      background-color: #f8fce8;
    }
    
    Animation
    /* Switch Animation */
    
    .form-switch + label::before {
      transition: background 150ms ease-out, padding 100ms ease-out;
    }
    
    .form-switch + label::after {
      transition: background 150ms linear, transform 150ms cubic-bezier(1, 0, 0, 1);
    }
    
  • HTML
    <input class="form-switch" id="switch" name="switch" type="text" value="on">
    <label for="switch">Switch Beside</label>
    
    CSS
    /* Switch Base */
    
    .form-switch {
      display: block;
      height: 0;
      position: absolute;
      right: 100%;
    }
    
    .form-switch + label {
      display: block;
      margin-left: 3.33em;
      padding-left: 0.625em;
      position: relative;
      visibility: visible;
    }
    
    .form-switch + label::before {
      background: rgba(0, 0, 0, 0.2);
      border-radius: 2em;
      border: 4px solid #403132;
      content: "Off";
      display: block;
      font-size: 50%;
      height: 2em;
      line-height: 2;
      padding: 0 1em 0 3em;
      position: absolute;
      right: 100%;
      text-align: center;
      top: 0;
      width: 2em;
      z-index: 10;
    }
    
    .form-switch + label::after {
      background: #e7f4b4;
      border-radius: 1em;
      border: 4px solid #403132;
      content: "";
      display: block;
      height: 1em;
      position: absolute;
      right: 100%;
      top: 0;
      transform: translateX(-2em);
      width: 1em;
      z-index: 11;
    }
    
    /* Switch States */
    
    .form-switch + label:hover {
      cursor: pointer
    }
    
    .form-switch:checked + label::before {
      background: white;
      content: "On";
      padding: 0 3em 0 1em;
    }
    
    .form-switch:checked + label::after {
      transform: translateX(0);
    }
    
    .form-switch:focus + label::after,
    .form-switch + label:hover::after {
      background-color: #f8fce8;
    }
    
    Animation
    /* Switch Animation */
    
    .form-switch + label::before {
      transition: background 150ms ease-out, padding 100ms ease-out;
    }
    
    .form-switch + label::after {
      transition: background 150ms linear, transform 150ms cubic-bezier(1, 0, 0, 1);
    }
    
  • HTML
    <label>
      Select
      <select>
        <optgroup label="Group A">
          <option>Option 1</option>
          <option>Option 2</option>
        </optgroup>
        <optgroup label="Group B">
          <option>Option 3</option>
        </optgroup>
      </select>
    </label>
    
    CSS
    /* Select Base */
    
    select {
      -webkit-appearance: none;
      background-color: transparent;
      background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjMjMxRjIwIiBkPSJNNTEyIDY4LjZMMjU2IDUxMiAwIDY4LjZ6Ii8+PC9zdmc+);
      background-position: 90% 50%;
      background-repeat: no-repeat;
      background-size: auto 25%;
      border-radius: 12px;
      border: 4px solid #403132;
      display: block;
      padding: 6px 48px 6px 12px;
    }
    
    /* Select Browser Hacks */
    @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
      select::-ms-expand {
        display: none;
      }
      select:focus::-ms-value {
        background: transparent;
        color: #222;
      }
    }
    @-moz-document url-prefix() {
      select {
        background-image: none;
      }
     }
    select::-moz-focusring {
      color: transparent;
      text-shadow: 0 0 0 #000;
    }
    
    
    Animation
    select {
      transition: background-color 250ms ease-out, -webkit-transform 150ms 100ms cubic-bezier(0, 0.5, 0.5, 1);
      transition: background-color 250ms ease-out, transform 150ms 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    select:hover {
      background-color: rgba(255, 255, 255, 0.4);
      cursor: pointer;
    }
    select:focus, .form-select:hover {
      background-color: rgba(255, 255, 255, 0.4);
      outline: none;
    }
    
    
  • HTML
    <label>
      Date
      <input type="date">
    </label>
    
    CSS
    /* Date Base */
    
    [type=date] {
      background: none;
      border-radius: 6px;
      border: 4px solid #403132;
      cursor: pointer;
      display: block;
      font: normal 400 24px/1.4 sans-serif;
      max-width: 100%;
      padding: 6px 12px;
      width: 15em;
    }
    
    /* Date States */
    
    [type=date]:focus {
      background: rgba(black, 0.1);
      transform: scale(1.05);
    }
    [type=date]:focus:hover {
      cursor: text;
    }
    [type=date]:hover {
      background: rgba(255, 255, 255, 0.4);
    }
    
    Animation
    /* Date Animation */
    
    [type=date] {
      transition: background 250ms ease-out, transform 150ms 100ms cubic-bezier(0, 0.5, 0.5, 1);
    }
    
  • HTML
    <label>
      Color
      <input type="color">
    </label>
    
    CSS
    /* Color Base */
    
    [type=color] {
      background-color: transparent;
      background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zd…02NC4xIDExMi4yLTExMi4yYzI2LjUtMjYuNSAyNi41LTY5LjYgMC05Ni4xeiIvPjwvc3ZnPg==);
      background-position: 90% 50%;
      background-repeat: no-repeat;
      background-size: auto 50%;
      border-radius: 6px;
      border: 4px solid #403132;
      cursor: pointer;
      display: block;
      height: 48px;
      padding: 0 48px 0 0;
      width: 5em;
    }
    
  • HTML
    <label>
      Range
      <input type="range">
    </label>
    
    CSS
    /* Range Base */
    
    [type=range] {
      background: none;
      cursor: pointer;
      display: block;
      height: 48px;
      width: 10em;
    }
    
    /* Webkit */
    
    [type=range] {
      -webkit-appearance: none;
    }
    
    [type=range]::-webkit-slider-runnable-track {
      background: #403132;
      border-radius: 4px;
      border: none;
      height: 4px;
    }
    
    [type=range]::-webkit-slider-thumb {
      -webkit-appearance: none;
      background: #e7f4b4;
      border-radius: 50%;
      border: 4px solid #403132;
      height: 24px;
      width: 24px;
      /* Webkit alignment hack */
      margin-top: 2px;
      transform: translateY(-50%);
    }
    
    [type=range]:focus::-webkit-slider-thumb,
    [type=range]:hover::-webkit-slider-thumb {
      background: #f8fce8;
    }
    
    /* Firefox */
    
    [type=range]::-moz-range-track {
      background: #403132;
      border-radius: 4px;
      border: none;
      height: 4px;
    }
    
    [type=range]::-moz-range-thumb {
      background: #e7f4b4;
      border-radius: 50%;
      border: 4px solid #403132;
      height: #403132;
      width: #403132;
    }
    
    [type=range]:hover::-moz-range-thumb,
    [type=range]:focus::-moz-range-thumb {
      background: #f8fce8;
    }
    
    /* IE */
    
    [type=range]::-ms-track {
      background: rgba(64, 49, 50, 0.7);
      border-radius: 4px;
      border: none;
      height: 4px;
    }
    
    [type=range]::-ms-fill-lower {
      background: #403132;
      border-radius: 4px;
    }
    
    [type=range]::-ms-fill-upper {
      background: none;
    }
    
    [type=range]::-ms-thumb {
      background: #e7f4b4;
      border-radius: 50%;
      border: 4px solid #403132;
      height: 24px;
      width: 24px;
    }
    
    [type=range]:hover::-ms-thumb,
    [type=range]:focus::-ms-thumb {
      background: #f8fce8;
    }
    
    Animation
    /* Range Animation */
    
    [type=range]::-webkit-slider-thumb {
      transition: background-color 250ms ease-out;
    }
    
    [type=range]::-moz-range-thumb {
      transition: background-color 250ms ease-out;
    }
    
    [type=range]::-ms-thumb {
      transition: background-color 250ms ease-out;
    }
    
  • HTML
    <input type="submit">
    
    CSS
    /* Submit Base */
    
    [type=submit] {
      background: #403132;
      border-radius: 6px;
      border: 4px solid #403132;
      color: #e7f4b4;
      padding: 12px 24px;
    }
    
    Animation
    /* Submit Animation */
    
    [type=submit] {
        transition: background 250ms ease-out;
    }
    [type=submit]:hover {
      background: rgba(64, 49, 50, 0.8);
    }
    [type=submit]:active {
      box-shadow: none;
      -webkit-transform: translateY(2px);
      transform: translateY(2px);
    }