jQuery : script toggle pour afficher et cacher de multiples blocs HTML

jquery

J’ai écrit il y a quelques temps un script jQuery utilisant la fonction toggle pour afficher/cacher un seul bloc HTML mais pas mal de gens m’ont demandé comment faire pour afficher plusieurs blocs HTML.

Voici comment s’y prendre, en utilisant les fonctions jQuery .slideup(), .slidedown() et .closest().

Démo


Article A

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam

Article B

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam

Article C
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam

Le script

1. Ajoutez jQuery dans l’entête de votre page (head), comme ceci :

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>

2. Ajoutez le script dans le corps de votre page, juste avant /body :

<script>
/* <![CDATA[ */
/*
|-----------------------------------------------------------------------
|  jQuery Multiple Toggle Script by Matt - www.skyminds.net
|-----------------------------------------------------------------------
|
| Affiche et cache le contenu de blocs multiples.
|
*/
jQuery(document).ready(function() {
    jQuery(".more").hide();
    jQuery('.button-read-more').click(function () {
        jQuery(this).closest('.less').addClass('active');
        jQuery(this).closest(".less").prev().stop(true).slideDown("1000");
    });
    jQuery('.button-read-less').click(function () {
        jQuery(this).closest('.less').removeClass('active');
        jQuery(this).closest(".less").prev().stop(true).slideUp("1000");
    });
});
/* ]]> */
</script>

3. Le code HTML avec vos blocs de texte :

<strong>Article A</strong></code></pre>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<div class="toggle">
  <div class="more">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam</p>
  </div>
  <div class="less">
    <a class="button-read-more button-read" href="#read">Lire la suite</a> <a class="button-read-less button-read" href="#read">Replier</a>
   </div>
</div>

<strong>Article B</strong></code></pre>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<div class="toggle">
  <div class="more">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam</p>
  </div>
  <div class="less">
    <a class="button-read-more button-read" href="#read">Lire la suite</a> <a class="button-read-less button-read" href="#read">Replier</a>
   </div>
</div>

<strong>Article C</strong></code></pre>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<div class="toggle">
  <div class="more">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam</p>
  </div>
  <div class="less">
    <a class="button-read-more button-read" href="#read">Lire la suite</a> <a class="button-read-less button-read" href="#read">Replier</a>
   </div>
</div>

4. Le code CSS, à styliser selon vos goûts et envies :

.less.active .button-read-more, .button-read-less  {display: none}
.less.active .button-read-less {display: block}
.more {margin-top: 10px}
.more p {margin: 0;padding: 0}

Et si on voulait que le bloc s’affiche dessous ?

Dans les commentaires, bilboquet m’a demandé comment faire pour que le bloc de texte s’affiche en-dessous du lien pour voir la suite.

Voici ce qu’il faut modifier au code précédent :

a. Dans le script jQuery, il faut remplacer les instances prev() par next():

<script>/* <![CDATA[ */
/*
|-----------------------------------------------------------------------
|  jQuery Multiple Toggle Script by Matt - www.skyminds.net
|-----------------------------------------------------------------------
|
| Affiche et cache le contenu de blocs multiples. Bloc après le texte.
|
*/
jQuery(document).ready(function() {
    jQuery(".more").hide();
    jQuery('.button-read-more').click(function () {
        jQuery(this).closest('.less').addClass('active');
        jQuery(this).closest(".less").next().stop(true).slideDown("1000");
    });
    jQuery('.button-read-less').click(function () {
        jQuery(this).closest('.less').removeClass('active');
        jQuery(this).closest(".less").next().stop(true).slideUp("1000");
    });
});
/* ]]> */
</script>

Cela veut dire qu’au lieu de remonter dans l’arbre DOM pour trouver l’élément le plus proche avec la fonction prev(), le script va descendre avec la fonction next().

b. Cela signifie également que la structure du code HTML doit être modifiée, le bloc de texte caché doit maintenant se trouver après les liens qui montrent ou cachent le bloc:

<strong>Article A</strong></code></pre>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>

<div class="toggle">
  <div class="less">
    <a class="button-read-more button-read" href="#read">Lire la suite</a> <a class="button-read-less button-read" href="#read">Replier</a>
  </div>
  <div class="more">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam</p>
  </div>
</div>

c. Voici un exemple de démonstration :


Article A

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam

 

N’ouvrir qu’un seul élément à la fois

Si vous ne souhaitez n’ouvrir qu’un seul élément à la fois, il suffit d’ajouter une ligne qui ferme tous les éléments lorsque l’on clique sur le lien:

 jQuery('.more').hide();

Code javascript modifié:

<script>
/* <![CDATA[ */
/*
|-----------------------------------------------------------------------
|  jQuery Multiple Toggle Script, one at a time by Matt - www.skyminds.net
|-----------------------------------------------------------------------
|
| Affiche et cache le contenu de blocs multiples. Bloc après le texte. 
| Un seul élément à la fois.
|
*/
jQuery(document).ready(function() {
    jQuery(".more").hide();
    jQuery('.button-read-more').click(function () {
	 // one at a time
	 jQuery('.more').hide();
	 jQuery('.less').removeClass('active');
        //
        jQuery(this).closest('.less').addClass('active');
        jQuery(this).closest(".less").next().stop(true).slideDown("1000");
    });
    jQuery('.button-read-less').click(function () {
        jQuery(this).closest('.less').removeClass('active');
        jQuery(this).closest(".less").next().stop(true).slideUp("1000");
    });
});
/* ]]> */ 
</script>

Explications

On crée un bloc avec la classe toggle qui contient deux autres blocs : un bloc avec une classe more qui est cachée par défaut et qui contient le texte à montrer, et un bloc avec la classe less qui contient les liens “Lire la suite” (lorsque le bloc est caché) et “Replier” (lorsque le bloc est visible).

Le script utilise la fonction .closest() pour trouver l’élément le plus proche à montrer ou à cacher et les fonctions .slideup() et .slidedown() pour rendre visible ou non les blocs.

Avec prev(), le script affiche l’élément qui se trouve au-dessus (on remonte l’arbre DOM). Dans le second exemple, avec next(), le script affiche le bloc qui vient après (on descend l’arbre DOM).

En espérant que cela puisse vous être utile.

Vous avez un projet WordPress ou WooCommerce en tête? Transformez votre vision en réalité avec mon expertise reconnue.

Parlons de votre projet dès aujourd'hui »

Articles conseillés :

29 pensées sur “jQuery : script toggle pour afficher et cacher de multiples blocs HTML”

  1. Génial ce code. Merci pour ton tuto très clair !
    Juste une question :
    Dans ton exemple, le click ferme la div qui est au-dessus, la fonction closest() lisant le code en le remontant dans la page html apparemment.
    Peut-on lui demander de fermer la div du dessous, celle qui vient après dans le code html ?
    Merci !

    Reply
    • Bonjour bilboquet,

      Je viens d’ajouter une partie à l’article qui explique comment on peut afficher un bloc qui vient en-dessous des liens.

      Reply
  2. Bonjour Matt,
    Ton tuto est bien expliqué. Cependant j’aurai quelques questions. Sur mon site internet j’ai une barre avec des onglets. Lorsque je clique sur un des onglets j’aimerai que mon contenu s’affiche sur une div (situé à gauche de mon écran) tout en restant sur la même page (d’où le principe du toggle). Or chaque onglet afficherait un contenu différent. Penses tu que celà serait faisable ?
    Et si oui, comment ?
    merci

    Reply
  3. Bonjour,
    Petite question,comment supprimer le bouton “Replier” ?
    Et en même temps,lorsqu’on l’on appuie sur le bouton “Lire la suite” ça ouvre le contenu,et lorsque que l’on reclique,le contenu se referme ?

    Reply
    • Bonjour,

      Tu peux remettre le texte du lien “Lire la suite” au lieu de “Replier” mais tu ne peux pas avoir un seul et même lien.

      Reply
  4. Bonjour,
    Super tuto !!!
    La dernière partie du tuto m’intéresse, quand je clique sur “lire la suite”, ceci fonctionne correctement mais lorsque je clique sur un autre article “lire la suite” le premier est bien refermé mais laisse apparaître le bouton “replier”, y a-t-il un moyen de revenir au résultat initial, à savoir le bouton “lire la suite” ?
    Merci d’aider un pov débutant ;)

    Reply
    • Je me réponds à moi-même, j’ai simplement supprimer le bouton “Replier”, ajouter la classe .button-read avec display: block et fait pointer la fonction sur la classe .button-read et ça fonctionne très bien…
      Désolé, un peu trop rapide à poser la question…
      Merci et bonne journée !!!!

      Reply
  5. Bonjour,

    J’ai testé les deux premiers scripts. Ils fonctionnent correctement. Par contre j’ai une bizarrerie concernant la couleur du lien « replier ». J’ai conservé la couleur des mes liens (css d’origine, fichier externe). Les couleurs restent les mêmes (a et a:hover) mais il apparaît une couleur background bleue (testé sur Firefox)et le lien « replier » est cliquable sur la largeur de la page, pas uniquement sur le mot.

    Avez-vous déjà rencontré ce problème ?

    Sur les démos, quel css avez-vous appliqué à vos liens ?

    Autre question : quel est l’intérêt de nommer une div « toggle » car ce nom n’apparaît dans aucun script ou style (jquery, css) ? Merci pour vos réponses !

    Reply
    • Désolé de vous avoir embêté. Je viens de trouver l’origine du problème. Dans mon fichier css il y avait déjà une classe qui s’appelait “active” et qui faisait donc interférence avec le script jquery. Maintenant tout fonctionne ! Kénavo.

      Reply
  6. Bonjour,

    Juste pour dire que le

    style="display:none"

    est inutile pour le div de class .more puisqu’il fait doublon avec le hide du javascript, et qu’il rend le tout inaccessible pour ceux qui aurait javascript désactivé.

    Sinon, l’ajout d’un

    $(".less").removeClass('active'); 

    après ou avant le second

    $('.more').hide();

    permet de retirer les class ajoutées auparavant (utile quand on a plusieurs blocs utilisant la fonction, car le possible “Replier” existant disparait alors).

    Reply
    • Bonjour P’tit Ben,

      Merci pour tes remarques constructives ! Je n’avais pas pensé au cas où javascript serait désactivé – le script a été corrigé pour prendre cela en compte.

      Reply
  7. Ce n’est pas tout à fait cela le problème:
    quand je clique sur le lien ire la suite, il m’envoie sur la page d’accueil
    Puis si je fais retour, je reviens sur ma page avec le bloc caché et le lien réduire qui sont bien bien affichés.
    Puis si je clique sur le lien replier, même processus: renvoi sur la page d’accueil retour arrière, le bloc cachés et le bouton replier ne sont plus visibles

    Reply
  8. Bonjour, est-il possible de faire apparaître d’emblée un “more”.
    Comme sur votre sommaire plus haut, où lorsque l’on clique on replie, mais le sommaire est déjà affiché au chargement de la page.

    Reply
  9. Bonjour,

    J’ai utilisé ce script mais en fin de mon url on trouve sans cesse: “#read”.
    Comment peut-on faire pour qu’il ne s’affiche plus systématiquement?
    Merci,

    Pierre

    Reply
  10. Bonjour Matt,

    C’est un super script et qui prouve que faire simple c’est faire efficace.

    Je cherchais quelque chose qui puisse s’intégrer à mon projet. Il est donc en test sur ma page locale mais pas avec l’usage initial que tu as imaginé.

    Je me suis dit, à tort ou à raison, que ça pouvait faire office d’accordéon et je l’envisage pour une FaQ. En remplaçant le premier texte par une simple question et en remplaçant lire la suite par lire la réponse : on obtient un déroulé de questions très sympa. Il y a juste un souci de présentation du coup: le lire la suite apparait collé en bas de chaque bloc texte.

    J’ai beau retourner le script et la css dans tous les sens, je n’arrive pas à arriver à l’effet voulu, savoir le bouton lire la réponse qui colle à la question.

    As-tu une idée ?

    Reply
  11. Je me reveil tard au regard de la date de l’article et des commentaires !
    J’ai trouvé le tuto efficace et meilleurs que sur d’autre site… étant parfaitement débutant, je suis content de trouver des articles pour ajouter des fonctions qui soit accessible au non initié !

    J’ai juste un petit problème que je ne sais pas résoudre seul… un petit coup de main serait vraiment génial.

    Les mots “lire la suite” et replier sont en permanence affiché… que le bloc soit ouvert ou plier…
    Un avis ?

    Reply
  12. Mise à jour de l’article. $ a été remplacé par jQuery tout au long du code. Cela peut éviter quelques erreurs selon la version de jQuery utilisée.

    Reply
  13. Bonjour Matt

    Il est très bien votre script. Hélas avec ma base de données et multiples div nommées avec id pour chaque div, je ne sais pas faire avec jQuery.
    La même chose n’existerait pas avec javaScript ?
    Voici mon script qui fait la même chose, mais je ne peux pas refermer une même div ouverte. Il ne doit pas manquer grand chose mais ça fait pas mal de temps que je bloque là-dessus.

    Exemple javaScript :

    function ouvrirFermerSpoiler(div) {
    let spoilers = document.getElementsByClassName(“contenuSpoiler”);

    for (let i = 0, nombres = spoilers.length; i < nombres; i++) {
    if (spoilers[i].classList.contains("afficher") == true) {
    spoilers[i].classList.remove ('afficher');
    spoilers[i].classList.toggle ('cacher');
    }
    }

    let divContenu = div.getElementsByTagName('div')[1];

    if (divContenu.classList.contains('cacher') == true) {
    divContenu.classList.remove('cacher');
    divContenu.classList.toggle('afficher');
    }
    };

    // Ouvre une div après l'autre, mais ne peut pas refermer la div ouverte en recliquant sur "cacher le résumé".

    Et le html (php) :

    Voir le résumé

    Pour “Voir le résumé”, j’ai un autre script en jQuery :

    $(document).ready(function(){
    $(‘.lienAfficher’).click(function() {
    if ($(this).hasClass(‘ouvrir’)) {
    $(this).empty().prepend(‘Cacher le résumé’);
    $(this).removeClass(‘ouvrir’);
    }
    else
    {
    $(this).empty().prepend(‘Voir le résumé’);
    $(this).addClass(‘ouvrir’);
    }
    });
    });

    Donc quand je clique sur Voir le résumé ça m’affiche le résumé et ça se transforme en “Cacher le résumé”. Tout ça fonctionne très bien. Je voulais juste le préciser.
    Merci de votre aide et tans pis si vous n’avez pas de solution pour moi :-) Je tente.

    Pour votre visuel de ce dont je parle, voyez mon site web ci-dessous, dans la partie Livres du menu.

    Valérie

    Reply

Opinions