≡ Éléments de javascript

Déplier lentement une zone en javascript

Smooth open area





On cherche à faire apparître du texte, par exemple après un click, lentement avec un effet de texte déplier. Cliquer …
Ligne 1
Ligne 2
Ligne 3
Ligne 4
Ligne 5
Ligne 6
Ligne 7
Ligne 9
Ligne 10
… pour dérouler …

Exclusivment en css avec transition

Les transitions css permettent de modifier des attributs lentement, et en interpolant les étapes intermédiaires. Dans l'exemple précédent, on créé en css deux classes:
.hide, .show {display:inline-block;
    vertical-align:top;
    overflow-y:hidden;
    border:solid blue;
    border-width:0 0 2px 2px}
.hide{height:0px;transition:height 3s}
.show{height:11em;transition:height 5s}
dans lesquelles:
  • le texte est caché/affiché grâce à sa hauteur: une hauteur de 0px cache le texte
  • la transition agit sur la hauteur, ici de 0px (caché) à 10em (complètement apparent)
  • On cache le texte hors cadre avec overflow-y:hidden
Il reste à piloter ceci avec javascript, pour répondre à un click par exemple, pour obtenir le code complet:
<button id="showButton">Show text</button>

<div id="text">
Ligne 1<br>
Ligne 2<br>
Ligne 3<br>
Ligne 4<br>
Ligne 5<br>
Ligne 6<br>
Ligne 7<br>
Ligne 9<br>
Ligne 10</div>

<style>
.hide, .show {
  display:inline-block;
  vertical-align:top;
  overflow-y:hidden;
  border:solid blue;
  border-width:0 0 2px 2px}
.hide{height:0px;transition:height 3s}
.show{height:10em;transition:height 5s}
</style>

<script>
document.getElementById("text").className="hide";
document.getElementById("showButton").addEventListener("click",
 function () {
  if (document.getElementById("text").className=="show") {
    document.getElementById("text").className="hide";
    document.getElementById("show").innerHTML="Show text";
    }
  else {
    document.getElementById("text").className="show";
    document.getElementById("show").innerHTML="hide text";
    }
});
</script>


Inconvénients:
  • on ne peut pas partir d'un état caché display:none qui n'a pas de hauteur définie et donc auquel on ne peut appliquer transition:height
  • il faut connaître d'avance la hauteur totale de l'élément à afficher, ce qui n'est pas le cas si on veut créer une fonction pour automatiser cet effet pour pouvoir l'appliquer à un élément quelconque.
    En effet, il faut à css des valeurs expliciteent définies afin de pouvoir interpolant les états intermédiaires, et par exemple l'attribut .show{height:auto;transition: height 5s} ne fonctionne pas.


Avec javascript

Cliquer …
Ligne 1
Ligne 2
Ligne 3
Ligne 4
Ligne 5
Ligne 6
Ligne 7
Ligne 9
Ligne 10
… pour dérouler …

Comme dit précédemment, avec css seul et ses transitions, on ne peut pas partir d'un élément caché en display:none et/ou arriver à un élément visible de hauteur inconnue à l'avance height:auto.
Une astuce, tout en javascript, est de montrer normalement l'élément display:none un instant (imperceptible pour l'utilisateur), de récupérer sa hauteur avec javascript via clientHeight, puis de lui affecter une hauteur nulle et enfin d(augment en boucle sa hauteur.
Voilà un exmemple de tel code qui donne le résultat précédent:

Cliquer ... 
<button id="showButton2">Show text</button>
<div id="text2">
Ligne 1<br>
Ligne 2<br>
Ligne 3<br>
Ligne 4<br>
Ligne 5<br>
Ligne 6<br>
Ligne 7<br>
Ligne 9<br>
Ligne 10</div>
... pour dérouler ... 


<style>
.hide, .show, .hide2 {
  display:inline-block;
  vertical-align:top;
  overflow-y:hidden;
  border:solid blue;
  border-width:0 0 2px 2px}
.hide2{height:0}
.displayOff{display:none}
</style>

<script>
document.getElementById("text2").className="displayOff";
document.getElementById("showButton2").addEventListener("click",
  function () {
    if (document.getElementById("text2").className=="show") {
	document.getElementById("text2").className="displayOff";
	document.getElementById("showButton2").innerHTML="Show text";
    }
    else {
	document.getElementById("text2").className="show";
	Ht=document.getElementById("text2").clientHeight;
	document.getElementById("text2").className="hide2";
	dt=20;
	cpt=1;
	for (i=1;i<Ht;i++)  {
	  setTimeout(function() {document.getElementById("text2").style.height=cpt+"px";cpt++;},i*dt);
	}
	setTimeout(function() {document.getElementById("text2").className="show";},Ht*dt);
	document.getElementById("showButton2").innerHTML="hide text";
    }
});
</script>


Voir aussi
LongPage: h2: 1 - h3: 2