CSS is awesome

Introduction au CSS.

Le CSS est un langage permettant de définir des styles visuels pour des documents structurés.

Son fonctionnement est simple, mais sa mise en œuvre est complexe. En effet, on travaille avec de nombreuses inconnues:

  • Les documents pour lesquels on crée les styles sont évolutifs.
  • Le support de lecture n’est pas défini, un site pouvant être visionné sur des appareils aux propriétés variables.

Pourquoi le CSS est un art difficile.

Historique

Le langage CSS (Cascading Style Sheets) est apparu en 1996, afin de proposer une meilleure manière de créer des sites internet, en séparant le contenu (HTML) de la présentation. CSS1 se définit comme un « mécanisme de feuille de style simple, permettant aux auteurs et aux lecteurs d’attacher des styles (…) au document HTML ». Cette simplicité se traduit par le choix d’un langage qui peut être aisément lu et écrit directement par ses utilisateurs humains, et d’une terminologie conforme aux usages courants dans la publication informatique.

Le standard CSS s’enrichit progressivement de nouvelles capacités, afin de répondre aux besoins des créateurs et utilisateurs du web. Alors que CSS1 définit essentiellement les propriétés de rendu typographique du texte, la spécification CSS 2, publiée en 1998, étend considérablement les possibilités théoriques des CSS, avec environ 70 propriétés supplémentaires. suivie par une version révisée, CSS 2.1, qui est restée en chantier pendant des années, avant d’atteindre le statut de Recommandation W3C en 2011.

La spécification CSS 3, qui l’a suivie, a été développée sous la forme de modules indépendants, dans le but que des modules “prêts” puissent être implémentés rapidement par les navigateurs. Cet objectif a été atteint, et de nombreux modules sont actuellement bien supportés par les navigateurs et utilisés au quotidien (p.ex. WebFonts, Media Queries, Flexbox, Backgrounds & Borders), alors que d’autres sont encore en développement.

L’année 2010, qui marque une large adoption du standard HTML5, représente une avancée importante pour le CSS 3. C’est en 2010 que sort le livre “CSS3 for Web Designers”, par Dan Cederholm, et que le terme “Responsive Web Design” fait son apparition, sous la plume d’Ethan Marcotte.

CSS Working Group
Le CSS Working Group du W3C, lors d’une réunion en 2010

Principes de base

“Fundamental concepts of CSS like cascading, specificity rules, selectors, inheritance, box model and stacking context must be well understood.” - Thanh Tran

La langage CSS permet de définir des règles, qui sont exprimées sous forme de couples propriété: valeur.

Les propriétés sont libellées à l’aide de mots-outils anglais tels que width (largeur), font-size (taille de la police de caractères) ou background-color (couleur de fond). Ces propriétés sont spécifiées dans le standard CSS.

Les valeurs sont exprimées à l’aide d’unités (pixels, pourcents…), ou de mots-clés propres au CSS. Par exemple, une couleur peut être exprimée à l’aide des mots clés (“black”, “blue”, etc), de valeurs hexadécimales (p.ex. #FF0000) ou du modèle RGB.

Les couples propriété-valeur constituent le “bloc de déclaration” d’une règle CSS. S’il y en a plusieurs, on les sépare avec des points-virgule. Ces déclarations seront appliquées à des parties du document identifiées par un sélecteur.

Chaque règle CSS comporte un sélecteur, et un bloc de déclaration.

Exemple de règle CSS:

h1 {
    color: red;
    text-transform: uppercase;
}

Dans cet exemple, nous avons:

  • le sélecteur: h1
  • le bloc de déclaration, qui contient deux déclarations: color: red; et text-transform: uppercase;
  • la première déclaration définit une propriété: color
  • avec la valeur: red
  • la seconde déclaration définit la propriété text-transform;
  • avec la valeur: uppercase

Résultat: dans cette régle, on applique un style à tous les éléments h1 du document: la couleur du texte sera rouge (red), et tous les caractères seront affichés en majuscules (uppercase).

Les sélecteurs CSS

Le sélecteur définit à quel élément de la page un style CSS sera appliqué. Par exemple:

H1 { color: Tomato }

La couleur Tomato sera appliquée à tous les éléments H1 de la page.

Il est possible de grouper plusieurs sélecteurs, en les séparant par des virgules. Exemple:

H1 { color: Tomato }
H2 { color: Tomato }
H3 { color: Tomato }

Ces trois règles peuvent être groupées comme ceci:

H1, H2, H3 { color: Tomato }

L’importance des sélecteurs

Le choix des sélecteurs appropriés joue un grand rôle, c’est là que se joue la qualité architecturale du code CSS.

Quand on essaie de juger la qualité d’un code CSS, la partie à l’intérieur des crochets, les valeurs et propriétés, c’est la partie “cosmétique”. Ça marche, ou pas.

Le choix des sélecteurs, au contraire, est très délicat, et repose sur des hypothèses:

The stuff outside the curly braces — the selectors — that’s harder to judge. It needs to be evaluated with lots of “what ifs”: What if this selects something you didn’t intend to? What if the markup changes? What if someone else writes some CSS that negates this? Jeremy Keith

Sélecteurs du CSS niveau 1

E tout élément de type E
E:link tout élément E qui est l’ancre d’un hyperlien
E:visited un hyperlien qui a déjà été visité
E:hover un élément E que l’utilisateur survole
E:focus un élément E faisant l’objet d’une sélection, notamment en utilisant le clavier
E:active un élément E soumis à des actions utilisateur
E::first‑line la première ligne d’un élément E
E::first‑letter la première lettre d’un élément E
.c tout élément ayant la classe “c”
#myid tout élément avec un ID égal à “myid”
E.warning tout élément E ayant la classe “warning”
E#myid tout élément E avec un ID égal à “myid”
E F un élément F qui est contenu dans un élément E

Voici un exemple utilisant “first-letter” pour produire une lettrine:

p::first-letter {
  font-size: 200%;
  float: left;
}

Sélecteurs du CSS niveau 2

* tous les éléments du document
E[foo] an E element with a “foo” attribute
E[foo="bar"] an E element whose “foo” attribute value is exactly equal to “bar”
E[foo~="bar"] an E element whose “foo” attribute value is a list of whitespace-separated values, one of which is exactly equal to “bar”
E[foo|="en"] an E element whose “foo” attribute has a hyphen-separated list of values beginning (from the left) with “en”
E:first‑child an E element, first child of its parent
E:lang(fr) an element of type E in language “fr”
E::before generated content before an E element’s content
E::after generated content after an E element’s content
E > F an F element child of an E element
E + F an F element immediately preceded by an E element

Un exemple réel:

input[type="checkbox"],
input[type="radio"] {
	padding: 0;
}

Cette règle annule le “padding” pour les éléments interactifs de type “case à cocher” ou “bouton radio” .

Voici un autre exemple réel, plutôt subtil:

a[href]:after {
	content: " (" attr(href) ")";
}

Cette règle est contenue dans les feuilles de style “print” (dédiées à l’impression) du framework HTML5Boilerplate. Son effet est de détecter tous les liens (élément a ayant un attribut href), et va afficher à la suite du lien son URL. Ainsi, si on imprime une page du site, chaque lien sera suivi de l’URL.

Sélecteurs du CSS niveau 3

E[foo^="bar"] an E element whose “foo” attribute value begins exactly with the string “bar”
E[foo$="bar"] an E element whose “foo” attribute value ends exactly with the string “bar”
E[foo*="bar"] an E element whose “foo” attribute value contains the substring “bar”
E:root an E element, root of the document
E:nth‑child(n) an E element, the n-th child of its parent
E:nth‑last‑child(n) an E element, the n-th child of its parent, counting from the last one
E:nth‑of‑type(n) an E element, the n-th sibling of its type
E:nth‑last‑of‑type(n) an E element, the n-th sibling of its type, counting from the last one
E:last‑child an E element, last child of its parent
E:first‑of‑type an E element, first sibling of its type
E:last‑of‑type an E element, last sibling of its type
E:only‑child an E element, only child of its parent
E:only‑of‑type an E element, only sibling of its type
E:empty an E element that has no children (including text nodes)
E:target an E element being the target of the referring URI
E:enabled a user interface element E that is enabled
E:disabled a user interface element E that is disabled
E:checked a user interface element E that is checked (for instance a radio-button or checkbox)
E:not(s) an E element that does not match simple selector s
E ~ F an F element preceded by an E element

Un exemple réel:

a[href*="tumblr.com"]:before {
	content: "\2b8a";
}

Cette règle CSS a pour effet d’ajouter une icône (l’élément \2b8a qui correspond à un glyphe dans la fonte d’icônes Icomoon) devant chaque lien pointant vers Tumblr.

Z-index

Habituellement, les pages HTML sont dites «en 2D» car les éléments (texte, images etc.) s’arrangent sur la page pour ne pas se chevaucher. Par contre, en CSS 2.1, chaque élément est en 3D. En effet, en plus de leur axe vertical (axe Y) et horizontal (axe X), s’ajoute un axe de profondeur perpendiculaire aux autres, l’axe-Z. Cet axe se contrôle avec la propriété CSS Z-index.

Représentation 3D d'une page HTML

Le Z-index contrôle l’axe Z et donc l’ordre d’empilement des éléments qui se chevauchent sur une page. Elle permet de décider quel élément va au-dessus ou au-dessous des autres, selon la valeur Z-index attribuée à l’élément.

Les 4 règles du Z-index

  1. Les valeurs Z-index les plus élevées sont au premier plan, et les valeurs Z-index plus faibles sont en arrière-plan.

Exemple

  1. Le Z-index ne concerne que les éléments dont la position n’est pas «static» (= valeur de position par défaut). Il marche donc pour les éléments dont la position est soit relative, absolute ou fixed.

Exemple:

div#test1 {z-index: 10;} 
div#test2 {position: absolute; z-index: 2;}
  • L’élément qui sera au dessus sera div#test2, car il est positionné.

  • L’élément qui sera au dessous sera div#test1 (qui ne se place pas au-dessus malgré un Z-index de 10, car il n’est pas positionné).

  1. En l’absence de valeur Z-index, les éléments s’arrangent selon l’ordre d’apparition dans le code HTML (l’élément apparaissant en dernier apparaît au-dessus des autres).

Stacking child element

Ordre naturel de chevauchement

Sur une page HTML, l’ordre naturel (sans z-index) des éléments sur l’axe Z s’organise comme ceci (de l’élément le plus derrière à l’élément le plus devant):

  • Couche 1) Background + borders d’un élément source
  • Couche 2) Eléments blocs (sans position, ni float), par ordre d’apparition dans le code HTML
  • Couche 3) Eléments positionnés, par ordre d’apparition dans le code HTML

NOTES

  • Si plusieurs éléments de même nature (ex: 2 div) se situent sur la même couche, l’ordre d’apparition dans le code HTML fait foi.
  • Un élément non-positionné se situera toujours sous un élément positionné, même s’il apparaît plus tard dans l’ordre HTML.
  • Si un élément B est au-dessus d’un élément A, un enfant de l’élément A ne pourra jamais être au-dessus de l’élément B (peut importe la hauteur de son z-index).

Les 7 niveaux de chevauchement

Sur une page HTML, l’ordre naturel (avec z-index) des éléments sur l’axe Z s’organise comme ceci (de l’élément le plus derrière à l’élément le plus devant):

  • Couche 1) Background + borders d’un élément source
  • Couche 2) Z-Index négatifs
  • Couche 3) Eléments blocs (sans position, ni float)
  • Couche 4) Eléments floats (sans position)
  • Couche 5) Eléments «inline» (sans position)
  • Couche 6) Z-index: 0 + éléments positionnés
  • Couche 7) Z-index positifs + éléments positionnés

Stacking order

Comment ajouter un Z-index?

Initialement, le Z-index par défaut est à valeur «auto». Si on veut un ordre spécifique, il faut positionner l’élément et y appliquer la propriété Z-index.

Voici les valeurs qu’on peut lui appliquer:

1) La valeur auto (valeur de base)

Aucun changement d’ordre n’est appliqué, l’ordre initial HTML prime.

z-index: auto;

2) La valeur

Positive ou négative, cette valeur indique la position de l’élément sur l’axe Z.

z-index: 0;
z-index: 3;
z-index: 289;
z-index: -1; /* valeur négative afin de descendre la priorité au minimum */

3) Les valeurs globales

z-index: inherit; /*hérite sa propriété de l’élément qui lui est parent */
z-index: initial; /*ramène à la valeur par défaut */
z-index: unset; /*ramène à la valeur par défaut */

Bien utiliser le Z-index

Certaines personnes adorent utiliser des valeurs Z-index ridiculement hautes pour être certain que l’élément apparaîtra bien en premier. Mais la meilleure manière de faire est d’incrémenter la valeur de 100 en 100.

Exemple:

1) z-index: 0, 
2) z-index: 100
2 bis) z-index: 110
3) z-index: 200

Avec cette technique, on possède un espace libre au cas où on aurait besoin d’intercaler un élément entre 2 couches (2 bis). Ce champs d’action aurait été restreint si on avait mis les valeurs 1,2 et 3.

Le Z-index est supporté par tous les navigateurs. Cependant, seuls les navigateurs les plus à jour supportent une valeur Z-index négative.