La partie des CSS3 qui semble défrayer la chronique des blogs et de la presse est la partie la plus bling-bling !! Des bordures arrondies, de l’ombrage sur les boites et les nouvelles méthodes pour monter des structures de pages web sont des fonctionnalités très attrayantes.
Elles amènent évidemment avec elles une multitude de nouvelles possibilités pour le design web.

À part ça, ce qui m’a vraiment mis en transe en tant que développeur est un peu plus mondain.

Dans ce billet, je vais mettre en exergue comment les CSS3 vont simplifier le code de nos « front et back-end ». Je vais analyser comparativement la façon dont nous arrivons à créer certains effets visuels et comment faire de même dans un glorieux « CSS3-supported » futur.

Je vais aussi vous faire la démonstration de comment utiliser ces sélecteurs avec l’aide d’un peu de Javascript, ce qui peut vous enlever une sacrée épine du pied dans le cas ou vous ne pourriez pas changer les balises d’un code généré du coté serveur (par ex. php ou Ruby).

Le merveilleux nth-child

Pourquoi nth-child m’a tant esbroufé ? Voici une situation classique, le designer Web souhaite que les tableaux s’affichent de cette manière :

tableauMettre chaque rangée du tableau dans une couleur différente est une pratique usuelle afin d’améliorer la lisibilité du tableau. La méthode testée et approuvée est d’appliquer une classe à chaque rangée.
Si vous écrivez vous même le code source à la main cela peut devenir une sérieuse souffrance, de plus si vous devez insérer une rangée en plein milieu du tableau il vous faudra tout revoir pour que la mise en page soit correcte.
Si votre code est généré coté serveur, vous devrez donc avoir accès à la fonction qui le génère afin d’y adjoindre le marqueur de classe.

<title>Une couleur sur chaque rangée - à l'aide de classe</title>

 

<style type="text/css">

body {

padding: 40px;

margin: 0px;

font: 0.9em Arial, sans-serif;

}

table {

border-collapse: collapse;

border: solid 1px #124412;

width: 600px;

}

th {

border: solid 1px #124412;

background-color: #334f33;

color: #fff;

padding: 0.4em;

text-align: left;

}

td {

padding: 0.4em;

}

tr.odd td {

background-color: #86b486;

}

</style>

 

<table>

<tbody><tr class="odd">

<th>Nom</th>

<th>Cartes envoyées</th>

<th>Cartes reçues</th>

<th>Cartes écrites mais non-envoyées</th>

</tr>

<tr>

<td>Anne</td>

<td>40</td>

<td>28</td>

<td>4</td>

</tr>

<tr class="odd">

<td>Joe</td>

<td>2</td>

<td>27</td>

<td>29</td>

</tr>

<tr>

<td>Paul</td>

<td>5</td>

<td>35</td>

<td>2</td>

</tr>

<tr class="odd">

<td>Louise</td>

<td>65</td>

<td>65</td>

<td>0</td>

</tr>

</tbody></table>

Cette situation est récurrente sur quasi tous les projets, et à part un truc à faire en plus, cela n’a rien de fun. De plus, générer le marqueur de classe coté serveur n’est pas vraiment approprié (du point de vue de la présentation). C’est donc ici que le pseudo-sélecteur nth-childentre en scène !! Le code généré coté serveur fourni une balise html « table » valide pour  y ranger les données et les CSS prennent en charge l’alternance des rangées à l’aide du sélecteur suivant :

tr:nth-child(odd) td {

    background-color: #86b486;

    }

Les mot-clés « odd » et « even » sont très utiles dans cette situation, mais vous pouvez aussi utiliser des multiplicateurs. 2n serait l’équivalent du mot-clé « odd », 3n sélectionnerait chaque troisième rangée et ainsi de suite…

Support des navigateurs

Malheureusement, nth-child est très mal pris en charge par les navigateurs. Tout simplement non-supporté par Internet-Explorer 8 et de manière très aléatoire par certains autres navigateurs. Seul Firefox 3.5 le supporte intégralement. Dans certains cas vous devrez peut être considérer l’usage de JavaScript pour arriver à vos fins. Ce sera fort utile si vous utilisez un CMS sur lequel vous ne pouvez pas changer le code source pour y adjoindre la tant désirée classe. Je vais donc utiliser jQuery dans ces exemples, puisqu’il est très simple d’utiliser le même sélecteur CSS pour pointer vers l’élément. Vous pouvez tout aussi bien utiliser un autre framework JavaScript ou encore écrire votre propre fonction JavaScript pour y arriver. J’ai donc rajouté au sélecteur nth-childle sélecteur original :

tr:nth-child(odd) td, tr.odd td {

    background-color: #86b486;

    }

Puis j’ajoute un peu de jQuery pour qu’une fois le document chargé, soit ajoutée une classe dans le code html en utilisant le sélecteur nth-child.

<script src="http://code.jquery.com/jquery-latest.js"></script>

    <script>

    $(document).ready(function() {

    $("tr:nth-child(odd)").addClass("odd");

    });

</script>

Nous aurions pu simplement ajouter de la couleur de fond à l’aide de JavaScript, mais je préfère ne pas mélanger ce genre d’information dans le JavaScript, car s’il devait y avoir un changement de couleur pour la table, il faudrait se souvenir de le modifier dans la feuille de style et dans le JavaScript.

Faire du dernier un élément différent

Voici donc un autre cas que nous avons régulièrement à traiter. Nous avons une liste d’éléments flottants à gauche avec une marge à droite dans un espace contraint. Si tous les éléments ont cette marge, le dernier sera donc repoussé à la ligne… Last-childDans l’absolu, nous avons deux manières de traiter ce type de problématique. Nous pourrions mettre une marge négative au conteneur de liste de la même taille que celle séparant les éléments de la liste. De ce fait l’encombrante marge remplirait cet espace et donc le dernier élément ne serait pas renvoyé à la ligne.

<title>Faire du dernier un élément différent</title>

 

<style type="text/css">

body {

padding: 40px;

margin: 0px;

font: 0.9em Arial, sans-serif;

}

div#wrapper {

width: 740px;

border: solid 5px #ccc;

}

ul.gallery {

margin: 0px -10px 0px 0px;

padding: 0px;

list-style: none;

}

ul.gallery li {

float: left;

width: 240px;

margin: 0px 10px 10px 0px;

}

</style>

 

<div id="wrapper">

<ul class="gallery">

<li><img src="xmas1.jpg" alt="baubles"></li>

<li><img src="xmas2.jpg" alt="star"></li>

<li><img src="xmas3.jpg" alt="wreath"></li>

</ul>

</div>

L’autre solution eut été de mettre une classe au dernier élément et dans la feuille de style de supprimer la marge pour cette même classe.

ul.gallery li.last {

    margin-right: 0px;

    }

Cette dernière solution peut être problématique si le code est généré par un CMS auquel vous n’avez pas accès. Ce pourrait être tellement différent. En CSS3 nous avons un sélecteur qui tombe sous le sens, le fantastique last-child qui veut dire, comme son nom l’indique, qu’on peut appliquer en toute facilité, des règles au dernier élément.

ul.gallery li:last-child {

    margin-right: 0px;

    }

Ceci supprime la marge du dernier (last-child) li du ul avec la classe gallery. Aucun soucis avec la classe qui est appliquée au dernier élément, ni même besoin d’appliquer une marge négative. Si la liste est répétée ad-infinitum nous aurions pu utiliser nth-child pour cette tâche. En créant une règle pour chaque triptyque d’éléments.

ul.gallery li:nth-child(3n) {

    margin-right: 0px;

    }

Liste d'images

Un exemple similaire, lorsque le designer souhaite avoir une bordure au bas de chaque élément, mais pas sur le dernier ou alors d’un autre type.
Une fois de plus,seule une classe ajoutée au dernier élément règlerait notre soucis, si vous ne pouvez pas utiliser le sélecteur last-child.
Support des navigateurs

La situation pour last-child est quasi la même que pour nth-child, à savoir pas de support sur IE8. Ceci dit il est encore une fois très facile de répliquer cette fonction à l’aide de jQuery.

Ajouter notre classe .last au dernier élément :

$("ul.gallery li:last-child").addClass("last");

Nous aurions pu aussi utiliser le sélecteur nth-child pour ajouter la classe .last à chaque triptyque d’éléments.

$("ul.gallery li:nth-child(3n).addClass("last");

Du fun et des forms

Habiller des formulaires peut parfois ne pas être une partie de plaisir car toutes règles appliquées à input aura un effet sur tous les champs texte : les boutons « submit », les cases à cocher et les boutons radios.

En tant que développeurs, nous en sommes venus à attribuer des classes à chaque élément afin de les différencier.

Dans la plupart de mes montages de formulaires j’ai simplement une classe text, c’est un peu comme avoir une classe para pour chaque paragraphe d’un document.

<title>Habiller des formulaires</title>

 

<style type="text/css">

body {

padding: 40px;

margin: 0px;

font: 0.9em Arial, sans-serif;

}

form div {

clear: left;

padding: 0px 0px 0.8em 0px;

}

form label {

float: left;

width: 120px;

}

form .text, form textarea {

border: solid 1px #333;

padding: 0.2em;

width: 400px;

}

form .button {

border: solid 1px #333;

background-color: #eee;

color: #000;

padding: 0.1em;

}

</style>

 

<h1>Envoyer sa liste de cadeaux à Saint Nicolas</h1>

<form method="POST" action="" id="nicolas-list">

<div><label for="fName">Nom</label>

<input name="fName" id="fName" class="text" type="text">

</div>

<div><label for="fEmail">Email</label>

<input name="fEmail" id="fEmail" class="text" type="text">

</div>

<div><label for="fList">Liste</label>

<textarea name="fList" id="fList" rows="10" cols="30"></textarea>

</div>

<div><label for="fName">Nom</label>

<input name="fName" id="fName" class="text" type="text">

</div>

<div><input name="btnSubmit" id="btnSubmit" value="Propulser" class="button" type="submit"></div>

</form>

Les sélecteurs d’attribut permettent d’agir sur certains éléments à l’aide de leurs attributs. Aux antipodes de cet article sur les CSS3, les sélecteurs d’attribut sont des règles CSS 2.1, peu d’entre nous en font l’usage à cause du mauvais support dans IE6.
En utilisant ces sélecteurs d’attribut nous aurions pu écrire des règles CSS pour les champs text et submit sans même avoir besoin de faire appel à des classes.

Par exemple après avoir supprimé du code ci-dessus les classes text et button de mes champs input, je peux utiliser les règles suivantes pour les modifier.

form input[type="text"] {

    border: solid 1px #333;

    padding: 0.2em;

    width: 400px;

    }

    form input[type="submit"] {

    border: solid 1px #333;

    background-color: #eee;

    color: #000;

    padding: 0.1em;

    }

Un autre problème que je rencontre souvent, lorsque j’utilise le flottant pour positionner mes label à coté des éléments des formulaires. Tout fonctionne bien si je veux tous les label en flottant, mais parfois j’ai des « boutons radios » ou une « case à cocher » et ne souhaite pas que les label soient flottants, et là… c’est le drame !
Comme vous pouvez le voir dans l’exemple ci dessous, le label de la case à cocher est coincé dans l’espace utilisé par l’autre label. Ici, il y aurait tout de même un peu plus de sens à afficher le label après le texte, non?

damn my label position suck

J’aurais pu utiliser une classe pour ce label, mais les CSS3 me permettent de cibler directement le label par son attribut for.

label[for="fOptIn"] {

    float: none;

    width: auto;

    }

what a nice label

Avoir la possibilité de cibler précisément les attributs de cette manière est très utile. Une fois débarrassé d’IE6, cela va nous aider à édulcorer notre code, et ainsi éviter d’avoir à ajouter trop de conditionnelles dans le code coté serveur.
Support des navigateurs

Les nouvelles sont plutôt bonnes pour les sélecteurs d’attributs, la compatibilité est assurée correctement à partir de IE7+ et Firefox 2.0+ ainsi que sur tous les navigateurs modernes.
Comme je l’ai déjà dit, il s’agit de règles compatibles avec le CSS2.1, donc nous sommes en bonne posture pour dire que nous devrions pouvoir l’utiliser début 2010.

Internet Explorer 7 est encore légèrement buggé sur les règles CSS3 et a du mal à gérer les attributs for du label, mais comme précisé sur le site : Sitepoint CSS reference comments reference comments, ajouter le sélecteur label[htmlFor= »fOptIn »] ciblera correctement dans IE7.

Internet Explorer 6 encore une fois, ne supporte pas ce type de sélecteur, mais à l’aide de jQuery il est possible de faire en sorte de palier ces lacunes.
Le code source suivant ajoutera les classes text et button aux champs input ainsi que la classe check aux label des cases à cocher.


$('form input[type="submit"]').addClass("button");

$('form input[type="text"]').addClass("text");

$('label[for="fOptIn"]').addClass("checks");

Les sélecteurs que nous avons choisis pour cet article, sont faciles à reproduire dans des cas concrets que nous produisons chaque jour en tant que développeurs, spécialement lors d’utilisation de « frameworks ».

Je pense que le temps est venu pour le nettoyage du code source de nos « front et back-end »et de supprimer nos classes habituelles pour nous reposer sur les nouveaux sélecteurs CSS3.
Avec l’aide d’un peu de JavaScript, quasiment tous les internautes pourront avoir le plaisir de bénéficier d’une parfaite expérience utilisateur. Là nous ne parlons que d’un point de vue purement visuel, et il n’y a définitivement pas lieu de s’inquiéter pour le petit nombre d’utilisateurs qui ont des navigateurs obsolètes avec aucun support pour le JavaScript.
Ils bénéficieront toujours d’un site internet exploitable, il leur manquera juste la finesse visuelle apportée pas les navigateurs modernes.