1

Plugin SPIP : « CSS imbriqués »

Pré-processeur de CSS

27 septembre 2011
par ARNO*

Voici un pré-processeur de CSS destiné aux webmestres qui manipulent sous SPIP des fichiers CSS particulièrement complexes, avec des imbrications à la chaîne.

Télécharger le plugin « CSS imbriqués »
Télécharger (18.3 ko)

Une des difficultés des CSS, lorsque l’on commence à entrer dans les plus petits détails de l’interface d’un site Web et que l’on veut donc créer des classes très discriminées selon les endroits, est que l’on se retrouve alors avec des listes interminables de classes aux noms de plus en plus longs.

Une idée qui circule sur le Web (par exemple sur le site de Shaun Inman) consiste à écrire ses styles selon une méthode contenant des enrichissements par rapport à la norme, puis à faire passer ces fichiers par un pré-processeur qui les transforme en fichiers CSS standards.

SPIP propose déjà quelques solutions pour aller dans ce sens :
— en passant une feuille de style par le filtre direction_css, on peut l’adapter automatiquement aux langues qui s’écrivent de droite à gauche, l’interface étant intégralement inversée ;
— avec les balises #SET et #GET, si l’on réalise ses styles sous forme de squelettes, on a un système de variables très pratique (par exemple : définir une seule fois la valeur d’une couleur puis l’utiliser dans plusieurs classes ; par la suite, pour changer la couleur de l’ensemble, il suffit d’intervenir uniquement dans la définition de la variable).

Il manque, à mon avis, une autre possibilité offerte par le pré-processeur de Shaun Inman : pouvoir écrire ses définitions de classes sous forme imbriquée (nested), pour en clarifier la lecture.

C’est l’objet du présent plugin.

Voici un court morceau de code CSS standard :

  1. ul#principal {
  2.         border: 1px solid red;
  3.         width: 200px;
  4.         background-color: #aaaaaa;
  5. }
  6. ul#principal li {
  7.                 color: red;
  8. }
  9. ul#principal li  a {
  10.         color: black;
  11. }
  12. ul#principal li.on {
  13.         background-color: red;
  14.         color: white;
  15. }
  16. ul#principal li.on  a {
  17.         color: #ffaaaa;
  18. }

Télécharger

On peut considérer que ce code est artificiellement compliqué, mais en réalité, quand on entre dans les détails d’une mise en page, on se retrouve rapidement avec des systèmes d’héritages beaucoup plus complexe.

L’idée de la méthode des CSS imbriqués est de saisir une classe qui dépend d’une autre classe à l’intérieur de sa définition, sans répéter la hiérarchie des intitulés.

Ainsi le code précédent s’écrit :

  1. ul#principal {
  2.         border: 1px solid red;
  3.         width: 200px;
  4.         background-color: #aaaaaa;
  5.  
  6.         li {
  7.                 color: red;
  8.                
  9.                 a {
  10.                         color: black;
  11.                 }
  12.         }
  13.         li.on {
  14.                 background-color: red;
  15.                 color: white;
  16.                
  17.                 a {
  18.                         color: #ffaaaa;
  19.                 }
  20.         }
  21. }

Télécharger

Il existe une autre subtilité : la possibilité, dans une classe imbriquée, de faire précéder le nom de la classe imbriquée par un point suivi d’un espace ; cela indique que cette classe est une variante de la précédente (plus simplement : on « colle » les deux noms). Voici par exemple une manière de code a.spip_in, a.spip_out :

  1. a {
  2.         . .spip_in {...}
  3.         . .spip_out {...}
  4. }

Télécharger

et avec des variantes de survol :

  1. a {
  2.         . .spip_in {
  3.                 ...
  4.                 . :hover {...}
  5.         }
  6.         . .spip_out {
  7.                 ...
  8.                 . :hover {...}
  9.         }
  10. }

Télécharger

Notez bien : cette notation n’est pas standard et ne correspond pas à la norme des CSS. Il s’agit d’un système de notation qui doit être impérativement traduit de manière logicielle (par le présent plugin) pour qu’un fichier CSS standard soit envoyé au visiteur.

Remarque : l’utilisation du plugin ne vous interdit pas d’utiliser la notation d’une manière respectant la norme : le plugin admet des fichiers totalement standards, ou totalement imbriqués, ou utilisant les deux notations (la méthode imbriquée n’étant qu’une extension de la norme).

Pour que ce plugin traite votre fichier CSS, il faut l’utiliser de la même façon qu’on utilise direction_css, ou en complément de ce dernier, en passant le fichier par css_imbriques :

  1. [<link rel="stylesheet" href="(#CHEMIN{monstyle.css}|direction_css|css_imbriques)" type="text/css" />]

Si vous réalisez votre feuille de style sous forme de squelette (ma méthode préférée), il suffit d’ajouter, en fin de squelettes (par exemple « css.html »), la balise :

  1. #FILTRE{css_imbriques_decouper}

Une autre méthode pour utiliser des CSS imbriqués dans une feuille de style sous forme de squelette (ici, couleur.html) consiste à l’appeler ainsi :

  1. <link
  2.         rel="stylesheet"
  3.         href="[(#URL_PAGE{couleur}|direction_css|css_imbriques)]"
  4.         type="text/css" />

Télécharger

Cette dernière méthode est particulièrement compatible avec la fonction de SPIP qui regroupe différents fichiers CSS dans un même fichier compacté.

Notez enfin que ces fonctions, contrairement à direction_css, ne traitent pas les @import présents à l’intérieur des fichiers CSS. Dans la version actuelle, il y a des chances que ces @import disparaissent (bug à corriger pour une prochaine version).

Pseudo-styles

La version 1.2 du plugin introduit des pseudo-styles, non standards, permettant de coder facilement des fonctionnalités des CSS (généralement qualifiées de « CSS 3 ») qui demandent habituellement plusieurs lignes de code, voire des codes très farfelus pour assurer une compatibilité maximale pour le webkit (Safari, Chrome), Mozilla, Opera et MSIE.

Ces pseudo-styles, à l’image des raccourcis propres à Mozilla (styles commençant par -moz) ou le webkit (-webkit), commencent ici par le -spip. Il permettent en une seule ligne, assez simple, de produire automatique les différents codes nécessaires à l’affichage cohérent sur les différents navigateurs.

• Opacité

Voici le pseudo-style pour gérer l’opacité :

  1. .exemple {
  2.         -spip-opacity: 0.4;
  3. }

Télécharger

Ce -spip-opacity est ainsi transformé par le plugin :

  1. .exemple {
  2.         -webkit-opacity:0.4;
  3.         -moz-opacity:0.4;
  4.         opacity:0.4;
  5.         -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=40)";
  6.         zoom:1;
  7. }

Télécharger

À partir d’une seule déclaration (-spip-opacity), on obtient ainsi automatiquement le code fonctionnant sous d’anciennes versions de Safari, sous Mozilla 3.5, sous Chrome et Safari, ainsi que sous Internet Explorer (notez l’utilisation d’un « filtre » MSIE et la valeur d’opacité adaptée.

• Coins arrondis

Le code de base arrondi d’un coup tous les coins :

  1. -spip-border-radius: 6px;

On peut préciser une valeur pour chacun des coins du pavé :

  1. -spip-border-top-right-radius: 0px;
  2. -spip-border-top-left-radius: 3px;
  3. -spip-border-bottom-right-radius: 14px;
  4. -spip-border-bottom-left-radius: 2px;

Télécharger

— Inset

  1. -spip-inset: 1px 2px 3px 4px;

est transformé en :

  1. top: 1px;
  2. right: 2px;
  3. bottom: 3px;
  4. left: 4px;

Télécharger

Évidemment, on abusera de :

  1. -spip-inset: 0;

pour positionner une boîte exactement sur son contenant.

• Ombre de boîte

  1. -spip-box-shadow: 3px 2px 10px #666666;

La première valeur (3px) est le décalage de l’ombre portée vers la droite. La seconde (2px) est le décalage vers le bas. La troisième (10px) est l’intensité du floutage de l’ombre. La dernière valeur est la couleur.

En mettant les deux premières valeurs à zéro, on obtient assez classiquement un halo autour de la boîte, et non une ombre portée.

• Dégradé

  1. -spip-gradient: top, #f0f0f0, #bbbbbb;

Je n’ai pas trouvé de consensus sur la syntaxe exacte d’un dégradé de fond, aussi je me suis inspiré de ce que propose le W3C, en essayant de faire aussi simple que possible. À noter : les différents navigateurs ont de puissantes particularités, mais la méthode proposée est simple et le rendu est très proche sous Mozilla, Safari, Chrome et... Internet Explorer (même de vieilles versions !).

Le code produit est assez farfelu :

  1. background:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#bbbbbb));
  2. background-image:-moz-linear-gradient(top,#f0f0f0,#bbbbbb);
  3. filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#f0f0f0',endColorstr='#bbbbbb');

Télécharger

La syntaxe de notre pseudo-style est la suivante :
— « top » l’orientation du dégradé (de haut en bas) ; l’autre valeur possible est « left » (de gauche à droite) ; il n’est pas possible de faire un dégradé en biais (MSIE ne sait pas le faire, et les dégradés verticaux et horizontaux représentent en pratique un bonne partie des besoins) ;
— la première couleur est la couleur de départ (ici, la couleur du haut),
— la seconde est la couleur d’arrivée (ici, en bas).

Pour assurer la compatibilité avec les navigateurs qui ne gèrent pas les dégradés, on pensera à indiquer, dans la feuille de style, la couleur de fond que l’on souhaite. Notez bien : il faut impérative indiquer cette valeur avant le dégradé, sinon on écrase le dégradé :

  1. background: #dddddd;
  2. -spip-gradient: top, #f0f0f0, #bbbbbb;

Télécharger

Important : les couleurs de dégradé doivent être indiquées sous forme hexadécimale « classique » à six lettres (pour la compatibilité du code pour MSIE) ; par ailleurs, l’actuel compacteur de CSS livré avec SPIP est en effet un peu trop « efficace », et transforme les codes couleurs composés de trois paires de lettres identiques (du genre #ff0066 transformé en #f06) d’une façon qui ne permet plus au dégradé MSIE de fonctionner. Si vous utilisez le compactage des CSS (et vous devriez le faire...), choisissez des couleurs qui n’ont pas d’équivalent à trois lettres (tel que #ff0066).

À partir de la version 3.3, on peut utiliser des couleurs roba :

  1. -spip-gradient: top, rgba(100, 50, 0, 0.85) , rgba(50, 50, 2, 0.25);

• Fond de bloc semi-transparent

Pour réaliser des fonds de bloc colorés semi-transparents, dans les navigateurs modernes, il suffit de définir la couleur de fond en rgba (on code les 3 composantes de couleurs, suivies d’une valeur d’opacité).

Évidemment, pas sous MSIE.

Le pseudo-raccourci suivant transforme les valeurs pour qu’elles fonctionnent « normalement » en RGBA, et fabriquent le filtre approprié pour MSIE.

  1.         -spip-background-color: rgba (255, 255, 127, 0.5);

On peut aussi utiliser des pourcentages :

  1.         -spip-background-color: rgba (100%, 100%, 50%, 0.5);

Notez bien : n’insérez pas de background-color traditionnel avec ce style, sinon il écrasera l’effet de transparence sous MSIE.

• Transitions

La versions 1.3 du plugin traite les transitions CSS :

  1. -spip-transition
  2. -spip-transition-property
  3. -spip-transition-duration
  4. -spip-transition-timing-function
  5. -spip-transition-delay

Télécharger

Par exemple, pour effectuer une transition sur la couleur du fond, on peut coder ainsi :

  1. a {
  2.         background-color: #eeeeeee;
  3.         -spip-transition-property: background-color;
  4.         -spip-transition-duration: 0.1s;
  5. }
  6. a:hover {
  7.         background-color: #cccccc;
  8. }

Télécharger

• Text shadow

L’ombre portée du texte se code avec -spip-text-shadow.

Son intérêt à limité à une situation (qui n’est cependant pas inutile du tout) : lorsque les décalages horizontal et vertical sont nuls, c’est qu’on souhaite réaliser un halo autour du texte.

Dans ce cas, le plugin insère un code compatible MSIE.

  1. -spip-text-shadow: 0px 0px 3px #000000;

• Compatibilité

D’après mes essais, la compatibilité est assez bonne, y compris avec MSIE. Habituellement, ces effets se dégradent bien, visuellement, lorsqu’ils ne sont pas actifs. On perd des effets de relief, mais la page n’est pas « déformée » (trucs qui dépassent partout) et le texte reste lisible.

Sous MSIE, on pourra être amené à changer l’ordre des différents styles, certains ayant tendance à en désactiver d’autres (il semble par exemple que l’opacité, placée après la dégradé, annule le dégradé).

Les deux choses à surveiller principalement sont :
— la dégradation de l’opacité ;
— la mention explicite d’une couleur de fond avant la définition d’un dégradé de fond.

• Clearfix

On a souvent besoin d’être certain que les « float » sont dégagés à la fin d’un bloc (qui contient, donc des blocs flottants à gauche et/ou à droite). On souhaite éviter d’ajouter un « clear:both » à la suite de ce bloc : on veut que ce soit le bloc lui-même qui contienne l’ordre de libérer les blocs flottants à sa suite.

Pour cela, il existe la méthode dite « clearfix », qui consiste à créer une classe spécifique, .clearfix, que l’on insère dans le code HTML des blocs concernés.

Voir par exemple : http://nicolasgallagher.com/micro-c....

Le plugin CSS imbriqués propose un pseudo-style qui donne le même résultat :

  1. -spip-float: fix;

Le gros avantage de cette méthode, c’est qu’il n’est pas nécessaire d’ajouter une classe dans le code HTML de la page : on peut avec ce pseudo-style forcer le comportement de n’importe quelle class sans modification de code HTML.

• Pseudo-styles libres

En dehors des cas prévus ci-dessus, tout pseudo-style commençant par -spip- est automatiquement transformé dans les déclinaisons pour Mozilla, Webkit, MSIE, Opera et en CSS3 « simple ».

Noter que le préprocesseur ne vérifie pas que ces styles existent réellement.

Ainsi,

  1. -spip-user-select: none;

est transformé en :

  1. -moz-user-select: none;
  2. -webkit-user-select: none;
  3. -khtml-user-select: none;
  4. -ms-user-select: none;
  5. -o-user-select: none;
  6. user-select: none;

Télécharger

@media

Les CSS3 introduisent la notion de @media, qui permet de définir des comportements de classes selon divers critères (support, largeur d’affichage...).

À partir de la version 1.8, le plugin CSS imbriqués est compatible avec ces pseudo-classes définissan les @media. Il introduit de plus une subtilité qui permet de définir les @media à l’intérieur d’une hiérarchie (puisqu’ici, les CSS peuvent-être imbriqués), le plugin reconstituant ensuite des classes de @media correctes (à la « racine » des déclarations), regroupant les différentes définitions d’un même média.

Cela permet de définir localement la variante d’une classe en fonction du média, le plugin regroupant ensuite toutes les variantes de classe d’un même média en fin de fichier.

Par exemple :

  1. .colonne_texte {
  2.         background-color: white;
  3.  
  4.         a { color: blue; }
  5.  
  6.         @media all and (min-width: 640px) {
  7.                 a { color: red; }
  8.         }
  9. }
  10.  
  11. @media all and (min-width: 1024px) {
  12.         #fond_degrade {
  13.                 width: 100%;
  14.                 height: 400px;
  15.                 position: absolute;
  16.                 top: 0px;
  17.                 left: 0px;
  18.         }
  19. }

Télécharger

devient :

  1. .colonne_texte {background-color: white;}
  2. .colonne_texte a {color: blue;}
  3.  
  4. @media all and (min-width: 640px){
  5.         .colonne_texte a {color: red;}
  6. }
  7.  
  8. @media all and (min-width: 1024px){
  9.         #fond_degrade {width: 100%;height: 400px;position: absolute;top: 0px;left: 0px;}
  10. }

Télécharger

Mise à jour

1.0. Accepter les critères sur plusieurs lignes, du style :

  1. a,
  2. a.spip_in,
  3. a.spip_out {
  4.         text-decoration: none;
  5.         color: #ff0000;
  6. }

Télécharger

1.1. Les ereg sont remplacés par des mb_ereg (compatibilité PHP 5.3).

1.2. Introduction de pseudo-styles -spip... permettant de créer automatiquement des styles compatibles Webkit, CSS3, Mozilla et MSIE. Tous les mb_ereg sont remplacés par des preg plus classiques.

1.3. Introduction des pseudo-styles pour les transitions CSS.

1.4. Introduction du pseudo-style -spip-background-color.

1.5. Introduction de -spip-text-shadow.

1.6. Introduction de la fonction couleur_rgba($couleur, $alpha) qui permet de fabriquer une couleur RGBA à partir d’un code hexadécimal.

1.7. Introduction de -spip-float: fix; qui permet de faire adopter par n’importe quelle classe le comportement « clearfix » (sans devoir ajouter de classe dans le code HTML).

1.8. Compatibilité avec les @media queries.

1.9. Ajout du comportement PIE.htc, inséré automatiquement dans les pseudo-comportements -spip-border-radius et -spip-box-shadow. Ces deux pseudo-classes fonctionnent donc désormais sous MSIE.

À noter : dans ces deux pseudo-classes, si aucune position n’est indiquée explicitement, le plugin injecte automatiquement une position:relative;, de façon à assurer le bon fonctionnement sous Internet Explorer.

2.0. Gestion des mediaqueries imbriquées. Le plugin « inverse » la structure par la suite.

2.1. Suppression du comportement PIE.htc (et de l’ajout de « position:relative ») : résultat beaucoup trop aléatoire.

2.3. Retour de PIE.htc, mais on peut le désactiver avec :

  1. define("_UTILISER_PIE_HTC", false);

Si on n’insère pas PIE.htc, le plugin n’insère plus les mentions de position dans les classes pseudo-classes border-radius et box-shadow.

2.4. Tous pseudo-style commençant par -spip- est transformé dans ses équivalents -moz-, -webkit-, -o-, -ms-

3.0. Compatibilité avec SPIP 3.

3.1 Compatibilité avec les @keyframes. Par cohérence, on pourra utiliser @-spip-keyframes. Dans tous les cas, le plugin fabriquera toutes les versions avec les différents préfixes.

Et pour appeler ces keyframes, utiliser évidemment -spip-animation, qui fabriquera également les versions avec les préfixes nécessaires.

Remarque. Le minifieur de CSS intégré a SPIP n’autorise pas d’intitulé de CSS baptisé « 0% » (il le remplace par « 0 »). Ce qui bloque les keyframes qui commencent par cet intitulé. Le pré-processeur remplace donc automatiquement l’intitulé « 0% » par « from ».

3.3 Possibilité d’utiliser des couleurs rgba dans les gradients.

3.8 Ajour de -spip-inset, qui s’utilise comme le caractéristique CSS insert, mais qui est automatiquement transformé en valeurs de left, right, top, bottom.

Les insertions de fichiers .htc ne sont plus activées par défaut. Si on tient à les utiliser, il faut donc déclarer :

  1. define("_UTILISER_PIE_HTC", true);
  2. define("_UTILISER_BOXSIZING_HTC", true);

Télécharger

Qui êtes-vous ?
Votre message

Ce formulaire accepte les raccourcis SPIP [->url] {{gras}} {italique} <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.