Niveau : Expert

Créer un volet coulissant en CSS3 avec :target et transition

Tutoriel par (WebDesigner grapilleur de Kiwiz, Strasbourg)
Créé le , mis à jour le (97940 lectures)
Tags : css, css3, transition

Alors que CSS3 continue son chemin dans les validations, les réécritures et la prise en charge par les navigateurs, il y a des choses qui commencent à être plutôt bien implémentées par la plupart de ces derniers.

La pseudo classe :target et la propriété transition - que nous avons déjà mis à l'épreuve dans ce long tutoriel sur la création d'un slideshow en CSS3 - vont être nos armes pour ce tutoriel.

Qu'allons-nous produire ?

Le but de ce tutoriel est de créer un volet caché dans un coin de la page que nous allons pouvoir révéler en cliquant sur un lien.
Dans un premier temps nous allons juste nous charger de révéler le volet, nous verrons comment faire pour replacer notre volet à son état initial dans un second temps.

 la démonstration

Structure de base

Il va nous falloir une structure HTML (vous vous en doutiez, j'imagine).
Pour se faire nous allons composer une base HTML que nous complèterons plus tard.

<div id="volet">
	<p>Lorem Elsass ipsum réchime amet sed bissame so libero. DNA, leo Richard Schirmeck tellus</p>
	<p>Wurscht elementum semper tellus s'guelt Pfourtz !</p>
	
	<a href="#volet" class="ouvrir">Ouvrir !</a>
</div>

Une division, des paragraphes pour le contenu, et un lien pour l'action, nous n'aurons besoin de rien de plus ici.

Styles de base

Les styles proposés ici ont été mis à jour récemment pour correspondre au support navigateur. Certains préfixes sont à rajouter si vous souhaitez améliorer le support de navigateurs plus anciens.

Passons à notre code CSS.
Nous allons fixer une largeur à notre volet (et quelques couleurs) et à notre lien.

#volet {
	width: 250px;
	padding: 10px;
	background: #6B9A49; color: #fff;	
}
#volet a.ouvrir {
	padding: 10px 25px;
	background: #555;
	color: #fff;
	text-decoration: none;
}

Puis nous décalons le volet en dehors de l'écran en ne faisant ressortir que notre lien.

#volet {
	position: relative;
	left: -270px; top: 55px;
}
#volet a.ouvrir {
	position: absolute;
	right: -88px;
	top: 150px;

	/* quelques styles CSS3 */
	-ms-transform: rotate(270deg);
	-moz-transform: rotate(270deg);
	-webkit-transform: rotate(270deg);
	transform: rotate(270deg);

	border-radius: 0 0 8px 8px;
}

Ensuite il nous faut préparer la transition sur le volet.


#volet {
	-webkit-transition: all .5s ease-in;
	transition: all .5s ease-in;
}

Et enfin déterminer à quel moment nous allons faire sortir le volet.

#volet:target {
	left: 0;
}

Ici, le lien cible l'élément porteur d'id "volet", lorsque cet élément est ciblé (état :target) nous attribuons zéro à sa propriété left. Une transition va s'effectuer pour faire passer cette valeur de -300 à 0 pixel en 0,5 seconde.

Si nous en restons là l'utilisateur se retrouve avec un volet ouvert sans avoir la possibilité de le fermer.
Passons à la seconde action.

 la démonstration

Un peu plus de HTML

Concrètement, nous avons une action de plus à effectuer, il nous faut donc un lien de plus, plaçons-le après le lien ouvrir
Ce lien aura besoin lui aussi de cibler le volet pour lui dire de se cacher...
Ah ! Mais ça ne va pas être possible puisque il existe déjà une réaction lorsque #volet est ciblé.

Nous allons donc ajouter un conteneur à notre volet pour pouvoir le cibler et agir sur ses enfants. Procédons, vous comprendrez rapidement.

<div id="volet_clos">
	<div id="volet">
		<p>Lorem Elsass ipsum réchime amet sed bissame so libero. DNA, leo Richard Schirmeck tellus</p>
		<p>Wurscht elementum semper tellus s'guelt Pfourtz !</p>
	
		<a href="#volet" class="ouvrir">Ouvrir !</a>
        <a href="#volet_clos" class="fermer">fermer !</a>
	</div>
</div>

Avec cette forme je peux cibler #volet_clos et faire quelque chose dans le genre :

#volet_clos:target #volet {
	/* retourne à ta place */
}

C'est ce que nous ferons après. Pour le moment considérons nos nouveaux éléments, et voyons quels styles leur appliquer.

Un peu plus de CSS

Notre nouveau conteneur n'a une présence que fonctionnelle. Nous n'avons pas besoin de le styler.

Notre nouveau lien va avoir les mêmes styles que notre lien déjà en place. Il suffit dans ce cas de doubler le sélecteur :

#volet a.ouvrir,
#volet a.fermer {
	/* les styles donnés précédemment */
}

Sauf que, par défaut notre lien .fermer doit être caché, rajoutons :

#volet a.fermer {
	display: none;
}

Maintenant nous devons faire notre décalage inverse du volet. Pour se faire nous effectuerons notre déplacement lorsque l'élément ciblé par notre lien "Fermer" le sera (ciblé).

#volet_clos:target #volet {
	left: -270px;
}

Et voilà ! C'est prêt !
Sauf que, si vous testez en l'état, nous en sommes toujours au même stade, puisque notre lien "Fermer" est caché.
Pour le faire apparaitre, nous devons cacher notre lien "Ouvrir" et afficher notre lien "Fermer" lorsque le volet s'ouvre, donc lorsque #volet est ciblé.

#volet:target a.ouvrir {
	display: none;
}
#volet:target a.fermer {
	display: block;
}

Cette fois c'est la fin !
Lorsque nous cliquons sur Ouvrir, l'élément #volet est ciblé, il se déploie et le lien "Fermer" prend la place du lien "Ouvrir".
Lorsque nous cliquons sur Fermer, l'élément #volet_clos est ciblé, son fils #volet se planque et le lien "Ouvrir" prend la place du lien "Fermer".

Limites connues

Et qu'ça saute !

Cette technique utilise le principe de l'ancre, qui comme nous la connaissons, permet de faire un saut vers l'élément ciblé.
Dans le cas où votre élément est positionné en absolute ou relative, la position de l'élément est déterminée, et le saut aura lieu si votre page est suffisamment haute. Cet effet peut être indésirable.

En plaçant l'élément parent en position fixed, nous pouvons résoudre ce problème de saut puisque l'emplacement absolu de l'élément dépend de votre position dans la page.

 petit aperçu

Il existe également une autre solution proposée par Vincent De Oliveira sur CSS3 Create.

Lecteur d'écran

Le contenu sorti de la zone visible est tout de même lu par les lecteurs d'écran (car déplacé et non caché grâce à display: none). Ce n'est pas réellement problématique ici, sauf lorsque le lecteur va lire les liens "Ouvrir" et "Fermer". Ces liens n'ont pas d'utilité si le contenu du volet a déjà été lu. Nous pouvons donc désactiver leur présence en utilisant l'attribut ARIA aria-hidden directement sur nos liens.

<a href="#volet" class="ouvrir" aria-hidden="true">Ouvrir !</a>
<a href="#volet_clos" class="fermer" aria-hidden="true">fermer !</a>

Cet attribut n'est pas compris de manière uniforme.

Amusez-vous bien ;)