CSS-Filter – mehr Effekte fürs Web – CSS3 Adventskalender Tag 19

Nachdem CSS 2.1 uns Ende der 90er einigermaßen solide Werkzeuge zum Layouten von Seiten ohne Tabellen an die Hand gegeben hat, ging es bei CSS3 zunächst viel darum, uns mit mehr dekorativen Gestaltungsmöglichkeiten auszustatten. Heute haben wir endlich einbettbare Schriftarten, runde Ecken, Farbverläufe, semitransparente Elemente und Farbwerte, Box- und Textschatten usw. Soweit, so gut.

Der Blick in Richtung Photoshop und dessen Featureset offenbart jedoch immer noch Lücken. In Photoshop haben wir zum Beispiel die Möglichkeit, Bereiche zu entsättigen oder zu schärfen und weichzuzeichnen. Wofür könnten wir diese Effekte brauchen? Nun, ein Entsättigen oder ein Weichzeichnen bestimmter Areale einer Seite hilft dem Benutzer, sich auf unangetastete Bereicher besser zu fokussieren.

Ein unscharf maskieren, was ein unglücklicher Name für eigentlich eine Nachschärfungsmethode ist, könnte man im Browser kleinskalierte, und damit einhergehend detailarm gewordene Bilder wieder knackiger machen.

Schön wäre, wenn wir diese Effekte genauso auftragen könnten, wie wir mit opacity ganze Areale transparenter machen.

Für einen Entsättigungseffekt müssten wir stattdessen aufwändig per JavaScript durch die Farbwerte aller betroffenen Elemente zirkeln, und diese durch ihre entfärbte Pendants ersetzen. Leider scheitert dieser Ansatz spätestens in dem Moment, wo wir auf usergeneriertes Bild- oder Videomaterial treffen. Hier könnten wir zu HTML5 Canvas wechseln, das es uns erlaubt, jeden Pixelwert einzeln zu manipulieren. Dabei helfen uns zwar bestimmte Canvas-Effektbibliotheken wie CamanJS oder Hoverizr, aber die Umsetzung bleibt anstrengend.

Einen Unschärfeeffekt können wir bislang ebenfalls nur tricksen, indem wir Texte mit einem text-shadow gleicher Farbe versehen und bei einfarbigen Boxen einen box-shadow zum Einsatz bringen. Wieder müssten wir für Bilder oder Videos auf Canvas ausweichen.

Einen ziemlich brutalen Ansatz fährt das Framework blurry.js, das nämlich weichzuzeichnende Bereiche inklusive Text via Cufón nach Canvas überführt und sie dort im Ganzen weichzeichnet.

Unscharf Maskieren, also nachschärfen, können wir hingegen gar nicht mit CSS umsetzen. Hier würde der Weg einzig und allein über Canvas führen.

Filter über SVG

SVG kennt eine riesige Palette an Filtern, so etwa Überblenden, Farbüberlagerungen, Helligkeits- und Kontrastanpassungen, Beleuchtung und Reliefeffekte, gausssche und bewegte Unschärfe, Wolken und Rauschen, et cetera pépé.

Wir haben mit SVG einerseits die Möglichkeit, anstatt unseren Texte und Bilder in HTML einzubetten, diese in ein SVG zu packen, innerhalb dessen wir dann Filter auftragen können. Es dürfte Markup-technisch jedoch ungewohntes Terrain sein, Texte mit folgender Syntax einbauen zu müssen:

<text id="header" font-family="Arial" font-weight="900" font-size="40" x="20" y="55%">SVG Example</text>

Cooler ist daher das ForeignObject/xlink in SVG, das es uns erlaubt, normale HTML-Abschnitte in das SVG einzusetzen, die dann via Filter umgestaltet werden können. Damit lässt sich eine komplette HTML-Seite ins SVG einbetten und von A-Z umfärben oder ein nur einzelnes eingebettetes Bitmap-Bild weichzeichnen. Der Grad der Unterstüzung ist schon recht weit gediehen, fehlt nur noch der IE, der mit Version 10 endlich nachzieht.

Firefox geht seit Version 3.5 noch einen Schritt weiter und ermöglicht es, in HTML SVG-Filter anzuwenden, die in einer externen SVG-Datei definiert sind. Zum Beispiel könnten wir in einer SVG-Datei einen feGaussianBlur-Filter mit einem Weichzeichnungsradius von 2 Pixeln definieren, dem wir die id gaussian_blur verpassen:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="710" height="476" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <filter id="gaussian_blur">
      <feGaussianBlur in="SourceGraphic" stdDeviation="2" />
    </filter>
  </defs>
</svg>

Den Filter mit dieser id referenzieren wir dann aus unserem normalen Stylesheet heraus:

img {
  filter: url(blur.svg#gaussian_blur);
}

Eine Live-Demo findet sich hier. Leider beschränkt sich dieses praktische Verfahren auf besagten Firefox.

Allerdings: Der IE kennt ja auch Filter, die allesamt von der Windows-Grafikbibliothek DirectX abgeleitet sind. Darunter befinden sich die altbekannten Alpha- oder Gradient-Filter, mit denen wir uns in alten IEs CSS3-Features herbeitricksen. Es befinden sich aber auch ein paar darunter, mit denen sich die am häufigsten benötigten Effekte realisieren lassen:

/* Um 2 Pixel weichzeichnen */
filter: progid:DXImageTransform.Microsoft.Blur(pixelradius=2);
/* 13 Pixel Bewegungsunschärfe in Richtung 310° */
filter: progid:DXImageTransform.Microsoft.MotionBlur(strength=13, direction=310);
/* In Graustufen umwandeln */
filter: gray;
/* Röntgen-Effekt (also Graustufen invertiert) */
filter: xray;
/* Lichtkegel setzen */
filter: light();
/* Emboss */
filter: progid:DXImageTransform.Microsoft.emboss();

Eine komplette Liste gibt es hier.

Mit Hilfe von Conditional Comments können wir damit schon zwei Browserfamilien bedienen, die zusammen immerhin 77% des deutschen Browsermarkts ausmachen:

<!DOCTYPE HTML>
<!--[if lte IE 9]> <html class="ie" lang="de"> <![endif]-->
<!--[if gt IE 9]><!--> <html lang="de"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Unschärfe via CSS-Filter SVG</title>
<style>
img {
  filter: url(blur.svg#gaussian_blur);
}
.ie img {
  margin: -2px;
  filter: progid:DXImageTransform.Microsoft.blur(pixelradius=2);
  zoom: 1;
}
</style>
</head>
<body>
  <img src="stadt.jpg"
  alt="Some rights reserved by zigazou76"
  width="500" height="333">
</body>
</html>

margin: -2px gleicht den erhöhten Platzverbrauch aus. zoom: 1 sind bei Filtern für die IE6/7 immer notwendig. Wichtig zu wissen ist, dass der IE 10 keine Filter mehr unterstützen wird :(

Hier das erweiterte Beispiel

Weil man nun aber erkannt hat, wie unglaublich praktisch die SVG-Filter von Firefox sind, hat sich das W3C gedacht, man müsste diesen Ansatz doch mal standardisieren, und so wurde die W3C FX Task Force gegründet, welche nun die ersten Drafts für offizielle W3C Filter Effekte vorgelegt hat.
Diese Filter funktionieren im Prinzip genau so, wie sie der Firefox vorexzerziert, also mit Verweis auf eine externe URL, die den Filter unter einer id bereithält. Darüberhinaus definiert man aber auch ein paar Filter-Shortcuts für die prominentesten Filter, die dann keine externe Datei benötigen. Diese Shortcut-Filter wären:

  • grayscale
  • sepia
  • saturate
  • hue-rotate
  • invert
  • opacity
  • brightness
  • contrast
  • blur
  • drop-shadow

Das Gute an den Filter-Shortcuts ist zudem, dass man per Shortcut angewendete Filter in CSS animieren kann, z.B. so:

.foo {
  filter: blur(2px);
  transition: filter 1s ease-in-out;
}

.foo:hover {
  filter: blur(0);
}

Zu guter letzt soll auch noch eine Möglichkeit bereitgestellt werden, OpenGL/WebGL-Verformungs- und Shaderfilter zu definieren, die das entsprechende Element z.B. dreidimensional verformen:

Praktischerweise sind vergangene Woche endlich erste Umsetzungen dieser Filter in der WebKit-Engine gelandet und nehmen nun den Weg über die WebKit-Nightlies (im OSX-Nightly läuft es schon) über Chrome Canary, dann über die Chrome Beta, um schließlich in 3 Monaten im stabilen Allerwelts-Chrome zu landen. Und irgendwann sicherlich auch im Safari. Und damit wären die wichtigsten Filter in 90% – 95% aller Browserversionen am Markt verfügbar.

Für WebKit fügen wir für unser Beispiel also einfach ein -webkit-filter: blur(2px); zusätzlich ein, und machen es in dem Zug noch ein wenig interaktiv und zumindest im WebKit animiert:

<!DOCTYPE HTML>
<!--[if lte IE 9]> <html class="ie" lang="de"> <![endif]-->
<!--[if gt IE 9]><!--> <html lang="de"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Unschärfe via CSS-Filter SVG</title>
<style>
img {
  filter: url(blur.svg#gaussian_blur);
  -webkit-filter: blur(2px);
  -webkit-transition: -webkit-filter 1s ease-in-out;
}
img:hover {
  filter: none;
  -webkit-filter: blur(0);
}
.ie img {
  margin: -2px;
  filter: progid:DXImageTransform.Microsoft.blur(pixelradius=2);
  zoom: 1;
}
.ie img:hover {
  margin: 0;
  filter: none;
}
</style>
</head>
<body>
  <img src="stadt.jpg"
  alt="Some rights reserved by zigazou76"
  width="500" height="333">
</body>
</html>

Das finale Beispiel gibt es hier online zu sehen. give me money

Eine erste Demo-Spielerei, die nicht nur CSS Filter verwendet, sondern auch CSS 3D Tranforms gibt es übrigens ganz frisch bei Simurai zu bewundern. Viel Spaß mit den CSS Filtern!

Update: Im aktuellen Chrome Canary sind die CSS Filter nun auch angelandet, sowohl unter Mac, als auch unter Windows.


Christian ”Schepp” Schaefer ist freiberuflicher Webentwickler aus Düsseldorf. Er ist Autor der Ladezeitenbeschleuniger-Bibliothek CSS-JS-Booster sowie Moderator des wöchentlich erscheinenden Working Draft Podcasts and er verfolgt Eure Tweets mit seinem Account derSchepp.


4 thoughts on “CSS-Filter – mehr Effekte fürs Web – CSS3 Adventskalender Tag 19”

Kommentare sind geschlossen.