DropDown mit Hilfe von CSS3 stylen, Mockup

Dropdown mit CSS3 gestalten

Eine der größten Herausforderungen für den geneigten Frontend-Entwickler ist das Stylen von Formularfeldern. Die kleinteilige Arbeit, spezielle Wünsche der Grafikabteilung und zahlreiche Browser-Besonderheiten bringen den Programmierer hier regelmäßig an seine Geduldsgrenze. Die Lösung ist meist der Einsatz von jQuery-Plugins, über die das zugrundeliegende HTML komplett umgebaut wird – eine nicht immer so elegante Lösung. Beispielsweise wird auch das native Standardverhalten von Dropdowns auf mobilen Endgeräten unterbunden, was nicht immer gewollt ist.

CSS3 erleichtert uns die Arbeit mittlerweile etwas und stellt Möglichkeiten zur Verfügung, das Aussehen von Formularfeldern ohne Zuhilfenahme von JavaScript zu beeinflussen. In diesem kurzen Tutorial wollen wir davon Gebrauch machen und ein optisch ansprechendes Select-Auswahlfeld gestalten. Dieses soll einen transparenten Hintergrund, Schatten und abgerundete Ecken erhalten. Außerdem wird ein individueller Pfeil vergeben, den wir aus der OpenSource-Icon-Schriftart FontAwesome entnehmen und über fontello integrieren.

Das Grundgerüst

Das HTML halten wir so simpel wie möglich und setzen ein einfaches <select> auf einen grünen Hintergrund. Die einzige Veränderung, die wir zu Beginn vornehmen, ist ein Wrapper mit der CSS-Klasse „select-wrapper“, den wir um das Element legen und dem wir eine Breite von 200px mitgeben. Wir werden diesen später benötigen, wenn wir den Pfeil integrieren.

<div class="select-wrapper">
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
  </select>
</div>
.select-wrapper {
  width: 200px;
}

Ungestylt schaut das <select> recht trostlos aus (links), unser Ziel ist die Vorlage (rechts), in der das Element auf eine ansprechende Art und Weise mit dem Hintergrund harmoniert:

Dropdown ungestylt Dropdown gestylt

Browser-Styles entfernen

Im ersten Schritt reduzieren wir die Standard-Formatierung der zu berücksichtigenden Browser auf ein Minimum. Wir erreichen das über die CSS3-Eigenschaft „appearance“, die wir auf „none“ setzen. Hierbei müssen wir beachten, dass wir Präfixe für die Browser Chrome, Safari und Firefox vergeben. Außerdem entfernen wir den auffälligen Rahmen.

select {
  -moz-appearance: none;
  -webkit-appearance: none;
  appearance: none;
  border: none;
}

Nun sollte es in fast allen Browsern ungefähr so ausschauen:

Dropdown ohne Browser-Styling

In fast allen? Ganz recht! Der Internet Explorer macht uns hier noch einen Strich durch die Rechnung und zeigt uns nach wie vor den Standard-Pfeil an. Wir schreiben dem IE daher eine Extra-Einladung mit folgendem Code-Schnipsel:

select::-ms-expand {
  display: none;
}

Nun kann es aber mit dem eigentlichen Styling losgehen.

Abstände und transparenter Hintergrund

Wir kümmern uns als nächstes darum, dem Element ein wenig Innenabstand zu geben. Dazu können wir ganz einfach mit width, height und padding arbeiten. Da wir für den übergeordneten Wrapper bereits eine Breite vergeben haben, strecken wir das <select> auf 100%. Beim padding ist zu beachten, dass der Firefox einen minimalen Abstand von Haus aus generiert, den wir mit der folgenden zusätzlichen Zeile angleichen können (siehe Kommentar von Guido Jansen unter diesem Beitrag):

-moz-padding-start: calc(10px - 3px);

Da wir im <select> nicht mit der CSS-Eigenschaft „opacity“ arbeiten können, verwenden wir für den Hintergrund ein transparentes Pixel im PNG-Format, das wir in x- und y-Richtung wiederholen. Wer sich die Arbeit sparen möchte, für das Pixel sein Grafikprogramm zu öffnen, kann sich hier z.B. auch einfach eines generieren lassen: www.1x1px.me.

Mit dem folgenden CSS haben wir uns unserer Vorlage ein großes Stück angenähert:

select {
  /* ... */
  width: 100%;
  height: 40px;
  -moz-padding-start: calc(10px - 3px);
  padding-left: 10px;
  background: url(fff-0-2.png) repeat;
  color: #fff;
  font-family: 'Open Sans', sans-serif;
  font-size: 16px;
}

 

Dropdown mit transparentem Hintergrund

Schatten hinzufügen, Ecken abschleifen, Bugs fixen

Die Eigenschaften „border-radius“ und „box-shadow“ geben unserem Element den nötigen Feinschliff. Ein transparentes Schwarz soll als Schatten genügen:

select {
  /* ... */
  box-shadow: 2px 2px 5px 1px rgba(0,0,0,0.3);
  border-radius: 3px;
}

Die Browser bringen nach wie vor noch einige unschöne Besonderheiten mit sich, die wir aber verändern können. Im Chrome fällt uns auf, dass ein unschöner, blauer Rahmen gezeichnet wird, wenn wir das Element fokussieren. Dieses Verhalten kann leicht modifiziert werden:

select {
  /* ... */
  outline: none;
}

Während die mobilen Geräte alle brav ihre nativen Menüs bei Touch auf das <select> aufklappen, fällt uns in den Desktop-Browsern auf unangenehme Art und Weise auf, dass sich die weiße Schriftart, die wir verwendet haben, auch auf die Auswahlliste auswirkt. Entsprechend setzen wir hier unsere Schriftfarbe zurück:

select option {
  color: #666;
}

Zu guter letzt fühlen wir dem Internet Explorer nochmal richtig auf den Zahn und werden fündig: Nachdem wir eine Option markiert haben, verfärbt sich das <select> unschön. Aber auch das können wir beeinflussen:

select:focus::-ms-value {
  background-color: transparent;
}

Für das optimale „Button-Click-Feeling“ fehlt uns nur noch ein kleines Detail: Wir verändern beim Hovern unseren Mauszeiger!

select {
  /* ... */
  cursor: pointer;
}

Ein Detail: Der Pfeil!

Beinah könnte unser Dropdown jetzt als Button durchgehen, doch das lassen wir nicht zu und holen uns das Dropdown-Aussehen zurück, indem wir den Pfeil aus fontello über dem <select> positionieren. Dabei stellen wir schnell fest, dass das auf dem <select> selbst nicht möglich ist. Nun kommt also unser Wrapper ins Spiel, den wir relativ positionieren. So können wir den Pfeil einfach als :before-Element einbinden und diesen absolut positioniert in den Wrapper legen. Das könnte im Stylesheet ungefähr so ausschauen:

.select-wrapper {
  /* ... */
  position: relative;
}

.select-wrapper::before {
  font-family: fontello;
  content: "\f107";
  font-size: 20px;
  position: absolute;
  right: 15px;
  top: 10px;
  color: #fff;
}

Die Einbindung über fontello haben wir in einem vorangegangen Beitrag bereits thematisiert.

Ein kleines Detail fehlt aber noch. Zwar erscheint der Pfeil an der richtigen Position, aber natürlich soll er auch klickbar sein und das <select> öffnen. Wir behelfen uns dazu mit einem Trick und lassen das klickbare <select> sozusagen „durchscheinen“:

.select-wrapper::before {
  /* ... */
  pointer-events: none;
}

Fertig! Wir überprüfen noch einmal unser <select> in allen Browsern und auf allen Geräten und sind mit dem Ergebnis ganz zufrieden.

Dropdown gestylt

Wer weitere Anregungen, Ideen oder Ergänzungen zum Thema hat, darf sich gern in den Kommentaren dazu austoben.

  • 05/12/2017

    Kommentar von Ron

    Hi,
    wäre vielleicht ganz cool, wenn Du an dieser Stelle das Einbinden über Fontello erläuterst.
    Das erspart viel googlen. Und wenn Du Dir schon so viel Arbeit machst, den Style zu erklären, sollte so etwas dazu gehören.

    • 13/12/2017

      Kommentar von Christoph

      Hallo Ron,
      vielen Dank für deine Anmerkung! Ich habe im Text nochmal einen Link zu einem anderen Blog-Beitrag von uns ergänzt: https://www.clickstorm.de/blog/icons-gesucht-font-awesome/
      Dort haben wir das Einbinden der Fontello-Schriftart schonmal thematisiert.

  • 18/05/2018

    Kommentar von Christoph

    Sehr cooles Tutorial, Danke Christoph! Auch die kleinen IE Hacks haben mir viel Zeit gespart 🙂

  • 09/07/2018

    Kommentar von Oliver

    QUOTE: Da wir für den übergeordneten Wrapper bereits eine Breite vergeben haben …

    Haben wir? Wo denn?

    • 10/07/2018

      Kommentar von Christoph

      Hallo Oliver,
      danke für den Hinweis. Ich hatte zwar die Wrapper-Breite im Text ganz oben angesprochen, aber kein entsprechendes CSS-Schnipsel eingefügt. Das habe ich mal ergänzt.

  • 19/07/2018

    Kommentar von Marvin

    Selbst wenn ichs 1:1 abkopiere gehts nicht was mach ich da bitte falsch? ._.

    • 30/07/2018

      Kommentar von Marc

      Hallo Marvin, was genau funktioniert denn nicht?

  • 20/07/2018

    Kommentar von Jürgen

    Hey ich hab bei Fontello gesehen das die eine Kopierrechtslizenz haben aber ich möchte es verwenden um damit Geld zu verdienen. Kann ich das machen oder was wäre meine alternative?

    • 30/07/2018

      Kommentar von Marc

      Hallo Jürgen, meines Wissens nach kann Fontello auch für kommerzielle Zwecke eingesetzt werden. Die aktuelle Lizenz findest du hier https://github.com/fontello/fontello/wiki/What-about-license%3F. Viele Grüße, Marc

  • 28/08/2018

    Kommentar von Klaus

    Ein exzellenter Artikel:

    Kleiner Hinweis: das separate transparaente PNG kann man auch durch ein eingebettetes transparents GIF ersetzen:

    background: url(„data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==“) repeat;

    Klappt natürlich nicht mit IE7 und älter.

  • 19/09/2018

    Kommentar von Peter Pan

    Für mich als Anfänger war alles bis ‚Der Pfeil‘ verständlich. Bei fontello.com habe ich den nötigen Pfeil gefunden und die Datei heruntergeladen (fontello-118bb044.zip).
    Welche der vielen CSS Dateien soll in meine CSS Datei verlinkt werden? Die anderen Dateien font & config.json igonieren?
    „Icons gesucht font awesome“ Artikel habe ich auch gelesen.

    Die Datei font-awesome.min.css ist bei mir nicht vorhanden.
    fotawesome.css fontawesome-code.css und andere schon.

    Wäre schön wenn es genauer beschrieben wäre, die Profis könnten den Abschnitt ja überspringen.
    Trotzdem danke.
    PS: Wenn ich mein Text hier reinkopiere, kommt die Meldung ich soll ein Kommentar eingeben.

    • 19/09/2018

      Kommentar von Christoph

      Hallo,

      über Fontello kannst du dir ja dein eigenes Icon-Paket zusammenschnüren. Die config.json ist dann dazu da, dass du später, wenn du weitere Icons benötigst, diese wieder in Fontello importieren und konfigurieren kannst – deshalb am besten behalten. Außerdem brauchst du noch den Ordner „font“ und alle enthaltenen Font-Schriftarten. Diese werden wiederum in der fontello.css (so heißt sie zumindest bei mir) per @font-face geladen, d.h. diese Datei bräuchtest du noch für die grundlegenden Icon-Styles. Ggfs. musst du auch noch die Pfade zu deinem Font-Ordner anpassen.

      Wenn du neue Icons hinzufügst, reicht es dann, die Icons aus der *-codes.css in deine eigene CSS-Datei zu übernehmen. Falls du den IE7 noch mit unterstützen musst, dann noch die *-ie7.css per Browserweiche einbinden.

      Grüße und vielen Dank für das Feedback!

  • 30/10/2018

    Kommentar von Olivia

    Danke für diesen Beitrag! Das war absolut das einzige was ich nützliches im Netz gefunden habe. Zudem ist es alles noch absolut verständlich erklärt. Dankeschön!

  • 22/11/2018

    Kommentar von Georg

    Hallo, vielen Dank für den Artikel hat mir sehr geholfen. Das einzige was ich nicht geschafft habe ist den Pfeil an die richtige Position zu bekommen. Es wird immer die Größe des Fenster für die absolute Position genommen, nicht die vom div…

    • 23/11/2018

      Kommentar von Christoph

      Hallo Georg,

      vielen Dank für deine Anmerkung. Damit der Pfeil im ::before-Element absolut positioniert werden kann, muss das übergeordnete Element, also in dem Fall das „div“ mit der Klasse „select-wrapper“ relativ positioniert werden. Das hatte ich zwar im Text erwähnt, allerdings nicht im Quellcode aktualisiert – daher sicher die Verwirrung.

  • 08/04/2019

    Kommentar von Sandy

    Ich habe mir das mal alles durchgelesen, alles schön und gut, aber warum gibt es dann keine Zusammenfassung per HTML+CSS, glaube das würde hier viele Fragen überflüssig machen

    Das mit dem Pfeil verstehe ich echt nicht, musst das style im select oder in der Option?

    • 03/05/2019

      Kommentar von Christoph

      Hallo Sandy,

      entschuldige die späte Antwort.

      Meiner Erfahrung nach ist es so, dass grundsätzlich mehr Wissen hängenbleibt, wenn man ein Tutorial Schritt für Schritt durcharbeitet. Daher hatte ich bisher auf eine Zusammenfassung verzichtet. Ich habe dir aber zum Abgleich mal ein Snippet unter „Quellen“ verlinkt.

      Der Pfeil hängt an dem div-Wrapper, den wir um das select herum gelegt hatten. Pseudoelemente wie :before und :after funktionieren an einem select gewöhnlichen nicht.

      Viele Grüße
      Christoph

  • 14/11/2019

    Kommentar von Susana Pinho

    Hi, sorry, ich hab nur ein riesen Problem mit der zeilen abstand in den dropdown selbst, also zwischen die tags. Kein margin / padding / line-height nichts funktioniert?

    • 22/11/2019

      Kommentar von Christoph

      Hallo Susana,

      meinst du das Styling der option-Tags? Dafür ist das Tutorial leider nicht ausgelegt, da hier die native Darstellung behalten werden soll.

      Wenn du die komplette Darstellung des Dropdowns verändern möchtest, benötigst du JavaScript. In Verbindung mit jQuery kannst du dir z.B. mal https://select2.org/ oder https://github.com/patrickkunka/easydropdown anschauen.

  • 02/04/2020

    Kommentar von Isa

    Ein wirklich super verständliches Tutorial, danke dafür!

  • 02/07/2020

    Kommentar von Guido Jansen

    Man kann den Zusatzabstand im Firefox kompensieren, wenn man die firefox-eigene CSS-Regel `-moz-padding-start` auf einen Wert 3 Pixel weniger als den Wert für `padding-left` setzt. Also zum Beispiel

    select {
    padding-left: 10px;
    -moz-padding-start: calc(10px – 3px);
    }

    • 02/07/2020

      Kommentar von Christoph

      Stimmt. Danke! So ist es dann eine wirklich einheitliche Darstellung in den Browsern.

  • 24/07/2020

    Kommentar von top

    Schöne Erklärung. Danke schon mal dafür.

    Was den „Haken“ betrifft würde ich den einfach auch nur mit CSS erstellen (ohne einen extra Font einzubinden). Ist ja schließlich nur ein Haken.

    Etwa so:
    .select-wrapper::before {
    pointer-events: none;
    position: absolute;
    right: 15px;
    top: 10px;
    content: “ „;
    transform: rotate(45deg);
    border-right: solid 3px #fff;
    border-bottom: solid 3px #fff;
    width: 12px;
    height: 12px;
    box-sizing: border-box;
    }

    • 24/07/2020

      Kommentar von Christoph

      Das geht natürlich auch, danke! Viele Wege führen nach Rom. 😉

      Da wir Font Awesome ohnehin bei den allermeisten Projekten mit nutzen, bietet sich für uns die Integration der Standard-Icons über Fontello aus diesem Grund schon an.

  • 27/03/2022

    Kommentar von Jan

    Vielen Dank für diese Tutorial, das mir sehr geholfen hat. Allerdings stelle ich fest, dass die modifizierten Selects sich in Javascript nicht mehr mit „document.f.name.disable = true;“ deaktivieren lassen. Hast Du dafür vielleicht auch eine Lösung? Vielen Dank!

    • 04/04/2022

      Kommentar von Christoph

      Hallo Jan,
      ich bin mir nicht ganz sicher, was du meinst. Im Tutorial geht es ausschließlich um Anpassungen per CSS, dadurch sollte das DOM per JavaScript weiterhin genauso angesteuert werden können. Ob dein Funktionsaufruf geklappt hat, kannst du prüfen, indem du schaust, ob das Select im gerenderten HTML das ‚disabled‘-Attribut hat. Ansonsten ggfs. nochmal die Syntax checken: https://www.w3schools.com/jsref/prop_select_disabled.asp

      Es kann sein, dass die Darstellung / Usability dann noch nicht den Anforderungen entspricht (z.B. Änderung des Mauszeigers on hover). Dann könntest du im CSS das disabled-Attribut ansteuern, also z.B. über „select[disabled]“, wobei dein Selector vermutlich eher eine ID sein wird.

      VG Christoph

  • 19/09/2022

    Kommentar von Adi Fuhrer

    super, die Doku zum select hat mir sehr geholfen.

Kommentar hinzufügen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert