Chez Jérémie

Chez Jérémie, parfois c'est sérieux, parfois non !

Des effets pour le Web

- Web - Lien permanent

Cet article est la traduction d’un article de Christian « Schepp » Schaefer à propos des nouvelles propriétés de filtres CSS3 et montre comment commencer à les utiliser tout en proposant des solution de repli basées sur ce que supportent les navigateurs actuels.

A la fin des années 90, CSS 2.1 nous a fourni un ensemble d’outils de base pour pouvoir enfin se débarrasser des mises en page en tableaux. Maintenant c’est le tour de CSS3 qui nous donne de nouveaux outils plus précis pour gérer les détails de mise en forme : Les fontes embarquées, les coins arrondis, les dégradés, la transparence des éléments et des couleurs, les ombre portées sur le texte et les boites, etc.

Évidement, lorsqu’on compare notre outillage à celui de logiciels comme Photoshop, on se dit qu’on pourrait rêver mieux. Ce genre de logiciel permet, par exemple, de désaturer une image ou bien de la rendre plus nette ou plus floue. Pourquoi aurions-nous besoin de ce genre d’outil pour le Web ? Et bien, désaturer ou flouter une partie de page Web peut être un moyen de guider le regard de vos visiteurs sur des zones choisies. Ça pourrais aussi aider vos visiteurs à concentrer leur attention sur les zones qui n’ont pas été modifiées. Par exemple, on peut utiliser ce genre d’effets pour mettre en scène une galerie d’images :

Mike Matas - One Week In Japan

D’un autre coté, un effet de netteté peut être utile lorsque vous réduisez une image dans le navigateur. Sans lui, vous allez perdre un certain nombre de détails sur cette image.

sharpen.jpg

Voila, ce serait génial si nous pouvions avoir ce genre d’effets à notre disposition, un peu comme la propriété CSS opacity qui nous permet de rendre un élément transparent. Malheureusement, ce n’est pas le cas.

Le status quo actuel

Au lieu de cela, pour simuler un effet de désaturation/niveau de gris nous sommes actuellement obligés de passer en revue « à la main », via Javascript, toutes les propriétés utilisant de la couleur sur un éléments donnée pour leur attribuer la valeur de gris que l’on veut. Dès que l’on doit faire face à des images ou de la vidéo, c’est encore plus compliqué : Dans ce cas-là, nous avons besoin de nous appuyer sur la balise Canvas de HTML5 pour pouvoir changer leur couleur pixel par pixel puis pour remplacer l’élément d’origine. Même si nous nous appuyons sur des bibliothèques tel que CamanJS ou Hoverizr, ça reste quand même un truc assez sale.

Un effet de flou peut également être simulé à l’aide des propriétés text-shadow et box-shadow en leur appliquant la même couleur que le texte ou l’arrière-plan auquel elles se rapportent. Le problème, c’est que cette illusion ne fonctionnera pas avec les boîtes multicolores non plus qu’avec les images ou les vidéos comme précédemment. Une fois de plus, il faudra se reposer sur des manipulation à base de Canvas HTML5. Arf!

Item Blur Effect with CSS3 and jQuery

Á propos de la balise Canvas: La bibliothèque blurry.js propose une solution particulièrement brutale à cette histoire de flou. Elle va extraire tout le contenu à flouter, va le recréer dans une balise Canvas (en utilisant partiellement Cufón), va le flouter et enfin va réinjecter le tout à l’emplacement de l’original.

En ce qui concerne la netteté, il n’existe actuellement aucun truc basé sur CSS pour réaliser un tel effet, ce qui nous laisse une fois de plus seul face à la balise Canvas.

SVG à la rescousse

Il est intéressant de noter que SVG connaît la notion de filtres depuis des lustres avec, entre autre, les mélanges de couleurs, l’ajustement de la luminosité et du contraste, les effets d’éclairage, le « displacement mapping », les flous gaussien et de déplacement, le bruit, la netteté, etc.

Ainsi, maintenant que SVG est de plus en plus largement supporté, nous pourrions essayer de placer nos contenus, non plus dans du HTML, mais plutôt dans du SVG que l’on placerait dans du HTML. Nous serions alors capables d’appliquer n’importe quel effet à notre contenu. Le problème, c’est que la plupart des intégrateurs HTML risquent de ne pas être très chauds pour se mettre à produire du balisage SVG de ce genre :

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

Il existe un truc un peu plus sympa en SVG, c’est la balise foreignObject. Elle nous permet d’inclure n’importe quel type de balisage à l’intérieur d’un contenu SVG. C’est un peu comme mettre du SVG directement dans un document HTML5, mais dans l’autre sens. Dès que vous avez inclus vos trucs dans du SVG, vous pouvez y appliquer des filtres comme vous le feriez pour n’importe qu’elle autre partis de votre contenu SVG. Vous pouvez embarquer une page HTML entière et lui appliquer des filtres, ou vous restreindre à une simple image bitmap. Bien sûr, vous devez mettre votre contenu SVG lui-même dans une page HTML, ce qui peut conduire à quelques migraines (du HTML embarqué dans du SVG embarqué dans du HTML). Le support navigateur pour la balise foreignObject est plutôt bon. Seul Internet Explorer reste à la traine. Heureusement, Internet Explorer 10 va rattraper le coup en supportant à la fois les filtres SVG et la balise foreignObject.

Les filtres SVG sur du contenu HTML via CSS

Depuis sa version 3.5, Firefox va encore plus loin. Il vous permet d’appliquer un filtre SVG, défini dans un document externe, à n’importe quel contenu HTML en passant simplement par une feuille de style. Nous pouvons, par exemple, définir dans un document SVG un filtre de flou gaussien (feGaussianBlur) ayant un rayon de 2 pixels et lui donner l’identifiant gaussian_blur :

<?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="1" height="1" 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>

On peut alors référencer ce filtre à l’aide du nom du fichier SVG et de son l’identifiant au sein de notre feuille de style pour l’appliquer à toutes les images :

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

Vous pouvez voir cette démo en live ici. Hélas, comme je vous le disais, ça ne fonctionne qu’avec Firefox.

Bien heureusement, ce n’est pas la fin de l’histoire. Internet Explorer connaît lui aussi les filtres. Ceux-ci ne sont pas basés sur SVG, mais sur des mécanismes propres à la bibliothèque graphique de Windows : DirectX. Parmi ces filtres certains sont bien connus pour nous aider à résoudre certains bugs (le filtre alpha pour les image PNG) ou pour imiter certaines fonctionnalités de CSS3 (le filtre des dégradé). Néanmoins, il en existes d’autres très similaires aux filtres SVG :

/* Flou de 2 pixels de rayon */
filter: progid:DXImageTransform.Microsoft.Blur(pixelradius=2);
/* Flou de mouvement de 13 pixel avec un angle de 310° */
filter: progid:DXImageTransform.Microsoft.MotionBlur(strength=13, direction=310);
/* niveau de gris / désaturation */
filter: gray;
/* Effet « Rayon X » (inversion des niveaux de gris) */
filter: xray;
/* cône de lumière */
filter: light();
/* Extrusion */
filter: progid:DXImageTransform.Microsoft.emboss();

Vous trouverez une liste complète de ces filtres ici : http://msdn.microsoft.com/en-us/library/ms673539(v=VS.85).aspx

Ainsi, à l’aide de commentaires conditionnels, nous pouvons désormais proposer un certain nombre d’effets à deux familles de navigateurs qui à elles deux représente une part non négligeable du marché :

<!DOCTYPE HTML>
<!--[if lte IE 9]> <html class="ie" lang="en"> <![endif]-->
<!--[if gt IE 9]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Blur via CSS</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 permet de contre balancer le changement de dimension de l’image provoqué par le filtre. zoom: 1 est necessaire pour que la plupart des filtres fonctionnent avec in IE6/7. Malheureusement, IE10 ne supporte plus les filtres propriétaires de Microsoft et n’autorise pas encore les filtres SVG sur du contenu HTML :(

Vous trouverez ici la version modifié de l’exemple

Un certain nombre de personnes ont apprécié l’idée de Firefox d’ouvrir les filtres SVG au contenu HTML. Ils ont donc formé un nouveau groupe au W3C appelé W3C FX Task Force dont l’objectif est de standardiser et simplifier l’usage des filtres SVG dans tous les navigateurs. Puisque Firefox avait défriché le terrain des filtres d’effets, le premier brouillon de spécification est vite arrivé sous le nom de W3C Filter Effects 1.0. Les mécanismes proposés dans ce brouillon fonctionnent à peu près comme dans Firefox tout en offrant en plus un certain nombre de raccourcis vers les effets les plus intéressants. Les filtres bénéficiant d’un raccourci fonctionnent sans l’aide d’un fichier SVG externe. Ils sont directement codés au cœur du navigateur. Les raccourcis en question sont :

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

Un autre avantage de ces raccourcis, c’est qu’ils peuvent être animés via les transformations et les animations CSS :

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

Ce serait plus difficile et moins efficace de réaliser cela dans un document SVG.

Pour finir, les effets de filtre prévois d’être enrichie à l’aide des vertex shaders et fragment shaders d’OpenGL/WebGL. Les vertex shaders permettront d’appliquer un maillage 2D sur un élément que vous pourrez alors déformer en déplaçant tous les points du maillage selon une formule mathématique de votre choix. Les fragment shaders d’un autre côté permettront de réaliser ces transformations mathématiques sur les couleurs de chacun des pixels de cet élément. Ces deux types de filtres bénéficieront en plus de l’accélération matérielle de votre carte graphique.

CSS shaders Cinematic effects for the web

Par un heureux hasard, il y a quelques semaines les premières implémentations de ces filtres sont apparues dans les compilations nocturnes de Webkit et sont à présent disponibles dans Chrome Canary. Ça veut dire que d’ici 3 mois les filtres CSS seront disponibles dans la version stable de Chrome et à brève échéance dans Safari. Ça veut également dire que nous ne sommes pas loin de pouvoir commencer à utiliser des filtres CSS sur 90 à 95% du marché des navigateurs !

Si l’on en revient à notre exemple, tout ce que nous avons à faire pour supporter Webkit est de rajouter un simple -webkit-filter: blur(2px);. Néanmoins, il faudra faire attention de le placer après la propriété filter non-préfixée. La raison étant que lorsque Webkit supportera la version non-prefixée de la propriété filter, la syntaxe propre à Firefox créra des problèmes avec la transition CSS que nous allons appliquer pour passer doucement entre la version flou et nette de l’image via -webkit-transition: -webkit-filter 1s ease-in-out;.

<!DOCTYPE HTML>
<!--[if lte IE 9]> <html class="ie"> <![endif]-->
<!--[if gt IE 9]><!--> <html> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Blur via CSS</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>

La dernière version de l’exemple

Et voila, des effets de filtres pour tout le monde ! Faisons de 2012 l’année des filtres CSS et amusez-vous bien avec.