Tag Archives: CSS

Custom styling für die Select-Box (auch im IE)

Custom Select-Box

Custom Select-Box

Ab und an kommen Designer auf die Idee, den Style der Select-Box so stark anzupassen, dass ein setzen des Backgrounds und vielleicht noch die Anpassung der Schriftart nicht reicht. Mit CSS3 ist jetzt auch sehr leicht viel mehr möglich. Wer aber noch den IE8 oder IE9 unterstützen muss, guckt in die Röhre. Ich weiß gar nicht, ob der IE10 dieses Feature schon unterstützt…?

Für die im folgenden beschriebene Möglichkeit ist JavaScript von nöten. Über die SelectBox für ein Span gelegt, welches das entsprechende Styling durch Background-Images oder sonstige CSS-Angaben bekommt. Die Ursprüngliche Select-Box liegt dank “z-index” aber über dem Span und wird per “opacity” durchsichtig gemacht. Der Inhalt des Spans wird per JavaScript immer auf die aktuelle Auswahl der Select-Box gesetzt.

Im Sinne von Progressive Enhancement, also der schrittweisen Anreicherung / Verbesserung, je nach Möglichkeiten, wird im Markup (HTML) zunächst nur eine normale Select-Box angegeben.

<select name="topics-select" id="topics-select" class="bb-styled">
<option selected>Themen</option>
<option>Thema 1</option>
<option>Thema 2</option>
</select>
view raw selectbox-style.html hosted with ❤ by GitHub

Das nötige Span-Element und der DIV-Container (Wrapper) wird, sofern JavaScript aktiviert ist, später hinzugefügt. Würden wir den Span und DIV-Container, inklusive Stylesheet-Angaben, direkt im Markup haben, könnte die Select-Box von einem User ohne JavaScript nicht mehr benutzt werden.

$('select.bb-styled').each(function(){
var title = $(this).attr('title');
if( $('option:selected', this).val() != '' ) title = $('option:selected',this).text();
var idName = $(this).attr('id') + '_container';
$(this).before('<div class="bb-styled-container" id="' + idName + '"></div>')
$('#' + idName).append(this);
$(this)
.css({'opacity':0})
.after('<span class="bb-styled">' + title + '</span>')
.change(function(){
val = $('option:selected',this).text();
$(this).parent().find('span').text(val);
})
});
view raw selectbox-style.js hosted with ❤ by GitHub

Hier noch das benötigte Stylesheet:

div.bb-styled-container { position:relative; margin: 50px; }
select.bb-styled {
position: relative;
z-index:10;
display: block;
-webkit-appearance:none;
-moz-appearance:none;
appearance:none;
cursor:pointer;
}
span.bb-styled {
position: absolute;
bottom: 0;
left: 0;
cursor: default;
z-index: 1;
}
span.bb-styled:after {
content: '<>';
display: inline-block;
transform: rotate(90deg);
-ms-transform: rotate(90deg);
-webkit-transform:rotate(90deg);
-ms-transform:rotate(90deg);
font-size: 10px;
height: 10px;
width: 10px;
float: right;
margin-top: -7px;
}
.bb-styled {
background-color: #ccc;
color: #000;
text-indent: 10px;
width: 200px;
border: 1px solid white;
border-radius: 4px;
font-size: 13px;
font-weight: normal;
font-family: Arial;
line-height: 18px;
}
view raw selectbox-style.css hosted with ❤ by GitHub

Demo-Code

Zum Abschluss das ganze noch in einem jsFiddle: http://jsfiddle.net/2zr78/2/

Bitte gerne Verbesserungsvorschläge in die Kommentare posten. Ich sehe es derzeit als ersten Entwurf. Vor allem mit der Struktur des CSS bin ich noch nicht richtig zufrieden, das Outcome (grauer Kasten ohne alles) ist hier nur zu Demozwecken, bei Zeiten lass ich mir aber mal etwas hübscheres einfallen. ;-p Der Code kann definitiv noch optimiert werden, zum Beispiel kann das JavaScript getrickse für die neusten WebKit-Versionen unterlassen werden.

Quik-Hints

Ein paar kurze Anmerkungen und Hinweise, die nicht für einen ganzen Beitrag reichen, aber trotzdem erwähnenswert sind.

  • display: inline-block & E.offsetWidth buggy im IE8 -> Abhilfe display: block + float.
  • Chromebook Pixel für Webworker
  • “display: table-cell” für “vertical-align: middle”
  • <div> Container um ein <img> hat 4px Höhe zuviel? -> img { vertical-align:bottom; } oder img { display: block; } weil User-Agents bei Inline-Elementen Platz für mögliche Descenders schaffen.
  • spezielle Font für Wireframes und Co. anstelle Lorem Ipsum
  • (new Function(strCode))(); ist bis zu 5400% performanter als eval(strCode);
  • Bilder malen mit purem CSS (box-shadow)

Mehrere / mehrfarbige “border” (Rahmen) mit CSS

Embossed HTML Element aus Twitters Bootstrap mit Border und inset Shadow

Es kann öfters einmal nützlich sein, einem HTML-Element mehr als nur einen Rahmen zu geben, respektive dem Element einen mehrfarbigen Rahmen zuzuweisen. Als Beispiel: Man möchte, dass das Element so wirkt, als sei es in die Seite “eingedrückt” (embossed). Ich hatte mir vor ein paar Tagen Gedanken dazu gemacht, weil ich einen Rahmen nur im oberen Teil des Elements brauchte, der eigentlich durchgängig grau ist und 5px dick. Eigentlich… Ganz Links, fast schon unauffällig, sollten die ersten 5px der Linie gelb sein.CSS Border mit zwei Farben So gesehen also einen zweifarbigen Border. Lösbar wäre es über die neue “border-image” Definition gewesen, würde aber bedeuten, man müsste wieder ein Bildchen mehr übertragen. Man hätte auch einen “Fake-Border” mit zwei Divs (weiter unten beschrieben) erstellen können, das wollte ich aber vermeiden. Man sollte immer versuchen, das Font-End als Schichtenmodell zu behandeln. Neben “Unobtrusive JavaScript” also auch immer “Unobtrusive CSS” verwenden, somit sind Präsentationsänderungen unabhängig von der Struktur. Ein Artikel bleib ein Artikel. Die Lösung sollte ab IE8 lauffähig sein. Hier nun drei gute Lösungen für doppelte oder mehrfarbige Rahmen mit CSS(3):

Pseudo-Element

Mein Liebling. Mit dem Pseudo-Element “:before” ist es möglich, einen zwei- oder mehrfarbigen Rahmen anzulegen. Im Beispiel (http://jsfiddle.net/672LA/) habe ich das Umgesetzt, was ich oben als Eingangsproblem beschrieben habe; grauer, 5px dicker Rahmen, die ersten 5px der in der Länge gelb. So haben wir also einen zweifarbigen Border mit reinen CSS Mitteln.

#myDualColorBorder {
border-top: 5px solid #eaeaea;
position: relative;
}
#myDualColorBorder:before {
position: absolute;
top: -5px;
display: block;
content: '';
border-top: 5px solid #ffd300;
width: 5px;
}
view raw dualcolor_border.css hosted with ❤ by GitHub

Es ist aber auch einfach möglich, einen doppelten Rahmen anzulegen, zum Beispiel für den Anfangs erwähnten embossed Effekt. Dann einfach nur das Verschieben durch “top: -5px;” entfernen und die width auf 100% setzen. Soll der Rahmen an allen Seiten sein, wird noch ein “height: 100%;” benötigt. Hier ein Beispiel: http://jsfiddle.net/ftvJN/. Dort ist aber nur ein Rahmen oben, weswegen keine Höhendefinition beim Pseudo-Element zu finden ist.

All these nice things!

Outline

#myDoubleborder {
border: 2px solid green;
outline: 2px solid red;
}
view raw outline_border.css hosted with ❤ by GitHub

Führt zu folgendem Ergebnis: http://jsfiddle.net/qFGeN/1/. Bitte beachten, dass es bei Outline mit äußeren Schatten in CSS zu unerwünschtem Verhalten kommen kann. Die Outline legt sich teilweise um den äußeren Schatten und nicht um das Element.

Box-Shadow

Ein doppelter Rahmen mit der neuen Box-Shadow Angabe sollte der Outline-Variante vorgezogen werden. Es führt zum gleichen Ergebnis (http://jsfiddle.net/hZGa7/3/), die Outline-Angabe wird, wie oben erwähnt, nicht unbedingt von jedem Browser gleich behandelt, bzw. wie gewünscht gerendert.

#myDoubleShadowBorder {
border: 2px solid green;
box-shadow: inset 0px 0px 0px 2px red;
}
view raw shadow_border.css hosted with ❤ by GitHub

Der Box-Shadow eignet sich hervorragend für einen Eindrückeffekt. Früher wurde dieser Effekt häufig durch eine Grafik als background-image erzielt. Durch zwei Rahmen um ein Element, mit geschickter Farbabstufung, wurde dieser Effekt dank Photoshop anstelle reinem CSS erreicht. Meiner Meinung nach kommt der Effekt noch besser, wenn der Schatten nach innen einen leichten Verlauf hat. Das Ergebnis des folgendes Codes könnt ihr hier ansehen: http://jsfiddle.net/aPv9X/

#myEmbossedElement {
background-color: #eee;
border: 2px solid #eee;
border-radius: 5px;
box-shadow: inset 1px 1px 5px 1px #ddd;
}
view raw embossed_border.css hosted with ❤ by GitHub

Es gibt aber noch weitere Möglichkeiten, die ich nur eingeschränkt empfehlen kann. Variante Eins sollte nur bei wirklich grafisch aufwendigen Rahmen benutzt werden und Variante Zwei ist für diejenigen, die immer noch einen völlig veralteten Browser unterstützen (müssen). Variante Drei wird in den wenigsten Fällen von Nutzen sein, sei aber trotzdem erwähnt.

Border-Image

Zur Border-Image Definition kann man in Normans Blog die Grundlagen nachlesen. Das war gleich der erste Eintrag in Google, von daher gehe ich darauf hier nicht weiter ein, sollte reichen… 😉

Div

Diese Variante (http://jsfiddle.net/R5adG/) sollte sogar im IE6 laufen, überprüft habe ich es aber nicht. Ich würde sie nur empfehlen, wenn man keine der oben beschriebenen Möglichkeiten nutzen kann. Es ist immer sinnvoll, das Markup größtmöglich vom Styling zu trennen und unnötige Divs sollte man sowieso vermeiden.

Border-Style

Zum Abschluss sei noch die Variante zu nennen, die im ersten Moment als logisch erscheint. Es ist mit dem “border-style” durchaus auch möglich einen doppelten Rahmen oder einen Embossed-Effekt zu erzielen, aber die Flexibilität hält sich stark in Grenzen.

Zunächst das Beispiel: http://jsfiddle.net/FM3fF/, dann der Code

div {
width: 200px;
height: 100px;
margin: 30px auto;
}
#doubleBorder {
border-style: double;
}
#insetBorder {
border-style: inset;
}

0 ist nicht messbar

Der Wert 0 (Null, Zero) ist nicht messbar und benötigt daher keine Maßeinheit.
In CSS-Styles kommt es häufig vor, dass der Außen- oder Innenabstand (margin/padding) auf 0 gesetzt wird. Hier habe ich ab und an beobachtet, dass 0px, 0em oder ähnliches verwendet wird. Vielleicht steht auch mancher vor der Frage ob margin: 0 oder 0px besser ist. Besser ist falsch, es wird in allen Browsern zum gleichen Ergebnis führen und ist auch gleich performant. Es ist nur eine Frage der Semantik.

/* Don't use... */
body {
margin: 0px;
}
h1 {
padding: 0px;
}
/* ...instead use it without measurement units */
body {
margin: 0;
}
h1 {
padding: 0;
}
view raw 0value.css hosted with ❤ by GitHub