kulturbanause Blog

Responsive Design, WordPress, Konzeption, HTML, CSS, JS & UX/UI …

Formular-Styling mit CSS – Select-Listen, Radio-Buttons und Checkboxen individuell gestalten

Die Gestaltung von Formularfeldern gehört zu den eher lästigen Aufgaben eines Web-Designers. Insbesondere Select-Listen, Radio-Buttons und Checkboxen ließen sich lange Zeit kaum mit CSS ansprechen, so dass für gewöhnlich mit JavaScript nachgeholfen werden musste, wenn eine individuelle Gestaltung gewünscht war. Mittlerweile lassen sich Formularfelder in modernen Browsern ohne JavaScript individuell gestalten. In diesem Zusammenhang möchte ich einige CSS-Snippets archivieren.

Workshops und Seminare von kulturbanause

Visual Prototyping, Responsive Design, CSS Grid & Flexbox, WordPress, Adobe XD, HTML & CSS Grundlagen, Website-Optimierung …

Jetzt Frühbucher-Rabatte sichern!

appearance: none;

Mit Hilfe des CSS-Befehls appearance: none; kann die Standard-Gestaltung von Bedienelementen im Browser deaktiviert werden. Das ist nicht nur hilfreich um Selectlisten, Radio-Buttons und Checkboxen zu gestalten, sondern auch um das Standard-Styling von Suchfeldern, Buttons und weiteren UI-Elementen zu entfernen, deren Gestaltung zunehmend vom Browser übernommen wird. Der appearance-Befehl ermöglicht es übrigens auch, dass Standard-Styling des Browsers/OS bewusst zuzuweisen.

Progressive Enhancement

Der appearance-Befehl funktioniert nicht im Internet Explorer. Damit es in alten Versionen des Browsers (<=IE9) nicht zu unerwünschten Effekten kommt, behalten wir in inkompatiblen Systemen das Standard-Aussehen der Eingabefelder bei. Nach dem Prinzip des Progressive Enhancement gestalten wir die Felder nur dann, wenn der Browser den Befehl auch unterstützt.

Select-Listen gestalten

Die individuelle Gestaltung von Select-Listen ist einfach. Über den appearance-Befehl entfernen wir zunächst das Standard-Styling.


/* remove standard-styles */
select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border:none;
  border-radius: 0;
  font-size: 1em;
  width: 100%
} 

Anschließend gestalten wir das Element mit CSS unseren Vorstellungen entsprechend. Ein individuelles Pfeil-Icon weisen wir in diesem Beispiel als CSS-background-image zu – eine DataURI bietet sich ebenfalls an.


/* styling */
select {
  width:100%;
  border: 1px solid #bbb;
  padding:.75em 1em .5em 1em;
  box-shadow: 0 2px 1px 0 rgba(0,0,0,0.2);
  background-color:white;
  background-image:url(select-arrow.png);
  background-position: right;
  background-repeat: no-repeat;
}

select:hover {
  box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
}

Die Select-Liste im Vergleich: IE8, IE9, IE10 und – stellvertretend für die modernen Browser – Chrome
Die Select-Liste im Vergleich: IE8, IE9, IE10 und – stellvertretend für die modernen Browser – Chrome

Damit der Internet Explorer 10 den Pfeil des Browsers ebenfalls verliert, ist ein kleiner Hack nötig.


/* hide browser-styling (arrow) in IE10 */
select::-ms-expand {
  display:none;
}

Die inkompatiblen Browser (IE8 & IE9) identifizieren wir hier mit einer CSS-Klasse, die über einen Conditional Comment eingefügt wurde. Auch hier sind verschiedene Herangehensweisen denkbar. Wir entfernen somit die Pfeil-Grafik, da ansonsten zwei Pfeile in der Select-Liste angezeigt würden.


.lt-ie10 select {
    background-image: none;
}

Das option-Element gestalten

Das Drop-Down-Element der Select-Liste (<option>) lässt sich nur sehr eingeschränkt mit CSS ansprechen. In Webkit-Browsern haben wir – sofern ich recht informiert bin – keine Möglichkeit das <option>-Element zu gestalten. Firefox hingegen verwendet für <option> die Hintergrund- und Textfarbe des <select>-Elements, sofern <option> nicht selbst angesprochen wurde.

Gestaltetes option-Element in Firefox
Gestaltetes option-Element in Firefox

Mit folgendem Code erreicht ihr daher im Firefox eine Darstellung wie im Screenshot zu sehen:


select {
  /* irrelevante Eigenschaften gekürzt */
  border: 1px solid black;
  padding:.75em 1em .5em 1em;
  box-shadow: 0 2px 1px 0 rgba(0,0,0,1);
  background-color:#333;
  color:white;
}

option {
  background:#222;
  border-top:1px solid #444;
  padding:.3em 1em .3em 1em;
}

Radio-Buttons und Checkboxen gestalten

Radio-Buttons und Checkboxen benötigen etwas mehr Arbeit. Zunächst erledigen wir die Basis-Gestaltung für alte Versionen des Internet Explorers: Wir behalten die Browser-Standards bei, und passen nur die Positionierung und die Abstände ein wenig an.

Radio-Buttons und Checkboxen im Vergleich: IE8, IE9, IE10 und – stellvertretend für moderne Browser – Chrome
Radio-Buttons und Checkboxen im Vergleich: IE8, IE9, IE10 und – stellvertretend für moderne Browser – Chrome

In modernen Browsern blenden wir die Standard-UI-Element für Radio-Buttons und Checkboxen komplett aus. Wir identifizieren die modernen Browser über die Pseudoklasse :checked. Alle Browser die :checked verstehen, sind auch in der Lage die anderen notwendigen Befehle zu interpretieren.



/* remove standard-styles */
input {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border:none;
  border-radius: 0;
  font-size: 1em;
  width: 100%
} 

/* graceful degradation for ie8 */
input[type='checkbox'],
input[type='radio'] {
  width:auto;
  float:left;
  margin-right: .75em;
  background:transparent;
  border:none;
}

input[type='checkbox']:checked,
input[type='checkbox']:not(:checked),
input[type='radio']:checked,
input[type='radio']:not(:checked) {
  background: transparent;
  position: relative;
  visibility: hidden;
  margin:0;
  padding:0;
}

input[type='checkbox'] + label,
input[type='radio'] + label {
  cursor: pointer;
}

Nachdem wir die Standard-UI-Elemente versteckt haben, fügen wir Sie als ::before-Pseudoelement des jeweiligen <label>-Elements wieder ein. Da man die Auswahlfelder auch durch Klicken auf <label> aktivieren kann, nutzen wir anschließend die Pseudoklasse :checked um das Pseudoelement ::before mit CSS umzugestalten, sobald ein Radio-Button oder eine Checkbox aktiviert wurde. Hier kann anstelle der schlichten CSS-Gestaltung natürlich auch eine Grafik eingesetzt werden.


input[type='checkbox']:checked + label::before,
input[type='checkbox']:not(:checked) + label::before,
input[type='radio']:checked + label::before,
input[type='radio']:not(:checked) + label::before {
    content:' ';
    display:inline-block;
    width: 17px;
    height:17px;
    position: relative;
    top:4px;
    border: 1px solid #bbb;
    background: white;
    margin-right: 1em;
    box-shadow: inset 0 1px 1px 0 rgba(0,0,0,.1);
}

input[type=radio]:checked + label::before,
input[type=radio]:not(:checked) + label::before {
  border-radius: 30px;
}

input[type='checkbox']:hover  + label::before,
input[type='radio']:hover  + label::before {
  background:#ddd;
  box-shadow: inset 0 0 0 2px white;
}

input[type='checkbox']:checked  + label::before,
input[type='radio']:checked  + label::before {
  background:black;
  box-shadow: inset 0 0 0 2px white;
}

Vollständiges Beispiel

Das Beispiel mit zusammengefassten Code-Passagen und zusätzlichem Styling für Textfelder könnt ihr euch hier anschauen.

Beispiel anzeigen

Jetzt bist du gefragt!

Hast du Anregungen, Ergänzungen, einen Fehler gefunden oder ist dieser Beitrag nicht mehr aktuell? Dann freuen wir uns auf deinen Kommentar.

Du kannst diesen Beitrag natürlich auch weiterempfehlen. Wir sind dir für jede Unterstützung dankbar!

Das könnte dich auch interessieren

21 Kommentare

  1. Birgit

    Verfasst am 23. März 2015 um 14:15 Uhr.

    Super, vielen Dank für die ausführliche Anleitung! Listen sind ein Horror für mich ;-)
    Wo es bei mir jedoch immer hakt, sind nicht die Settings, die du oben beschrieben hast, sondern wenn ich eben diesen eine bestimmte Klasse zusätzlich zuordnen muss, um z.B. die Standard-Listen-Settings meines WP-Themes n i c h t zu überschreiben.
    Da weiß ich dann nie, wie man dann die Listenbefehle korrekt schreibt:
    .meineliste .input oder umgekehrt oder ohne Leerraum … Vielleicht eine Option für einen neuen Blogpost von dir? :-)

  2. Hans

    Verfasst am 30. März 2015 um 9:30 Uhr.

    phantastisch, „appearance“ ist toll, nie von gehört. habe bis jetzt immer select listen in einen wrapper getan und einfach 30PX rechts rausgeschoben so das man den pfeil nicht sieht, der nachteil ist halt das die ausgeklappte liste dann breiter ist.

  3. Alex

    Verfasst am 3. Mai 2015 um 18:41 Uhr.

    Sehr cooler Beitrag. Weshalb nutzt du :not(checked)? Ich habe eben mal etwas rumgespielt und da funktioniert auch alles ohne diese Angabe, ist ja sozusagen die Standardformatierung oder hat das noch einen Grund?

    • Jonas Hellwig

      Verfasst am 3. Mai 2015 um 21:17 Uhr.

      Mit :not(checked) können unerwünschte Effekte in Browsern die :checked nicht verstehen verhindert werden. Die Fallback-Lösungen in alten IEs sind somit einfacher, also mit weniger Code, umsetzbar.

  4. Florence Maurice

    Verfasst am 6. Mai 2015 um 15:34 Uhr.

    Schöne Techniken!

    ein Nachteil ist nur, dass sich die so gestylten Radio- und Checkboxen nicht mehr per Tastatur auswählen lassen (getestet gerade auf Firefox und Chrome).
    Abhilfe besteht wahrscheinlich darin, dass man eine andere Technik zum Verbergen der ursprünglichen Radiobuttons/checkboxen verwendet; also nicht auf visibility: hidden setzt.
    Bei jQuery Mobile etwa lassen sich die Radiobuttons/Checkboxen auch mit der Tastatur bedienen: Die nativen Inputs werden absolut positioniert und durch einen niedrigeren z-index von den gestalteten Elementen mit höherem z-index verdeckt.

    • Carsten A.

      Verfasst am 26. August 2016 um 9:21 Uhr.

      Hallo Florence,

      der Übeltäter ist die CSS-Eigenschaft visibility:hidden. Wenn man diese durch opacity:0 ersetzt, bleibt das Element im auswählbaren Context erhalten und ist einfach 100% transparent.
      Was fehlt ist, dass man genau so wie :checked gestylet wurde, auch für :focus stylet (und z.B. einen blauen Rahmen und Schatten vergibt – ähnlich wie bei Textfeldern), damit man auch sehen kann auf welchem Element der Fokus durch Tastaturauswahl liegt.

      Ich habe für mich neben der oben beschriebenen Änderung auch folgendes in dem Beispiel vom Autor ergänzt:

      input[type=’checkbox‘]:focus + label::before, input[type=’radio‘]:focus + label::before {
      border-color: rgb(156,190,245);
      box-shadow: 0 0 0px 1px rgb(156,190,245), inset 0 0 0 2px white;
      }

      Beste Grüße,
      Carsten

  5. Ruth Richter

    Verfasst am 5. August 2015 um 14:46 Uhr.

    Vielen Dank für diesen konstruktiven Beitrag Schade dass dieser nicht als erster Eintrag in Google gefunden wird, war Zufall aber hat mir geholfen und hat mich beeindruckt.

  6. Michael

    Verfasst am 11. Dezember 2015 um 13:52 Uhr.

    leider fehlen die folgenden (für eine Radio box) Standard Effekt
    – Focused-Effect
    – Tastursteuerung
    – Tabindex-Support

  7. Wanst

    Verfasst am 23. Februar 2016 um 15:30 Uhr.

    Hi, soweit ganz gut, aber kann man die OPTIONs und OPTGROUPs eines SELECT-Feldes auch so gestalten, dass es ein IE oder Webkit-Browser darstellt? Bei mir klappt das zwar im FF, aber die anderen ignorieren die Anweisungen einfach und kochen ihr eigenes Süppchen.

    Danke!

    • Carsten A.

      Verfasst am 26. August 2016 um 8:58 Uhr.

      Hallo Wanst,

      das ist leider nicht möglich. Die genannten Browser verwenden zur Darstellung und für die Funktion an sich Systemelemente des Betriebssystems. Deswegen sehen diese, trotzdem man den gleichen Browser verwenden, auf unterschiedlichen Betriebssystemen (z.B. Mac OS gegenüber Windows) auch unterschiedlich aus.
      Einzige Abhilfe wäre das Element und dessen Funktionalitäten mit eigenem HTML, CSS und Javascript nachzubauen. Es gibt auch bereits fertige Javascript-Bibliotheken im Netz, mit denen man ein normales Select pflegt, aber frei style-bare Elemente generiert werden.

      Beste Grüße,
      Carsten

  8. Mafrieger

    Verfasst am 4. April 2016 um 16:23 Uhr.

    schicker Beitrag! Danke!

    Zur Weiterentwicklung:

    1) Hier gibts ein Beispiel mit schönen Symbolen aus fontawesome:
    http://codepen.io/rstrahl/pen/yyEYBx

    2) und hier gibts nen Ansatz der Tastatursteuerung erlaubt:
    http://weblog.west-wind.com/posts/2015/Feb/26/Using-FontAwesome-Fonts-for-HTML-Radio-Buttons-and-Checkboxes

    das jetzt zusammen mit der im obigen Beitrag beschrieben „Browserweiche“
    wäre doch die perfekte Lösung – oder?

    => vielleicht ein guter Anlass für eine Aktualisierung des Blogbeitrags?
    Oder eine Fortsetzung?

  9. Hella

    Verfasst am 19. April 2016 um 12:39 Uhr.

    Sehr schön, aber was mach ich, wenn ich kein Label habe? (Skala steht oben, mehrere Fragen darunter, somit kein Label am Radio-Button)

    Ich bin leider auf keine Lösung gekommen, denn wenn ich die checkbox verstecke, kann ich ja :before und :after nicht mehr nutzen.

    • Carsten A.

      Verfasst am 26. August 2016 um 8:53 Uhr.

      Hallo Hella,

      die Pseudoelemente :before und :after funktionieren sowieso nicht an Elementen, sondern nur an Elementen, die auch echte Kind-Elemente aufnehmen können.
      Man wird also nicht darum herumkommen ein solches Element noch zu den Radio-Buttons hinzuzufügen. Ein Label-Element hat zu dem den Vorteil, das man es einem Input-Element zuordnen kann. Dadurch werden Klicks auf ein Label behandelt wie Klicks auf das Input-Feld selbst (wodurch man u.A. Checkboxen umschalten, Radiobuttons auswählen und Textfelder fokussieren kann).

      Beste Grüße,
      Carsten

      • Florence Maurice

        Verfasst am 7. September 2016 um 12:33 Uhr.

        danke, Carsten, für deine äußerst nützlichen Anmerkungen!

  10. Jens Trainer

    Verfasst am 17. August 2016 um 10:15 Uhr.

    Danke für die Übersicht!
    Besonders das Styling der Checkboxen hat mich Stunden gekostet.

  11. Jens Ubert

    Verfasst am 7. November 2016 um 9:56 Uhr.

    Wunderbare Lösung! Viel gelernt durch Dein Tutorial und Beispiel.
    Da ist aber noch eine Kleinigkeit. Checkboxen benötigen im Firefox scheinbar ein paar Punkte mehr Platz nach links als im Chrome, sie werden also im Firefox etwas weiter rechts dargestellt. Nun versuche ich dieses zu verhindern, so dass die Position zumindest in etwa identisch ist und wie im Chrome dargestellt wird.
    Gibt es da ein Workaround?

  12. Torsten Jerschabek

    Verfasst am 14. November 2016 um 9:23 Uhr.

    Vielen Dank für die tolle Anleitung. Ich habe lange gesucht nach guten Ressourcen für das Formularstyling. Hat mir sehr geholfen und viel Zeit gespart.

  13. maik

    Verfasst am 13. März 2017 um 8:53 Uhr.

    hi, die Anleitung ist super. Brauche gerade genau das.
    Allerdings, wie kriege ich die labels neben die boxen horizontal zentriert wenn ich die boxen und die radios größer mache?

  14. Karl

    Verfasst am 26. Juli 2017 um 17:53 Uhr.

    Das sind alles super Sachen!
    Doch habe ich da noch eine Frage.
    Kann man programmieren, dass bei einem ausgeklappten Selectfeld alle Einträge auf einer Seite stehen? Dann ist es nämlich übersichtlicher und man muss nicht scrollen.

  15. Aleksandar

    Verfasst am 8. September 2017 um 10:41 Uhr.

    Vielen Dank für die tolle Anleitung. Hat mir sehr geholfen und viel Zeit gespart.

Kommentar verfassen

Dieser Blog lebt vom Feedback der Besucher! Also los, mach mit!
Bitte habe Verständnis dafür, dass Kommentare die mit dem Inhalt dieses Beitrags nichts zu tun haben, gelöscht werden.