Si vous suivez le compte @NoupeMag sur Twitter (ça marche aussi pour mon compte), vous avez certainement vu passer mon slideshow en CSS3 datant de l’an dernier.
Ce n’était pas ma première tentative de slideshow comme le présentent ces premier et second travaux datant de mai 2010.

Ce tutoriel ne s’adresse pas aux débutants, il vous faudra un minimum de connaissances techniques pour vous y retrouver dans les tronçons de code qui vont suivre. Cependant, le code commenté reste – je l’espère – accessible.

Avant propos

La page de démonstration du slideshow full CSS3 vous propose des fichiers sources en téléchargement, profitez-en, notamment si vous souhaitez récupérer les images.

Les codes CSS fournis ici sont légèrement différents de ceux fournis dans l’archive zippée téléchargeable. En effet, la rédaction du tutoriel que vous allez lire m’a permis d’alléger, corriger et améliorer le code disponible en téléchargement. Il fera l’objet d’une refonte prochaine.

Les codes CSS3 présents sur ce tutoriel ne tiennent pas compte des préfixes parfois nécessaires (-webkit-, -moz-, -ms-, -o-) pour une question de gain de place dans le code. Ne les oubliez pas.

Enfin si les bases des langages HTML et CSS vous font défaut, n’hésitez pas à jeter un œil à cette formation HTML et CSS.

Les défauts des versions précédentes

Comme les expérimentations foireuses sont là pour faire ressortir les limites d’une technique, voyons ce qui nous manquait dans les versions précédentes (gardez-les sous les yeux pour tester, c’est mieux).
Sur la version contrôlable (la première) :

  • Un saut de page est visible au clic sur les flèches ;
  • Nous sommes obligés de multiplier les éléments (div pour les conteneurs, a pour les flèches) ;
  • il faut dupliquer des règles CSS à chaque image ajoutée.

Sur la version automatique (la seconde) :

  • Il n’y a pas de commandes (soit…)
  • Aucune possibilité de stopper l’animation
  • il faut dupliquer des règles CSS à chaque image ajoutée.

Certains de ces problèmes ne sont pas résolubles, j’ai décidé de me concentrer sur la fusion des fonctionnalités et sur la correction de certains points :

  • Fusionner le slideshow automatique et contrôlable
  • Ajouter une commande de stop et lecture de l’animation
  • Limiter la multiplication des éléments
  • Virer le saut au clic (grâce à l’astuce CSS de Vincent De Oliveira)

Les autres problèmes persisteront, vous le verrez.

À noter que ce slideshow reste expérimental même si compatible avec les derniers navigateurs du marché.

Poser les fondations

Voici du code HTML (HTML5 en l’occurrence) que j’espère suffisamment parlant.

<section id="slideshow">
		
	<div class="container">
		<div class="c_slider"></div>
		<div class="slider">
			<figure>
				<img src="img/dummy-640x310-1.jpg" alt="" width="640" height="310" />
				<figcaption>The mirror of soul</figcaption>

			</figure><!--
			--><figure>
				<img src="img/dummy-640x310-2.jpg" alt="" width="640" height="310" />
				<figcaption>Let's cross that bridge when we come to it</figcaption>
			</figure><!--
			--><figure>
				<img src="img/dummy-640x310-3.jpg" alt="" width="640" height="310" />
				<figcaption>Sushi<em>(do)</em> time</figcaption>

			</figure><!--
			--><figure>
				<img src="img/dummy-640x310-4.jpg" alt="" width="640" height="310" />
				<figcaption>Waking Life</figcaption>
			</figure>
		</div>
	</div>
		
	<span id="timeline"></span>
</section>

Ce code HTML pourrait être simplifié en prenant le risque de complexifier la CSS, mais cette dernière va déjà l’être suffisamment…
Pour faire simple nous avons une section pour le slideshow qui réunie le conteneur des images (.container), la partie qui glisse (.slider), les différentes images légendées (sous forme de figure > figcaption) et la petite barre de défilement du temps (#timeline).

Pour ceux qui s’interrogent sur la présence de commentaires HTML, je vous invite à lire cet autre article du blog : Display inline-block, une valeur trop peu utilisée.

Je n’ai mis aucun élément de commande pour le moment, nous verrons cela plus tard.

Voici le code CSS servant principalement à positionner, dimensionner et décorer les différents blocs, que je ne vais pas expliquer dans la mesure où ce n’est pas le cœur de l’article, mais il est un minimum commenté 😉

#slideshow {
	position: relative;
	width: 640px;
	height: 310px;
	padding: 15px;
	margin: 0 auto 2em;
	border: 1px solid #ddd;
	background: #FFF;
	/* CSS3 effects */
	background: linear-gradient(#FFF, #FFF 20%, #EEE 80%, #DDD);
	border-radius: 2px 2px 2px 2px;
	box-shadow: 0 0 3px rgba(0,0,0, 0.2);
}
 
/* avanced box-shadow
 * tutorial @
 * https://www.creativejuiz.fr/blog/les-tutoriels/ombre-avancees-avec-css3-et-box-shadow 
*/
#slideshow:before,
#slideshow:after {
	position: absolute;
	bottom:16px;
	z-index: -10;
	width: 50%;
	height: 20px;
	content: " ";
	background: rgba(0,0,0,0.1);
	border-radius: 50%;
	box-shadow: 0 0 3px rgba(0,0,0, 0.4), 0 20px 10px rgba(0,0,0, 0.7);
}
#slideshow:before {
	left:0;
	transform: rotate(-4deg);
}
#slideshow:after {
	right:0;
	transform: rotate(4deg);
}

Avec ceci nous avons le support graphique des images. C’est un peu tout cassé, mais vous pouvez voir comment réaliser simplement un élément qui semble assez complexe, notamment au niveau des ombres et dégradés.
Gérons le débordement et l’alignement de tout ce contenu.

/* gestion des dimensions et débordement du conteneur */
#slideshow .container {
	position:relative;
	width: 640px;
	height: 310px;
	overflow: hidden;
}
	
/* on prévoit un petit espace gris pour la timeline */
#slideshow .container:after {
	position:absolute;
	bottom: 0; left:0;
	content: " ";
	width: 100%;
	height: 1px;
	background: #999;
}
/* 
   le conteneur des slides
   en largeur il fait 100% x le nombre de slides
*/
#slideshow .slider {
	position: absolute;
	left:0; top:0;
	width: 400%;
	height: 310px;
}

/* annulation des marges sur figure */
#slideshow figure {
	position:relative;
	display:inline-block;
	padding:0; margin:0;
}
/* petit effet de vignette sur les images */
#slideshow figure:after {
	position: absolute;
	display:block;
	content: " ";
	top:0; left:0;
	width: 100%; height: 100%;
	box-shadow: 0 0 65px rgba(0,0,0, 0.5) inset;
}

Nous voici sur une mise en forme plus propre, les éléments figure sont placés sur une seule et même ligne et le débordement est caché.
Il ne nous reste plus qu’à présenter un peu mieux notre légende qui est actuellement planquée :

/* styles de nos légendes */
#slideshow figcaption {
	position:absolute;
	left:0; right:0; bottom: 5px;
	padding: 20px;
	margin:0;
	border-top: 1px solid rgb(225,225,225);
	text-align:center;
	letter-spacing: 0.05em;
	word-spacing: 0.05em;
	font-family: Georgia, Times, serif;
	background: #fff;
	background: rgba(255,255,255,0.7);
	color: #555;
	text-shadow: -1px -1px 0 rgba(255,255,255,0.3);
}

Et voilà qui est mieux.

Nous allons maintenant nous occuper de la phase automatique du slideshow.
Nous verrons dans une troisième partie comment gérer des actions pour contrôler notre slideshow.

Animer notre contenu : phase automatique

Cette phase va être quelque peu répétitive puisque nous allons devoir créer un certain nombre d’animations grâce à la fonction CSS @keyframes. Pour en savoir plus sur les animations, je vous invite à lire la partie « animation » de cet article sur le timing sur Alsacréations.

Pour obtenir une animation cohérente tout le long d’un cycle, vous devez vous poser la question suivante :
Combien de temps est nécessaire pour la compréhension de chaque slide ?

Bien entendu, la réponse va dépendre du contenu, mais imaginons que nous ayons 4 étapes, pas beaucoup de texte, 6 ou 7 secondes peuvent sembler suffisantes pour chaque étape. Il reste alors à estimer la durée d’une transition d’une étape à l’autre, 1 ou 2 secondes. Avec 8 secondes multipliées par 4, ça nous fait 32 secondes d’animation pour boucler un cycle complet.

Animation du conteneur

Commençons par animer le bloc qui contient nos images et légendes en le faisant glisser. Pour cela, créons notre animation :

/* fonction d'animation, n'oubliez pas de prefixer ! */
@keyframes slider {
	0%, 20%, 100%	{ left: 0 }
	25%, 45%		{ left: -100% }
	50%, 70%		{ left: -200% }
	75%, 95%		{ left: -300% }
}

N’oubliez pas de préfixer également la règle @keyframes (oui ! Il faudra s’embêter à dupliquer le code de l’animation) de la sorte : @-webkit-keyframes slider {[…]} @-moz-keyframes slider {[…]}, etc.

Chaque étape est exprimée en pourcentage, aussi 50% signifie que nous en sommes à la 16ième seconde de notre animation.
Si plusieurs étapes ont la même valeur d’une propriété, ou si vous souhaitez créer un arrêt, il suffit de mettre la valeur sur la même ligne séparer par une virgule.
Par exemple, sur la première étape, nous avons 0, 20 et 100% qui cohabitent. Cela sous entend que de 0 à 20%, la valeur de left est de 0, nous créons donc un arrêt. Cela signifie aussi que de 95 à 100%, la valeur de left passe de -300% à 0. C’est un moyen facile de retourner à la valeur initiale pour créer une boucle.

Nous avons créer l’animation, il faut maintenant l’attribuer à notre élément de cette manière :

/* complétez le sélecteur : */
#slideshow .slider {
	/* ... avec la propriété animation */
	animation: slider 32s infinite;
}

Cette syntaxe de la propriété animation est le raccourci de animation-name, animation-duration, animation-iteration-count, dans cet ordre précisément ici.

Animation de la ligne de temps

Notre petite ligne d’un pixel de hauteur servant de ligne de temps va être animée sur le même principe.
Mais avant cela, donnons-lui quelques styles de couleur.

#timeline {
	position: absolute;
	background: #999;
	bottom: 15px;
	left: 15px;
	height: 1px;
	background: rgb(214,98,13);
	background: rgba(214,98,13,.8);
	width: 0;
	/* fonction d'animation */
	animation: timeliner 32s infinite;
}

Il est ainsi placé précisément en tenant compte des marges autour des photos, et nous lui attribuons tout de suite une animation nommée timeliner qu’il nous faut déclarer comme ceci :

@keyframes timeliner {
	0%, 25%, 50%, 75%, 100%	{ width: 0;		}
	20%, 45%, 70%, 90%		{ width: 640px;	}
}

Ici nous savons que la ligne doit être à son maximum à quatre reprise (avant chaque changement de slide). Il y a donc 4 étapes à 640px (largeur max), et 4 (si on confond 0 et 100) à 0.

Animation de la légende

Même procédé, nous allons faire monter et descendre notre légende à chaque slide.

@keyframes figcaptionner {
	0%, 25%, 50%, 75%, 100%						{ bottom: -55px;	}
	5%, 20%, 30%, 45%, 55%, 70%, 80%, 95%		{ bottom: 5px;		}
}

Puis nous accrochons cette animation à notre élément :

/* ajouter à l'élément : */
#slideshow figcaption {
	/* ... la propriété animation */
	animation: figcaptionner 32s infinite;
}

Je ne sais pas si vous avez vu, mais le vignettage des slides est animé. Comme vous avez compris le principe, je vous laisse vous amuser à trouver le code 😉

Nous avons désormais un slideshow qui fonctionne en mode automatique.
Maintenant, voyons comment procéder si l’on souhaite ajouter des boutons stop/marche, et suivant/précédent, ou « aller à la slide 3 », par exemple.

Contrôler notre contenu : phase manuelle

Lorsque l’on conçoit un slideshow, il est très recommandé de permettre à l’utilisateur de stopper l’animation, soit parce que ça le stresse, soit parce qu’il veut contempler une des images, soit… bref, voyons ce qu’on peut faire !

Pour rappel, nous n’avons encore aucun élément HTML pour ces contrôles, nous allons donc les rajouter progressivement.
Ces éléments de contrôles (des liens) vont cibler des ancres placés « à côté » de notre slideshow, en tant que frères indirects.

Juste avant notre élément #slideshow, placez donc ces éléments span :

<span id="sl_play" class="sl_command"></span>
<span id="sl_pause" class="sl_command"></span>
 
<span id="sl_i1" class="sl_command sl_i"></span>
<span id="sl_i2" class="sl_command sl_i"></span>
<span id="sl_i3" class="sl_command sl_i"></span>
<span id="sl_i4" class="sl_command sl_i"></span>

Ceux-ci ont des classes communes (parfois) qui nous permettrons des actions groupées par la suite.
Vous comprendrez leur utilité par la suite, ne vous faites pas de souci.

Bouton jouer et arrêter

Les boutons play et pause peuvent être ajoutés dans la section #slideshow, juste avant notre .container.

Il n’y a aucune obligation à les placer précisément ici, il est généralement conseillé de conserver ordre d’apparition dans le DOM et ordre d’apparition à la lecture de la page. Là nous allons les placer au milieu (verticalement) du slideshow :

<a class="play_commands pause" href="#sl_pause" title="Maintain paused">Pause</a>
<a class="play_commands play" href="#sl_play" title="Play the animation">Play</a>

Ces éléments peuvent prendre leur apparence avec quelques lignes de code uniquement, et sont par défaut cachés : ils n’apparaissent qu’à certains moments bien précis que nous définirons par la suite.

.play_commands {
	/* positionnement en haut à droite */ 
	position: absolute;
	top: 25px; right: 25px;
	z-index: 10;
	/* dimensionnement des icônes */
	width: 22px;
	height: 22px;
	text-indent: -9999px;
	border:0 none;
	/* placez l'opacité à 1 si vous souhaitez voir les commandes */
	opacity: 0;
	/* préparation de transition sur opacicty et right */
	transition: opacity 1s, right 1s;
}
/* on décale play légèrement sur la gauche */
.play { right: 55px; cursor: default; }
 
/* création de l'icône pause avec 2 pseudos éléments */
.pause:after,
.pause:before {
	position: absolute;
	display: block;
	content: " ";
	top:0;
	width:38%;
	height: 22px;
	background: #fff;
	background: rgba(255,255,255,0.5);
}
.pause:after { right:0; }
.pause:before {	left:0; }
 
/* création de l'icône play avec des bordures */
.play {
	width: 1px; 
	height: 1px; 
	/* les transparentes forment la flèche */
	border-top: 10px solid transparent;
	border-bottom: 10px solid transparent;
	border-left: 20px solid #fff; 
	border-left: 20px solid rgba(255,255,255,0.5); 
	/* renseignez 1 pour voir l'icône de suite */
	opacity: 0;
}
 
/* apparition du bouton pause au survole */
/* apparition des boutons au focus */
#slideshow:hover .pause,
.play_commands:focus {
	opacity: 1;
	outline: none;
}

Voilà, toutes ces lignes pour mettre en place nos deux liens. Ceux qui trouveront plus pertinent de charger des images ou un sprite, je ne leur en voudrais pas.
C’est bien, c’est beau, mais pas fonctionnel.

Nous allons maintenant utiliser la pseudo classe target pour agir sur notre animation en fonction du bouton que nous aurons cliqué.
Lorsque pause est cliqué, nous ciblons l’élément #sl_pause, lorsque lecture est cliqué, c’est #sl_play qui est ciblé.
Dans notre scénario, nous n’afficherons que le bouton utile : pause quand la lecture est effective, play lorsque la pause est en place.

/* stopper les animation */
.sl_command:target ~ #slideshow .slider,
.sl_command:target ~ #slideshow figcaption,
.sl_command:target ~ #slideshow #timeline,
.sl_command:target ~ #slideshow .dots_commands li:first-child a:after {
	animation-play-state: paused;
}
 
/* redémarrer les animations */
#sl_play:target ~ #slideshow .slider,
#sl_play:target ~ #slideshow figcaption,
#sl_play:target ~ #slideshow #timeline,
#sl_play:target ~ #slideshow .dots_commands li:first-child a:after {
	animation-play-state: running;
}
 
/* switch entre les boutons */
.sl_command:target ~ #slideshow .pause 		{ opacity:0; }
#sl_play:target ~ #slideshow:hover .pause,
#sl_play:target ~ #slideshow .pause:focus 	{ opacity:1; }
.sl_command:target ~ #slideshow .play 		{ opacity:1; right: 25px; cursor: pointer; }
#sl_play:target ~ #slideshow .play 			{ opacity:0; right: 55px; cursor: default; }

Le premier bloc permet de stopper les animations grâce à la propriété animation-play-state. Cette propriété placée à sa valeur paused permet de figer l’animation.
Les sélecteurs sont assez spéciaux : .sl_command:target ~ #slideshow .slider permet de cibler « L’élément .slider fils de #slideshow lorsque ce dernier est indirectement frère de .sl_command, uniquement lorsque ce dernier est ciblé. ». Autrement dit : si .sl_command est ciblé, alors on va chercher le frère #slideshow puis son fils .slider pour lui appliquer un stop.
On procède de la même manière pour les autres éléments (figcaption, #timeline et .dots_commands que nous verrons plus tard dans le bonux) qui ont une animation en route également.
Pour en savoir plus sur les sélecteurs d’adjacence indirecte, lisez cet autre article du blog : Sélecteur d’adjacence indirecte en CSS3.

Le dernier bloc de code permet d’afficher les boutons en fonction de situation précise, je vous laisse essayer de décortiquer leur signification.

Bonux : Les flèches « suivant » et « précédent »

Il va nous falloir une paire de liens par étape de notre slideshow en gardant en tête que la flèche de gauche de notre première slide nous permet d’aller à la dernière, la flèche de droite de notre dernière slide nous permet d’aller à la première (vous me suivez ?). Lisez les title pour comprendre l’utilité de chaque flèche. Vous pouvez placer ces liens après nos deux liens pause et lecture.

<a class="commands prev commands1" href="#sl_i4" title="Aller à la dernière slide">&lt;</a>
<a class="commands next commands1" href="#sl_i2" title="Aller à la 2ème slide">&gt;</a>
<a class="commands prev commands2" href="#sl_i1" title="Aller à la 1ère slide">&lt;</a>
<a class="commands next commands2" href="#sl_i3" title="Aller à la 3ème slide">&gt;</a>
<a class="commands prev commands3" href="#sl_i2" title="Aller à la 2ème slide">&lt;</a>
<a class="commands next commands3" href="#sl_i4" title="Aller à la 4ème slide">&gt;</a>
<a class="commands prev commands4" href="#sl_i3" title="Aller à la 3ème slide">&lt;</a>
<a class="commands next commands4" href="#sl_i1" title="Aller à la 1ère slide">&gt;</a>

C’est là que la pertinence du markup en prend un coup. Pour des raisons d’accessibilité (clavier ici) ces liens ne sont peut-être pas des plus utiles et pratiques à utiliser. Est peut-être à envisager l’ajout de l’attribut tabindex="-1" pour empêcher le focus sur ces éléments. En effet, nous utiliserons un second système de navigation juste après, qui lui est peut-être plus pertinent.
Donnons quelques styles à nos boutons et cachons ceux qui ne sont pas utiles.

#slideshow .commands {
	position: absolute;
	top: 45%;
	padding: 5px 13px;
	border-bottom:0;
	font-size: 1.3em;
	color: #aaa;
	text-decoration:none;
	background-color: #eee;
	background-image: linear-gradient(#fff,#ddd);
	text-shadow: 0 0 1px #aaa;
	border-radius: 50%;
	box-shadow: 1px 1px 2px rgba(0,0,0,0.2);
}
 
#slideshow .prev { left: -48px; }
#slideshow .next { right: -48px; }
 
#slideshow .commands { display:none; }
#slideshow .commands1 {	display: block; }

Très bien, nous avons des flèches… mais que va-t-on bien pouvoir bouger avec ?
Sur le même principe que précédemment, nous ciblons l’un des span abandonnés en début de code. Si vous cliquez sur une des flèches, pour le moment ça ne fait que stopper l’animation (oui, tous les span sont porteurs de la classe .sl_command, rappelez-vous, en en ciblant un, les animations s’arrête).
En fonction de l’élément ciblé, on pourrait stopper l’animation et changer les valeurs de left pour le slider, de width pour la timeline, et de bottom pour la légende. Ça serait cool hein ?
Oui mais non, parce qu’en fait ça ne fonctionne pas : les keyframes sont « prioritaires ».

C’est ce qui nous oblige à compléter notre code HTML légèrement avec ce petit morceau :

<div class="c_slider"></div>

Il est déjà présent dans le code fourni initialement (premier bloc de cet article).

Cet élément nous permet d’appliquer les images en image de fond. Ces mêmes images que nous avons déjà chargé dans le HTML, nous allons les appliquer en background CSS.
C’est en faisant bouger ce nouvel élément que nous allons donner l’illusion d’un slideshow classique. Je dis bien illusion, car vous aurez compris qu’ici on se restreint à l’idée d’un vrai diaporama, avec des images, et non du contenu textuel qu’il serait difficile de « dupliquer ».

#slideshow .c_slider {
	position: absolute;
	left:0; top:0;
	width: 400%;
	height: 310px;
	/* multiple background */
	background: url(img/dummy-640x310-1.jpg) 0 0 no-repeat,
	            url(img/dummy-640x310-2.jpg) 640px 0 no-repeat,
	            url(img/dummy-640x310-3.jpg) 1280px 0 no-repeat,
	            url(img/dummy-640x310-4.jpg) 1920px 0 no-repeat;
	transition: background 1s;
}

Cette division fournie de quelques images est cachée par la partie principale du diaporama pour le moment. Lorsque nous ciblerons le contenu avec l’une de nos flèches « suivant » ou « précédent », nous cacherons ce diaporama automatique (qui se sera stoppé) pour découvrir nos slides contrôlables qui bougeront en fonction de l’élément ciblé.
Vous n’allez pas m’aimer… :

/* on cache le slider */
.sl_i:target ~ #slideshow .slider									{ visibility: hidden }
/* on planque la 1ère pastille (cf. bonux suivant) */
.sl_i:target ~ #slideshow .dots_commands li:first-child a:after		{ display:none; }
/* pour afficher la 2ème pastille (cf. bonux suivant) */
.sl_i:target ~ #slideshow .dots_commands li:first-child a:before	{ display:block; }
 
/* lorsque on cible le premier slider */
/* on cache tous les "précédent" et "suivant" */
#sl_i1:target ~ #slideshow .commands								{ display: none; }
/* on affiche seulement deux flèches */
#sl_i1:target ~ #slideshow .commands1								{ display: block; }
/* correspond au décalage des images */
#sl_i1:target ~ #slideshow .c_slider								{ background-position: 0 0, 640px 0, 1280px 0, 1920px 0; }
/* on place la pastille tout à gauche */
#sl_i1:target ~ #slideshow .dots_commands li:first-child a:before	{ left:0; }
 
/* même procédé lorsqu'on cible le second slide */
#sl_i2:target ~ #slideshow .commands								{ display: none; }
#sl_i2:target ~ #slideshow .commands2								{ display: block; }
#sl_i2:target ~ #slideshow .c_slider								{ background-position: -640px 0, 0 0, 640px 0, 1280px 0; }
#sl_i2:target ~ #slideshow .dots_commands li:first-child a:before	{ left:18px; }
 
/* puis le 3ème */
#sl_i3:target ~ #slideshow .commands								{ display: none; }
#sl_i3:target ~ #slideshow .commands3								{ display: block; }
#sl_i3:target ~ #slideshow .c_slider								{ background-position: -1280px 0, -640px 0, 0 0, 640px 0; }
#sl_i3:target ~ #slideshow .dots_commands li:first-child a:before	{ left:36px; }
 
/* et enfin le 4ème */
#sl_i4:target ~ #slideshow .commands								{ display: none; }
#sl_i4:target ~ #slideshow .commands4								{ display: block; }
#sl_i4:target ~ #slideshow .c_slider								{ background-position: -1920px 0, -1280px 0, -640px 0, 0 0; }
#sl_i4:target ~ #slideshow .dots_commands li:first-child a:before	{ left:54px; }

À chaque étape nous déplaçons les images, cachons tous les liens « précédent » et « suivant » sauf ceux dont on peut avoir besoin, et on déplace la petite pastille de la navigation secondaire (voir bonus qui suit).

Bonux : « pagination » pour sauter vers une slide

Vous avez certaine souvent vu ces petits points au pied d’un slideshow qui servent un peu de pagination et qui, parfois, permettent de savoir précisément où on se trouve dans le déroulement des slides.
Nous allons en créer une. Pour commencer, ajoutons ce code HTML juste après l’élément timeline

<ul class="dots_commands"><!--
	--><li><a title="Afficher la slide 1" href="#sl_i1">Slide 1</a></li><!--
	--><li><a title="Afficher la slide 2" href="#sl_i2">Slide 2</a></li><!--
	--><li><a title="Afficher la slide 3" href="#sl_i3">Slide 3</a></li><!--
	--><li><a title="Afficher la slide 4" href="#sl_i4">Slide 4</a></li>
</ul>

Puis, ces quelques lignes de CSS pour donner un style bien propre à nos petits points.
N’hésitez pas à agrandir les dimensions si ça vous semble trop petit.

.dots_commands  {
	padding:0;
	margin:32px 0 0;
	text-align: center;
}
.dots_commands li {
	display: inline;
	padding:0; margin:0;
}
.dots_commands a {
	position: relative;
	display: inline-block;
	height:8px; width: 8px;
	margin: 0 5px;
	text-indent: -9999px;
	background: #fff;
 
	border-radius: 50%;
	box-shadow: 0 1px 2px rgba(0,0,0,0.55) inset;

}
/* quelques styles au focus */
.dots_commands a:focus { 
	outline: none;
	background: orange;
}
.dots_commands li:first-child a { z-index: 25; }

Rien de sorcier ici.
On s’assure simplement en dernière ligne que le premier élément ait un z-index supérieur aux autres. Nous allons nous en servir pour l’animation qui suit.

Nous allons créer un petit disque par dessus ces puces pour représenter le slide visible par un point d’une couleur différente. Pour ce faire nous utilisons les pseudo-éléments.

/* on style after et before, on utilisera les deux */
.dots_commands li:first-child a:after,
.dots_commands li:first-child a:before {
	position: absolute;
	top: 0; left: 0;
	content: " ";
	width: 8px; height: 8px;
	background: #bd9b83;
	z-index:20;

	border-radius: 50%;
	box-shadow: 0 1px 2px rgba(0,0,0,0.55) inset;
}
/* on anime "after" */
.dots_commands li:first-child a:after {
	animation: dotser 32s infinite;
}
/* on cache "before", on l'utilise uniquement au clic (cf. bonux précédent) */
.dots_commands li:first-child a:before { display:none; }
 
/* c'est parti pour l'animation ! */
@keyframes dotser {
	0%, 100% 	{ opacity: 1; left: 0; 		}
 		
	20%			{ opacity: 1; left: 0;		}
	22%			{ opacity: 0; left: 0;		}
	23%			{ opacity: 0; left: 18px;	}
	25%			{ opacity: 1; left: 18px;	}
 		
	45%			{ opacity: 1; left: 18px;	}
	47%			{ opacity: 0; left: 18px;	}
	48%			{ opacity: 0; left: 36px;	}
	50%			{ opacity: 1; left: 36px;	}
 		
	70%			{ opacity: 1; left: 36px;	}
	72%			{ opacity: 0; left: 36px;	}
	73%			{ opacity: 0; left: 54px;	}
	75%			{ opacity: 1; left: 54px;	}
 		
	95%			{ opacity: 1; left: 54px;	}
	97%			{ opacity: 0; left: 54px;	}
	98%			{ opacity: 0; left: 0;	}
}

Comme nous l’avons prévu dans notre bonus précédent, nous n’avons rien besoin de gérer en plus. Ces liens ciblent les mêmes éléments que nos flèches latérales et ont donc le même effet. (stop de l’animation et slide contrôlable avec tous les effets qui y sont liés)
L’animation peut sembler compliquée, mais c’est la logique de « disparition, déplacement, apparition » multiplié par 4 (4 étapes). Pour information, jusqu’à très récemment, Google Chrome avait du mal avec les animations sur before ou after. Je ne sais pas si ça a changé, il me semble.

Et on en restera là !

Démonstration

Pour être sûr que tout fonctionne, j’ai effectué un test en suivant ce tutoriel et en préfixant pour Firefox uniquement, voici le résultat : Slideshow Full CSS3.

Lors de la rédaction de ce tutoriel certains éléments comme les infobulles ou le vignettage animés ont été volontairement omis pour alléger le contenu. Si certaines portions de ce tutoriel restent pour vous un mystère à cause d’un manque d’explications, l’espace de commentaires est là pour vous 🙂

Analyse personnelle

Ce qui est bloquant est gourmand en lignes de code ici, c’est la volonté de vouloir fusionner système automatique et système contrôlable au clavier, souris ou même touché.

Ce slideshow date de novembre 2011, les techniques se sont multipliées, il existe d’autres solutions full CSS3 passant par l’utilisation détournée des éléments label et input de type radio. En contrôlant la valeur de la coche avec la pseudo-classe checked il est possible d’agir sur les éléments, de la même manière que nous le faisons ici avec la pseudo-classe target.

Je vous invite à regarder ce qui peut se faire ailleurs, comme par exemple sur ce Slideshow Full CSS3 Responsive.

L’espace de commentaires est à vous !