04. September 2009
Transparenz-Effekte können – wenn man sie gezielt einsetzt – ein äußerst attraktives Stilmittel innerhalb des Layouts sein. Die Eigenschaft opacity beschreibt die Deckkraft eines Elementes und ist deshalb neben alphatransparenten PNGs oder den alphatransparenten RGBa-Farben von CSS3 eine der drei möglichen Grundtechniken, um Transparenz-Effekte zu erzeugen. Also, was soll man nun nehmen?
Alphatransparente PNG Grafiken sind der wohl einfachste Weg, denn es muss lediglich eine entsprechende Grafik erstellen und einbinden. Der grafische Ansatz hat den Vorteil, dass sich jeder erdenkliche Transparenzverlauf erstellen lässt. Nachteilig ist jedoch: dem Internet Explorer muss der fehlerfreie Umgang mit transparenten PNGs erst durch performanceraubende Hacks (PNG Fix) beigebracht werden. Zudem ist hier immer eine Grafik im Spiel, was schnelle Änderungen unnötig verkompliziert.

Geht es lediglich um einfarbige transparente Flächen oder Hintergründe, so stehen RGBa-Farben und die opacity-Eigenschaft als reine CSS-Alternativen zur Verfügung. Doch auch hier geht es nicht ohne Stolpersteine weiter. RGBa ist Bestandteil von CSS3 und wird momentan nur von den aktuellen Versionen des Firefox sowie den Webkit-Browsern Safari und Chrome unterstützt. Weder Opera, noch der Internet Explorer spielen mit. Für den Internet Explorer gibt es - einmal mehr - einen proprietären Kniff, womit wir der Lösung schonmal einen großen Schritt näher währen. Allerdings gibt es für Opera keine Lösung, es an dieser Stelle mit RGBa momentan noch nicht weiter geht.
Verbleibt also nur noch die CSS-Eigenschaft opacity. Opera unterstützt diese Eigenschaft und beim Internet Explorer sind wir mit dem eben bereits erwähnten Filter-Tricks dabei. Als Ausgangsbasis haben wir somit erst einmal alle Browser mit an Bord. Dummerweise wirkt opacity jedoch nicht nur auf den Hintergrund eines Elementes, sondern Vordergrund UND Hintergrund, einschließlich der eingeschlossenen Child-Elemente sind von den gewählten Transparenz-Einstellungen betroffen. Um einen transparenten Hintergrund zu erzeugen, vor dem dennoch nicht-transparente - und damit gut lesbare - Inhalte platziert werden können, muss daher noch eine kleine CSS-Krücke bemüht werden - ein absolut positioniertes Hilfselement.
<div class="parent colorA"> <p>Container A hat einen einfarbigen Hintergrund.</p> </div> <div class="parent opacity-wrapper" style="top: -130px; left: 150px;"> <div class="colorB opacity"></div> <p>Container B hat einen alphatransparenten Hintergrund.</p> <div class="child">Child-Container ohne Transparenz</div> </div>
Der Container .parent erhält die gewünschte Geometrie, jedoch keinen, bzw. einen volltransparenten Hintergrund ( background: transparent; ). Die eigentliche Hintergrundfarbe oder -grafik wird an den Childcontainer mit der Klasse .opacity vergeben. Dieser wird innerhalb von .parent absolut positioniert und erhält sinnvollerweise relative Dimensionen (width: 100% und height: 100%), damit das Spielchen unabhängig von der Größe des Elternelementes immer funktioniert. Damit die absolute Positionierung auch greift, muss das Elternelement (.parent) ebenfalls positioniert sein. Über die Klasse .opacity-wrapper wird dem Elternelement daher die Eigenschaft position:relative zugewiesen.
Damit das Hilfselement auch wirklich hinter den eigentlichen Inhalten gerendert wird, muss es VOR den Inhaltselementen im HTML Code erscheinen, demzufolge steht es an erster Stelle. Alternativ könnte man es per z-index in den Hintergrund rücken. Gäbe es den Internet Explorer 6 nicht, wären wir fertig. Dummerweise hat dieser Browser gerade bei positionierten Elementen ein Problem mit der korrekten Berechnung der Elementbreite des .opacity Elements. - die prozentualen Angaben für width und height werden falsch berechnet, sobald Randabstände oder definierte Höhen im Spiel sind. Hier hilft leider wirklich nur die Brechstange, deshalb weise dem Container eine fiktive Dimension von 2000px in Höhe und Breite zu, was eigentlich auch in jedem Fall groß genug sein dürfte. Damit die so provozierte Übergröße am Bildschirm nicht zum Problem wird, wird die Klasse .opacity-wrapper durch die Eigenschaft overflow:hidden erweitert. Damit sind wir fertig, hier das vollständige CSS:
.parent {
color: #fff;
height: 200px;
width: 50%;
padding: 20px;
margin-right: 10px;
}
.child {
background: #ff0;
color: #000;
height: 50px;
padding: 10px;
}
.colorA { background: #88a; }
.colorB { background: #668; }
/* partial opacity hack: configuration */
.opacity {
opacity: 0.5; /* modern browser */
-moz-opacity: 0.5; /* older Mozilla browser */
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; /* IE8 in Standard Compliant Mode */
filter:alpha(opacity=50); /* IE5.x -7.0 */
}
/* partial opacity hack, part I: Don't change the following properties! */
.opacity-wrapper,
.opacity-wrapper * {
position:relative;
}
.opacity {
/* partial opacity hack, part II: Don't change the following properties! */
width: 100%;
height: 100%;
position:absolute;
top:0;
left:0;
}
/* partial opacity hack, part III: IE6 support */
* html .opacity-wrapper {
overflow:hidden;
}
* html .opacity {
width: 2000px;
height: 2000px;
}
Ich habe im CSS die Farbklassen (.colorA, .colorB) und den technischen Teil (.opacity, .opacity_wrapper) bewusst als unabhängige CSS-Klassen formuliert, denn so lässt sich diese Technik ohne Änderungen auf jede beliebige Geometrie und mit jeder Hintergrundfarbe oder -bild ohne Änderungen wiederverwenden.
Das vollständige Beispiel mit flexibler Containerbreite kann man sich dieser Demoseite ansehen.
Update: Drüben Yatil.de stellt Eric Eggert eine deutlich schlankere Alternative vor, die auf RGBa basiert und mit mit dem soeben erschienenen Opera 10 nun auch endlich auch im letzten wichtigen Browser funktioniert. Wer keine älteren Browserversionen unterstützen muss (Opera 9 oder Firefox 1.x) kann bedenkenlos zugreifen. Ich verwende diese Technik ebenfalls bereits einige Zeit in YAML-Debug und kann sie daher guten Herzens empfehlen.
Die hier vorgestellte opacity-Lösung bietet sich demzufolge für ältere Browser an oder wenn man anstatt einer Hintergrundfarbe ein teiltransparentes grafisches Muster hinterlegen will, ohne auf PNG’s und die dafür notwendigen JS-Fixes zurückgreifen zu müssen.
Freitag, 04.09.09 (14:58 Uhr)
Ein toller Bericht, vor allem weil ich gerade selber daran arbeite. Mal sehen ob ich so hin bekomme. Dankeschön ;-)
Freitag, 04.09.09 (22:48 Uhr)
Der gerade neu erschienene Opera 10 unterstützt RGBa und auch HSLa.
Samstag, 05.09.09 (23:48 Uhr)
Wirklich ein sehr guter Artikel. Hab die Methode gleich angewendet bin jedoch beim IE6 auf ein Problem gestoßen. Dieser Browser interpretiert das ganz nur ein mal. Wenn ich also nach dem letzten </div> den Code wiederhole:
<div class=“codeblock”>
<div class="parent colorA"></div><p>Container A hat einen einfarbigen Hintergrund.</p>
</div>
<div class="parent opacity-wrapper" style="top: -140px; left: 150px;">
<div class="colorB opacity"></div>
<p>Container B hat einen alphatransparenten Hintergrund.</p>
<div class="child">Child-Container ohne Transparenz</div>
</div>
<div class="parent colorA">
<p>Container A hat einen einfarbigen Hintergrund.</p>
</div>
<div class="parent opacity-wrapper" style="top: -140px; left: 150px;">
<div class="colorB opacity"></div>
<p>Container B hat einen alphatransparenten Hintergrund.</p>
<div class="child">Child-Container ohne Transparenz</div>
Dann rendert der IE6 leider nur die erste Transparenz. Wie kann man so ein Problem umgehen wenn man in mehreren Containern Transparenz einsetzen möchte?
Sonntag, 06.09.09 (10:11 Uhr)
Bei älteren Opera kann man immer noch ein transparentes SVG verwenden, dass über CSS und background eingebunden wird. Das Bild kann dann auch zusätzlich runde Ecken enthalten.
Opera 9.3 hatte bei mir unter Linux Bilder immer mit 100% Deckung angezeigt auch wenn auf den umgebenden Container opacity angewendet wurde.
Sonntag, 06.09.09 (10:25 Uhr)
Sieht ziemlich tricky und umfangreich aus.
Wenn es irgendwie geht, setze ich lieber auf PNG-Grafiken oder CSS3.
Ist für mich mit dem geringsten Aufwand verbunden und im Bedarfsfalle ist bzw. wird der IE im Sinne einer stufenweise Verbesserung (Progressive Enhancement) einfach davon ausgeschlossen.
Für mein PNG-Logo mit Transparenz verwende ich für den IE6 übrigens das JavaScript Unit PNG Fix. Gibt es da gegenüber dem im Artikel erwähnten IE PNG Fix v1.0 / 2.0 Alpha 3 Vor- bzw. Nachteile?
Ich hatte noch zwei andere JavaScripte getestet (siehe hierzu meinen Blogbeitrag “PNG-Logo auch für den IE 6”), aber die bereiteten Layout-Probleme.
Montag, 07.09.09 (09:57 Uhr)
@Guido
Ich konnte keine Probleme feststellen, Mehrfachverwendung war im Test kein Problem.
@Andreas
Mit einem zusätzlichen transparenten SVGs können noch viel weniger Browser etwas anfangen, die Lösung soll ja auch halbwegs pflegeleicht bleiben. Was Opera 9.3 unter Linux angeht, dazu kann ich nichts sagen. Melde es bei Opera als Bug.
@Dieter
Klar, die aktuelle Beta des Alpha-PNG Fixes kann deutlich mehr, beispielsweise relativ fehlerfrei mit PNG-Hintergrundgrafiken umgehen.
Dienstag, 08.09.09 (08:42 Uhr)
Danke für die „Anleitung“, wird bei mir sicherlich nochmal Verwendung finden :)
Mittwoch, 23.09.09 (18:30 Uhr)
Hmmm, gute Browser unterstützen doch auch svg. Geht das eigentlich auch, dass man svg-“Bilder” im css als Hintergrund einrichtet?
Ging mir grade so durch den Kopf.
Montag, 02.11.09 (19:39 Uhr)
Leider ist auch diese Lösung nicht CSS 2.1 valide.
Montag, 02.11.09 (19:59 Uhr)
@Alex,
Die Validität ist hierbei doch völlig unerheblich. Die Fehlermeldungen rühren nicht von Syntax-Fehlern her, sondern von der bewussten (und dokumentierten) Verwendung proprietärer Eigenschaften, um den Internet Explorer zu unterstützen. Wenn diese Anpassungen Dich stören, kannst Du sie gern per Conditional Comment auslagern. Das ändert an der technischen Lösung nichts.
Montag, 02.11.09 (20:11 Uhr)
Stimmt an die Conditional Comments hab ich nicht gedacht. Vielen Dank!
PS: Schöner Blog