{"id":10908,"date":"2025-10-11T10:50:11","date_gmt":"2025-10-11T09:50:11","guid":{"rendered":"https:\/\/www.visionlarge.ch\/Blog\/?p=10908"},"modified":"2026-04-27T11:38:26","modified_gmt":"2026-04-27T10:38:26","slug":"de-nouveaux-plugin-s-pour-vos-images","status":"publish","type":"post","link":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/","title":{"rendered":"De nouveaux plugin&rsquo;s pour vos images. (et surtout les miennes)"},"content":{"rendered":"\n<p><strong>Qu\u2019est-ce qu\u2019un plugin ?<\/strong><br \/>Un plugin, c\u2019est un petit programme, g\u00e9n\u00e9ralement \u00e9crit en PHP, qui contient des morceaux de code HTML, des scripts et du CSS. Il permet d\u2019ajouter des fonctionnalit\u00e9s pratiques que WordPress ne propose pas nativement, ou d\u2019exploiter des fonctions sp\u00e9cifiques de WordPress.<\/p>\n\n\n\n<p><strong>Les plugins de visualisation de photos<\/strong><br \/>Il existe une multitude d\u2019options et de possibilit\u00e9s avec les plugins de galeries photo. Malheureusement, les fonctionnalit\u00e9s gratuites, comme celles d\u2019Envira par exemple, sont limit\u00e9es et souvent payantes. Et bien s\u00fbr, j\u2019ai rencontr\u00e9 beaucoup de bugs (ce qui n\u2019est pas vraiment surprenant\u2026) lorsque j\u2019utilise mon t\u00e9l\u00e9phone portable.<\/p>\n\n\n\n<p><strong>Les risques des plugins externes<\/strong><br \/>On est toujours expos\u00e9 au risque que le plugin cesse d\u2019\u00eatre mis \u00e0 jour, qu\u2019il r\u00e9duise le nombre de galeries autoris\u00e9es, ou qu\u2019il supprime des options qu\u2019on utilise. Sans parler des licences et des biblioth\u00e8ques tierces, qui peuvent parfois buguer ou ralentir l\u2019affichage.<\/p>\n\n\n\n<p><strong>Mon propre plugin<\/strong><br \/>Pour ne plus d\u00e9pendre d\u2019Envira Gallery (ou d\u2019une autre application), j\u2019ai d\u00e9cid\u00e9 de cr\u00e9er mon propre plugin. Enfin\u2026 il y en a m\u00eame deux aujourd\u2019hui, voire trois !<\/p>\n\n\n\n<p><strong>Disponibilit\u00e9<\/strong><br \/>Mon plugin n\u2019est pas disponible sur le d\u00e9p\u00f4t officiel de WordPress. Il faut me le demander directement. Bon, je dois avouer que\u2026 personne ne me l\u2019a encore demand\u00e9. Dommage, car il est gratuit (pour l\u2019instant, et je ne pense pas que j&rsquo;ai envie de le mettre payant&#8230;). Peut-\u00eatre que la mode est \u00e0 Instagram ? Ou alors, les gens ont des sites auto-h\u00e9berg\u00e9s sur WordPress et ne peuvent pas ajouter un plugin qui n\u2019est pas install\u00e9 sur leur serveur. Bref\u2026 Je trouve dommage que personne n&rsquo;aie fait une demande&#8230; Car franchement dans les galeries d&rsquo;images y&rsquo;a vraiment moins bien!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>VL SLIDER.<\/strong><\/h3>\n\n\n\n<p><strong>Le premier plugin : un slider simple<\/strong><br \/>Ce plugin permet tout simplement de faire d\u00e9filer des images dans un article mais c\u2019est tr\u00e8s pratique ! Si on choisi de pouvoir cliquer et les voir en grand, on peut passer \u00e0 la suivante avec les touches du clavier, ou si on est sur smartphone ou tablette de faire un swipe du doigts \ud83d\ude09<\/p>\n\n\n\n    \n        <div class=\"vl-slider-wrap\" id=\"vl-slider-inst1-wrap\">\n\n                        \n                <div id=\"vl-slider-inst1\"\n             class=\"vl-slider-container vl-slider-cols-1\">\n\n                        <div class=\"vl-slider-row\" data-row=\"0\">\n\n                                                <div class=\"vl-slider-slot\" data-slot=\"0\">\n\n                                        <img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/SevilleHasselbladProfil-scaled.jpg\"\n                         alt=\"Un moment de vie dans les rues color\u00e9es de la ville de S\u00e9ville en Espagne. Ici, j&#039;ai utilis\u00e9 un de mes presets de simulation de film. Je trouve qu&#039;il fonctionne bien avec les belles couleurs des maisons de S\u00e9ville.\"\n                         class=\"vl-slider-img vl-slider-img-active\">\n\n                                        <img decoding=\"async\" src=\"\" alt=\"\" class=\"vl-slider-img vl-slider-img-next\">\n\n                                        \n                <\/div>\n            <\/div><!-- \/.vl-slider-row -->\n            \n        <\/div><!-- \/.vl-slider-container -->\n\n                \n                \n                        <div class=\"vl-slider-below-wrap\"\n             id=\"vl-slider-inst1-below-wrap\"\n             style=\"display:none;opacity:0;\">\n                        <div class=\"vl-slider-below-text\"\n                 id=\"vl-slider-inst1-below-0\">\n                                <p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">Dans les rues de S\u00e9ville<\/p>\n                                                <p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">Canon EOS M et objectifs du kit EFM<\/p>\n                                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">Un moment de vie dans les rues color\u00e9es de S\u00e9ville, en Espagne. J\u2019ai utilis\u00e9 ici l\u2019un de mes presets de simulation de film, qui fonctionne particuli\u00e8rement bien avec les belles couleurs des maisons s\u00e9villanes.<\/p>\n                            <\/div>\n                    <\/div>\n\n                        <div class=\"vl-sl-toggle-wrap\" id=\"vl-slider-inst1-toggle-wrap\">\n            <button class=\"vl-sl-toggle-btn\"\n                    id=\"vl-slider-inst1-toggle-btn\"\n                    aria-pressed=\"false\"\n                    aria-label=\"Afficher les d\u00e9tails\">\n                                <svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\"\n                     viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n                     stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                    <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8z\"><\/path>\n                    <circle cx=\"12\" cy=\"12\" r=\"3\"><\/circle>\n                <\/svg>\n                <span class=\"vl-sl-btn-label\">Afficher les d\u00e9tails<\/span>\n            <\/button>\n        <\/div>\n                \n    <\/div><!-- \/.vl-slider-wrap -->\n\n                <div class=\"vl-sl-lb-wrap\"\n         id=\"vl-slider-inst1-lightbox\"\n         role=\"dialog\" aria-modal=\"true\" aria-label=\"Visionneuse d'images\"\n         style=\"display:none;\">\n\n                <div class=\"vl-sl-lb-overlay\" aria-hidden=\"true\"><\/div>\n\n        <div class=\"vl-sl-lb-content\">\n\n                        <div class=\"vl-sl-lb-toolbar\">\n                <span class=\"vl-sl-lb-counter\"\n                      id=\"vl-slider-inst1-lb-counter\"\n                      aria-live=\"polite\"><\/span>\n                <button class=\"vl-sl-lb-close\"\n                        id=\"vl-slider-inst1-lb-close\"\n                        aria-label=\"Fermer\">&times;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-stage\">\n                <button class=\"vl-sl-lb-prev\"\n                        id=\"vl-slider-inst1-lb-prev\"\n                        aria-label=\"Image pr\u00e9c\u00e9dente\">&#10094;<\/button>\n\n                <div class=\"vl-sl-lb-img-wrap\">\n                                        <div class=\"vl-sl-lb-progress-container\" aria-hidden=\"true\">\n                        <div class=\"vl-sl-lb-progress-bar\"\n                             id=\"vl-slider-inst1-lb-progress\"><\/div>\n                    <\/div>\n                    <img decoding=\"async\" src=\"\" alt=\"\"\n                         id=\"vl-slider-inst1-lb-img\"\n                         class=\"vl-sl-lb-img\">\n                                        <div class=\"vl-sl-lb-caption\"\n                         id=\"vl-slider-inst1-lb-caption\"\n                         aria-live=\"polite\"><\/div>\n                <\/div>\n\n                <button class=\"vl-sl-lb-next\"\n                        id=\"vl-slider-inst1-lb-next\"\n                        aria-label=\"Image suivante\">&#10095;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-footer\">\n                <div class=\"vl-sl-lb-controls\">\n                    <button class=\"vl-sl-lb-playpause\"\n                            id=\"vl-slider-inst1-lb-playpause\"\n                            aria-label=\"Lancer le diaporama\"\n                            aria-pressed=\"false\">\u25b6<\/button>\n                    <button class=\"vl-sl-lb-speed\"\n                            id=\"vl-slider-inst1-lb-speed\"\n                            aria-label=\"Changer la vitesse\">4s<\/button>\n                <\/div>\n            <\/div>\n\n        <\/div><!-- \/.vl-sl-lb-content -->\n    <\/div><!-- \/.vl-sl-lb-wrap -->\n    \n\n        <style id=\"vl-slider-inst1-style\">\n\n        \/* \u2500\u2500 Wrap ext\u00e9rieur \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:relative est n\u00e9cessaire pour que les fant\u00f4mes (position:absolute)\n           se positionnent par rapport au wrap et non \u00e0 la page enti\u00e8re.          *\/\n        #vl-slider-inst1-wrap {\n            width: 100%;\n            max-width: 100%;\n            margin: 20px auto;\n            position: relative;\n            \/* PAS de overflow:hidden ici \u2014 les fant\u00f4mes d\u00e9bordent intentionnellement *\/\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Conteneur principal : colonne flex (rang\u00e9es empil\u00e9es) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex-direction:column \u2192 les .vl-slider-row s'empilent verticalement.\n           gap:8px \u2192 espacement entre rang\u00e9es.                                    *\/\n        #vl-slider-inst1 {\n            display: flex;\n            flex-direction: column;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            overflow: hidden;\n            border-radius: 8px;\n            background: transparent;\n            box-sizing: border-box;\n        }\n\n        \/* \u2500\u2500 Rang\u00e9e : ligne flex (slots c\u00f4te \u00e0 c\u00f4te) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           height est d\u00e9fini ici par rang\u00e9e pour permettre des hauteurs\n           diff\u00e9rentes entre rang\u00e9e 1 et rang\u00e9e 2 (height_row2).                 *\/\n        #vl-slider-inst1 .vl-slider-row {\n            display: flex;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            height: 500px;\n            overflow: hidden;\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Slot individuel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex:1 \u2192 chaque slot prend la m\u00eame largeur dans sa rang\u00e9e.\n           position:relative \u2192 n\u00e9cessaire pour les images en absolute.            *\/\n        #vl-slider-inst1 .vl-slider-slot {\n            position: relative;\n            flex: 1;\n            min-width: 0;\n            overflow: hidden;\n            border-radius: 6px;\n            box-sizing: border-box;\n            \/* La hauteur est fix\u00e9e par la rang\u00e9e parente (.vl-slider-row) *\/\n        }\n\n        \/* \u2500\u2500 Images : remplissent exactement le slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:absolute + inset:0 \u2192 l'image couvre tout le slot.\n           object-fit:contain \u2192 image enti\u00e8re visible sans recadrage.\n           IMPORTANT : fonctionne uniquement si le slot a une hauteur d\u00e9finie,\n           ce qui est garanti par .vl-slider-row { height: Xpx }.               *\/\n        #vl-slider-inst1 .vl-slider-img {\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n            background: transparent;\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* \u2500\u2500 Fix critique : la rang\u00e9e DOIT avoir overflow:hidden \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Sans \u00e7a, les images en position:absolute d\u00e9bordent visuellement\n           m\u00eame si leur taille est contrainte.                                  *\/\n        #vl-slider-inst1 .vl-slider-row {\n            overflow: hidden;\n            contain: strict;       \/* Isole compl\u00e8tement le rendu de la rang\u00e9e *\/\n        }\n        \/* Image active : visible (opacity 1) *\/\n        #vl-slider-inst1 .vl-slider-img-active { opacity: 1; }\n        \/* Image suivante : invisible (opacity 0), pr\u00eate pour la prochaine transition *\/\n        #vl-slider-inst1 .vl-slider-img-next   { opacity: 0; }\n\n                \/* \u2500\u2500 Curseur zoom-in si lightbox activ\u00e9e \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           pointer-events:none sur img-next \u2192 seule l'image active re\u00e7oit les clics. *\/\n        #vl-slider-inst1 .vl-slider-slot { cursor: zoom-in; }\n        #vl-slider-inst1 .vl-slider-img-next { pointer-events: none; }\n        #vl-slider-inst1 .vl-slider-overlay-text { pointer-events: none; }\n        \n        \n        \/* \u2500\u2500 Overlay texte (sur l'image) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Bande semi-transparente en bas de chaque slot.\n           La transition opacity correspond au fade_in configur\u00e9.                 *\/\n        #vl-slider-inst1 .vl-slider-overlay-text {\n            position: absolute;\n            bottom: 0; left: 0; right: 0;\n            background: rgba(0, 0, 0, .5);\n            color: #fff;\n            padding: 10px 16px;\n            font-size: 13px;\n            line-height: 1.5;\n            border-radius: 0 0 6px 6px;\n            transition: opacity 1s ease-in-out;\n        }\n        #vl-slider-inst1 .vl-slider-overlay-text p { margin: 2px 0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2014 scop\u00e9 \u00e0 cette instance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Pour columns=3 rang\u00e9e 2 (1 slot centr\u00e9) : limiter la largeur du bloc.  *\/\n        #vl-slider-inst1-below-wrap .vl-row-centered .vl-slider-below-text {\n            max-width: 50%;\n        }\n\n        \/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*\/\n        @media (max-width: 767px) {\n            #vl-slider-inst1 .vl-slider-row {\n                height: 200px !important;\n            }\n        }\n        @media (max-width: 479px) {\n                    }\n\n    <\/style>\n\n        <style>\n\n        \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n           LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n           \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n        \/* Fond plein \u00e9cran \u2014 cach\u00e9 par d\u00e9faut, affich\u00e9 via display:flex en JS *\/\n        .vl-sl-lb-wrap {\n            position: fixed;\n            inset: 0;\n            z-index: 99999;\n            display: none; \/* display:flex quand ouverte *\/\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            padding: 1rem;\n            box-sizing: border-box;\n        }\n\n        \/* Fond semi-transparent \u2014 clic = fermeture *\/\n        .vl-sl-lb-overlay {\n            position: fixed;\n            inset: 0;\n            background: rgba(0, 0, 0, .88);\n            cursor: pointer;\n            z-index: 0;\n        }\n\n        \/* Contenu centr\u00e9 au-dessus du fond *\/\n        .vl-sl-lb-content {\n            position: relative;\n            z-index: 1;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 92vw;\n            max-height: 92vh;\n            gap: 8px;\n        }\n\n        \/* Toolbar : compteur + bouton \u00d7 *\/\n        .vl-sl-lb-toolbar {\n            display: flex;\n            width: 100%;\n            align-items: center;\n            justify-content: space-between;\n        }\n        .vl-sl-lb-counter {\n            color: #fff;\n            background: rgba(0, 0, 0, .55);\n            padding: 4px 10px;\n            border-radius: 20px;\n            font-size: 13px;\n        }\n        .vl-sl-lb-close {\n            background: rgba(0, 0, 0, .55);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 34px; height: 34px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            transition: background .2s, transform .2s;\n            line-height: 1;\n        }\n        .vl-sl-lb-close:hover { background: rgba(0, 0, 0, .9); transform: scale(1.15); }\n\n        \/* Stage : fl\u00e8ches + image *\/\n        .vl-sl-lb-stage {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n        }\n        .vl-sl-lb-prev, .vl-sl-lb-next {\n            flex-shrink: 0;\n            background: rgba(0, 0, 0, .5);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 42px; height: 42px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            user-select: none;\n            transition: background .2s, transform .2s;\n        }\n        .vl-sl-lb-prev:hover, .vl-sl-lb-next:hover {\n            background: rgba(0, 0, 0, .9);\n            transform: scale(1.15);\n        }\n\n        \/* Conteneur image : flex-column pour empiler image + caption *\/\n        .vl-sl-lb-img-wrap {\n            position: relative;\n            display: inline-flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 78vw;\n        }\n\n        \/* Image lightbox *\/\n        .vl-sl-lb-img {\n            display: block;\n            max-width: 78vw;\n            max-height: 72vh;\n            border-radius: 8px;\n            box-shadow: 0 4px 32px rgba(0, 0, 0, .5);\n            opacity: 0; \/* commence invisible, JS anime vers 1 *\/\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* Barre de progression du diaporama \u2014 en haut de l'image *\/\n        .vl-sl-lb-progress-container {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 3px;\n            background: rgba(255, 255, 255, .2);\n            border-radius: 2px;\n            overflow: hidden;\n            display: none; \/* visible seulement en mode play *\/\n        }\n        .vl-sl-lb-progress-bar {\n            height: 100%;\n            width: 0%;\n            background: #fff;\n            transition: width linear;\n        }\n\n        \/* Caption sous l'image *\/\n        .vl-sl-lb-caption {\n            color: #fff;\n            font-size: 13px;\n            text-align: center;\n            word-break: break-word;\n            margin-top: 8px;\n            padding: 6px 18px;\n            box-sizing: border-box;\n            max-width: 78vw;\n            line-height: 1.5;\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            border-radius: 14px;\n            display: none; \/* affich\u00e9 par le JS si caption non vide *\/\n        }\n        .vl-sl-lb-caption.has-text { display: inline-block; }\n\n        \/* Footer : boutons play\/pause + vitesse *\/\n        .vl-sl-lb-footer {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            gap: 6px;\n            width: 100%;\n        }\n        .vl-sl-lb-controls { display: flex; gap: 8px; }\n        .vl-sl-lb-playpause, .vl-sl-lb-speed {\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            color: #fff;\n            border-radius: 20px;\n            padding: 4px 14px;\n            font-size: 13px;\n            cursor: pointer;\n            transition: background .2s;\n            min-width: 48px;\n            text-align: center;\n        }\n        .vl-sl-lb-playpause:hover, .vl-sl-lb-speed:hover {\n            background: rgba(255, 255, 255, .28);\n        }\n\n        \/* Mobile : masquer les contr\u00f4les pour ne pas g\u00eaner le swipe *\/\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-prev,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-next,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-caption,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-progress-container,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-close,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-counter { display: none !important; }\n\n        \/* \u2500\u2500 Bouton toggle \"Afficher les d\u00e9tails\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Petit bouton discret align\u00e9 \u00e0 droite, au-dessus des textes below.\n           La classe .active indique l'\u00e9tat \"ouvert\".                             *\/\n        .vl-sl-toggle-wrap { text-align: right; margin-bottom: 10px; }\n        .vl-sl-toggle-btn {\n            background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;\n            padding: 7px 12px; cursor: pointer; font-size: 12px;\n            display: inline-flex; align-items: center; gap: 6px;\n            box-shadow: 0 2px 6px rgba(0, 0, 0, .12);\n            transition: background .2s, box-shadow .2s;\n            line-height: 1;\n        }\n        .vl-sl-toggle-btn:hover  { background: #ececec; box-shadow: 0 3px 8px rgba(0, 0, 0, .18); }\n        .vl-sl-toggle-btn.active { background: #e0e0e0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Le wrap est flex horizontal : un bloc par colonne, c\u00f4te \u00e0 c\u00f4te.\n           Chaque bloc est un bloc normal : les <p> s'empilent naturellement.     *\/\n        .vl-slider-below-wrap {\n            display: flex;\n            flex-direction: row;\n            gap: 8px;\n            width: 100%;\n            box-sizing: border-box;\n            opacity: 0;\n            transition: opacity .3s ease;\n        }\n        .vl-slider-below-wrap.vl-sl-texts-visible { opacity: 1; }\n\n        \/* Bloc texte individuel \u2014 un par image visible *\/\n        .vl-slider-below-text {\n            flex: 1;\n            min-width: 0;\n            padding: 8px 4px;\n            font-size: 13px;\n            line-height: 1.5;\n            text-align: center;\n            box-sizing: border-box;\n        }\n        .vl-slider-below-text p { margin: 2px 0; }\n\n        \/* Styles texte *\/\n        .vl-sl-title       { font-weight: bold; }\n        .vl-sl-caption     { font-style: italic; }\n        .vl-sl-alt         { font-size: 11px; }\n        .vl-sl-description { font-size: 12px; }\n\n        \/* Couleurs overlay (fond sombre \u2192 texte blanc) *\/\n        .vl-slider-overlay-text .vl-sl-title       { color: #fff; }\n        .vl-slider-overlay-text .vl-sl-caption     { color: rgba(255, 255, 255, .8); }\n        .vl-slider-overlay-text .vl-sl-alt         { color: rgba(255, 255, 255, .6); }\n        .vl-slider-overlay-text .vl-sl-description { color: rgba(255, 255, 255, .9); }\n\n        \/* Couleurs below (fond clair \u2192 texte sombre) *\/\n        .vl-slider-below-text .vl-sl-title       { color: #222; }\n        .vl-slider-below-text .vl-sl-caption     { color: #666; }\n        .vl-slider-below-text .vl-sl-alt         { color: #999; font-size: 11px; }\n        .vl-slider-below-text .vl-sl-description { color: #444; font-size: 12px; }\n\n    <\/style>\n\n        <script>\n    (function () {\n        'use strict';\n\n        document.addEventListener('DOMContentLoaded', function () {\n\n            \/\/ \u2500\u2500 R\u00e9f\u00e9rences DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On r\u00e9cup\u00e8re le conteneur principal. Si absent (shortcode mal copi\u00e9),\n            \/\/ on quitte imm\u00e9diatement pour \u00e9viter les erreurs JS.\n            var slider = document.getElementById('vl-slider-inst1');\n            if ( ! slider ) return;\n\n            \/\/ Tous les slots de la grille (inclut toutes les rang\u00e9es)\n            var slots = slider.querySelectorAll('.vl-slider-slot');\n\n            \/\/ Fant\u00f4mes gauche et droit (null si ghost_peek=false \u2192 divs absentes)\n            var ghostLeft  = document.getElementById('vl-slider-inst1-ghost-left');\n            var ghostRight = document.getElementById('vl-slider-inst1-ghost-right');\n            var ghostImgL  = ghostLeft  ? ghostLeft.querySelector('.vl-ghost-img')  : null;\n            var ghostImgR  = ghostRight ? ghostRight.querySelector('.vl-ghost-img') : null;\n\n            \/\/ Overlays texte \u2014 un par slot, cherch\u00e9s dans le conteneur slider\n            var overlayEls = Array.prototype.slice.call(\n                slider.querySelectorAll('.vl-slider-overlay-text')\n            );\n            \/\/ Blocs texte \"below\" \u2014 cibl\u00e9s par classe pour \u00e9viter de capturer le wrap\n            var belowWrap  = document.getElementById('vl-slider-inst1-below-wrap');\n            var belowEls   = belowWrap\n                ? Array.prototype.slice.call( belowWrap.querySelectorAll('.vl-slider-below-text') )\n                : [];\n\n            \/\/ \u2500\u2500 Donn\u00e9es inject\u00e9es par PHP \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ wp_json_encode() c\u00f4t\u00e9 PHP \u2192 JSON valide et safe\n            var slides      = [{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/SevilleHasselbladProfil-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/SevilleHasselbladProfil-scaled.jpg\",\"alt\":\"Un moment de vie dans les rues color\\u00e9es de la ville de S\\u00e9ville en Espagne. Ici, j&#039;ai utilis\\u00e9 un de mes presets de simulation de film. Je trouve qu&#039;il fonctionne bien avec les belles couleurs des maisons de S\\u00e9ville.\",\"title\":\"Dans les rues de S\\u00e9ville\",\"caption\":\"Canon EOS M et objectifs du kit EFM\",\"description\":\"Un moment de vie dans les rues color\\u00e9es de S\\u00e9ville, en Espagne. J\\u2019ai utilis\\u00e9 ici l\\u2019un de mes presets de simulation de film, qui fonctionne particuli\\u00e8rement bien avec les belles couleurs des maisons s\\u00e9villanes.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/VaulionEtLeJuradansSesCouleurs-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/VaulionEtLeJuradansSesCouleurs-scaled.jpg\",\"alt\":\"Entre neige et couleurs d&#039;automne. La dent de Vaulion \\u00e0 recouvert quelques heures son manteau blanc alors que le Jura rev\\u00eat ses plus belles couleurs\",\"title\":\"La dent de Vaulion\",\"caption\":\"Canon EOS R, Canon RF 70-200 F4 L IS\",\"description\":\"Entre neige et couleurs d\\u2019automne : la Dent de Vaulion a rev\\u00eatu, pour quelques heures, son manteau blanc, tandis que le Jura s\\u2019illumine de ses plus belles teintes.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/NatureDansLaLumiere-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/NatureDansLaLumiere-scaled.jpg\",\"alt\":\"Dans la nature dor\\u00e9e de la lumi\\u00e8re d&#039;automne. Au bord de la rivi\\u00e8re l&#039;Orbe \\u00e0 Orbe.\",\"title\":\"Lumi\\u00e8re d&rsquo;automne\",\"caption\":\"Canon EOS R, Canon 70-200 F4 L IS\",\"description\":\"Dans la nature dor\\u00e9e par la lumi\\u00e8re d\\u2019automne, au bord de la rivi\\u00e8re l\\u2019Orbe, \\u00e0 Orbe.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IrlandePlageVolcanique-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IrlandePlageVolcanique-scaled.jpg\",\"alt\":\"Plage volcanique d&#039;Irlande. On voit au loin les c\\u00e9l\\u00e8bres falaises de Moher. Immenses falaises de plusieurs centaines de m\\u00e8tres de haut. Ce jour-l\\u00e0, la mer atlantique se d\\u00e9chaine sur les c\\u00f4tes d&#039;Irlande.\",\"title\":\"Plage volcanique d&rsquo;Irlande\",\"caption\":\"Canon EOS 5D MK II, Canon 17-40 F4 L\",\"description\":\"Plage volcanique d\\u2019Irlande. Au loin, les c\\u00e9l\\u00e8bres falaises de Moher se dessinent, immenses parois de plusieurs centaines de m\\u00e8tres de haut.  Ce jour-l\\u00e0, l\\u2019Atlantique se d\\u00e9chaine sur les c\\u00f4tes irlandaises.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IrlandeMoher-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IrlandeMoher-scaled.jpg\",\"alt\":\"Les c\\u00e9l\\u00e8bres falaises de Moher en Irlande sont \\u00e0 couper le souffle. Un panorama incroyable sur ses murs immenses faisant face \\u00e0 l&#039;ocean. Il n&#039;y aura plus rien devant elles avant l&#039;Am\\u00e9rique.\",\"title\":\"Irlande et falaises de Moher\",\"caption\":\"Canon EOS 5D MK II, Canon 17-40 f4 L\",\"description\":\"Les c\\u00e9l\\u00e8bres falaises de Moher, en Irlande, sont \\u00e0 couper le souffle. Un panorama incroyable sur ces murs immenses, dress\\u00e9s face \\u00e0 l\\u2019oc\\u00e9an. Devant eux, plus rien jusqu\\u2019\\u00e0 l\\u2019Am\\u00e9rique.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChamonixFrance2025-84-Pano-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChamonixFrance2025-84-Pano-scaled.jpg\",\"alt\":\"Les pointes de... Beuhh... C&#039;est celle qui sont \\u00e0 c\\u00f4t\\u00e9 du Mont-Blanc! Un parapentes volent pr\\u00e8s de ses magnifiques montagnes.\",\"title\":\"Les piques du midi\",\"caption\":\"Canon EOS R, Canon RF 24-105 F4 L IS\",\"description\":\"Les pointes de... Beuhh... C&#039;est celle qui sont \\u00e0 c\\u00f4t\\u00e9 du Mont-Blanc! Un parapente vol pr\\u00e8s de ses magnifiques montagnes.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CygneAuCrepusculeOct2025-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CygneAuCrepusculeOct2025-scaled.jpg\",\"alt\":\"Un cygne fait le beau sur le lac de Neuch\\u00e2tel au cr\\u00e9puscule. Plage d&#039;Yverdon-les-Bains en 2025\",\"title\":\"Cygne au cr\\u00e9puscule\",\"caption\":\"Canon EOS R, Canon RF 70-200 F4 L IS\",\"description\":\"Un cygne fait le beau sur le lac de Neuch\\u00e2tel au cr\\u00e9puscule. Plage d\\u2019Yverdon-les-Bains, 2025.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Arc-en-Ciel_Sept_2025-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Arc-en-Ciel_Sept_2025-scaled.jpg\",\"alt\":\"Arc-en-ciel apr\\u00e8s l&#039;orage. Prise de mon balcon ;-) Des oiseaux passent dans le sillage de l&#039;arc-en-ciel.\",\"title\":\"Arc-en-Ciel\",\"caption\":\"Canon EOS R, Canon 70-200 F4 L IS\",\"description\":\"Arc-en-ciel apr\\u00e8s l&#039;orage. Prise de mon balcon ;-) Des oiseaux passent dans le sillage de l&#039;arc-en-ciel.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChanteurGroupeTrashNYverdon2025-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChanteurGroupeTrashNYverdon2025-scaled.jpg\",\"alt\":\"Pendant le concert du groupe TrashAndCo \\u00e0 Yverdon lors de la f\\u00eate de la musique 2025.\",\"title\":\"Concert de Trash And CO 2025\",\"caption\":\"Canon EOS R, Canon 135 F2 L\",\"description\":\"Pendant le concert du groupe TrashAndCo \\u00e0 Yverdon lors de la f\\u00eate de la musique 2025.\"}];\n            var columns     = 1;\n            var slotCount   = 1; \/\/ Nb total de slots visibles\n            var lightbox    = true;\n            var showTitle       = true;\n            var showCaption     = true;\n            var showAlt         = false;\n            var showDescription = true;\n\n            \/\/ \u2500\u2500 Variables d'\u00e9tat du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ currentIndex : index dans $slides de la premi\u00e8re image affich\u00e9e\n            var currentIndex  = 0;\n            \/\/ Dur\u00e9es en millisecondes (PHP les envoie en secondes)\n            var displayTime   = 5 * 1000;\n            var fadeInTime    = 1 * 1000;\n            var fadeOutTime   = 1 * 1000;\n            var sliderPaused  = false;  \/\/ Vrai quand la lightbox ou le toggle sont ouverts\n            var sliderTimer   = null;   \/\/ R\u00e9f\u00e9rence au setTimeout en cours\n\n            \/\/ \u2500\u2500 pauseSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Arr\u00eate les transitions (lightbox ouverte, textes below affich\u00e9s).\n            \/\/ clearTimeout annule le prochain changeImage() planifi\u00e9.\n            function pauseSlider() {\n                sliderPaused = true;\n                if ( sliderTimer ) {\n                    clearTimeout( sliderTimer );\n                    sliderTimer = null;\n                }\n            }\n\n            \/\/ \u2500\u2500 resumeSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Reprend les transitions apr\u00e8s fermeture lightbox ou toggle.\n            \/\/ Ne red\u00e9marre que s'il y a assez d'images pour animer.\n            function resumeSlider() {\n                sliderPaused = false;\n                if ( slides.length >= slotCount && slides.length > 1 ) {\n                    sliderTimer = setTimeout( changeImage, displayTime );\n                }\n            }\n\n            \/\/ \u2500\u2500 Protection des images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ D\u00e9sactive le clic droit (contextmenu) et le glisser-d\u00e9poser (dragstart)\n            \/\/ sur toutes les images du slider pour d\u00e9courager la copie.\n            slider.querySelectorAll('.vl-slider-img').forEach(function ( img ) {\n                img.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n                img.addEventListener('dragstart',   function (e) { e.preventDefault(); });\n            });\n            slider.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n            \/\/ Navigation : fl\u00e8ches, clavier, swipe tactile\n            \/\/ Diaporama  : play\/pause, vitesse, barre de progression\n            \/\/ Transitions: fade | slide | none (param\u00e8tre lb_transition)\n            \/\/ Mobile     : masquage automatique des contr\u00f4les, swipe uniquement\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            if ( lightbox ) {\n\n                var lbWrap     = document.getElementById('vl-slider-inst1-lightbox');\n                var lbImg      = document.getElementById('vl-slider-inst1-lb-img');\n                var lbClose    = document.getElementById('vl-slider-inst1-lb-close');\n                var lbOverlay  = lbWrap ? lbWrap.querySelector('.vl-sl-lb-overlay') : null;\n                var lbPrev     = document.getElementById('vl-slider-inst1-lb-prev');\n                var lbNext     = document.getElementById('vl-slider-inst1-lb-next');\n                var lbCounter  = document.getElementById('vl-slider-inst1-lb-counter');\n                var lbCaption  = document.getElementById('vl-slider-inst1-lb-caption');\n                var lbPlay     = document.getElementById('vl-slider-inst1-lb-playpause');\n                var lbSpeedBtn = document.getElementById('vl-slider-inst1-lb-speed');\n                var lbProgress = document.getElementById('vl-slider-inst1-lb-progress');\n                var lbProgWrap = lbProgress ? lbProgress.parentElement : null;\n                var lbTransition  = 'fade';\n                var lbTransSpeed  = 400;\n                var lbSlideTimer  = null;\n                var lbSlideSpeed  = 4000;\n                var lbIsPlaying   = false;\n                var lbCurrentIdx  = 0;\n                var lbImages      = [];\n                var lbNavigating  = false;\n\n                if ( ! lbWrap ) return;\n\n                function lbIsMobile() {\n                    return \/Android|iPhone|iPod\/i.test(navigator.userAgent) &&\n                           ( 'ontouchstart' in window || navigator.maxTouchPoints > 0 );\n                }\n                function lbIsTabletPortrait() {\n                    return ( \/iPad|Android\/i.test(navigator.userAgent) || navigator.maxTouchPoints > 0 ) &&\n                           window.innerWidth <= 1024 && window.innerHeight > window.innerWidth;\n                }\n                function updateMobileNav() {\n                    lbWrap.classList.toggle('vl-lb-hide-nav', lbIsMobile() || lbIsTabletPortrait());\n                }\n\n                function openLightbox( clickedIndex ) {\n                    lbImages = slides.map(function ( s ) {\n                        return { url: s.full_url || s.url, alt: s.alt || '', title: s.title || '', description: s.description || '' };\n                    });\n                    lbCurrentIdx = ( ( clickedIndex % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var single = lbImages.length <= 1;\n                    if ( lbPrev ) lbPrev.style.display = single ? 'none' : '';\n                    if ( lbNext ) lbNext.style.display = single ? 'none' : '';\n                    updateMobileNav();\n                    lbWrap.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                    showLbImage( lbCurrentIdx );\n                    if ( lbClose ) lbClose.focus();\n                }\n\n                function showLbImage( index ) {\n                    if ( ! lbImages.length ) return;\n                    var prevIdx  = lbCurrentIdx;\n                    lbCurrentIdx = ( ( index % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var item     = lbImages[ lbCurrentIdx ];\n                    var dir      = index >= prevIdx ? 1 : -1;\n\n                    if ( lbCounter ) lbCounter.textContent = ( lbCurrentIdx + 1 ) + ' \/ ' + lbImages.length;\n                    var capText = item.description || item.alt || item.title || '';\n                    if ( lbCaption ) {\n                        lbCaption.textContent = capText;\n                        lbCaption.classList.toggle('has-text', capText.length > 0);\n                    }\n                    resetLbProgressBar();\n\n                    if ( lbTransition === 'none' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealNone() { lbImg.style.opacity = '1'; }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealNone() : ( lbImg.onload = lbImg.onerror = revealNone );\n                        return;\n                    }\n\n                    if ( lbTransition === 'fade' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.onload = null; lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealFade() {\n                            void lbImg.offsetWidth;\n                            lbImg.style.transition = 'opacity ' + ( lbTransSpeed \/ 1000 ) + 's ease';\n                            requestAnimationFrame(function () { lbImg.style.opacity = '1'; });\n                        }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealFade() : ( lbImg.onload = lbImg.onerror = revealFade );\n                        return;\n                    }\n\n                    if ( lbTransition === 'slide' ) {\n                        var imgWrap = lbImg.parentElement;\n                        var easing  = 'cubic-bezier(.25,.46,.45,.94)';\n                        var dur     = ( lbTransSpeed \/ 1000 ) + 's';\n                        var newImg  = new Image();\n                        newImg.alt = item.alt; newImg.draggable = false;\n                        newImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;box-shadow:0 4px 32px rgba(0,0,0,.5);opacity:1;transform:translateX(' + ( dir * 100 ) + '%);transition:none;user-select:none';\n                        function doSlide() {\n                            imgWrap.style.cssText = 'position:relative;overflow:hidden;display:inline-flex;width:' + lbImg.offsetWidth + 'px;height:' + lbImg.offsetHeight + 'px';\n                            lbImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;opacity:1;transform:translateX(0);transition:none;user-select:none';\n                            imgWrap.appendChild( newImg );\n                            requestAnimationFrame(function () {\n                                requestAnimationFrame(function () {\n                                    lbImg.style.transition = newImg.style.transition = 'transform ' + dur + ' ' + easing;\n                                    lbImg.style.transform  = 'translateX(' + ( -dir * 100 ) + '%)';\n                                    newImg.style.transform = 'translateX(0)';\n                                    setTimeout(function () {\n                                        lbImg.src = newImg.src; lbImg.alt = newImg.alt;\n                                        lbImg.style.cssText = ''; lbImg.style.opacity = '1';\n                                        if ( imgWrap.contains(newImg) ) imgWrap.removeChild( newImg );\n                                        imgWrap.style.cssText = '';\n                                        lbNavigating = false;\n                                    }, lbTransSpeed + 30);\n                                });\n                            });\n                        }\n                        newImg.onload = newImg.onerror = doSlide;\n                        newImg.src = item.url;\n                        if ( newImg.complete && newImg.naturalWidth > 0 ) { newImg.onload = null; doSlide(); }\n                        return;\n                    }\n                }\n\n                function lbNavigateTo( direction ) {\n                    if ( lbNavigating ) return;\n                    lbNavigating = true;\n                    showLbImage( lbCurrentIdx + direction );\n                    if ( lbTransition !== 'slide' ) setTimeout(function () { lbNavigating = false; }, lbTransSpeed + 50);\n                }\n\n                function closeLightbox() {\n                    lbWrap.style.display = 'none';\n                    lbImg.src = '';\n                    document.body.style.overflow = '';\n                    stopLbSlideshow();\n                    pauseSlider();\n                    setTimeout(function () { resumeSlider(); }, 300);\n                }\n\n                function startLbSlideshow() {\n                    stopLbSlideshow();\n                    lbSlideTimer = setInterval(function () { lbNavigateTo( 1 ); }, lbSlideSpeed);\n                    lbIsPlaying = true;\n                    if ( lbPlay ) { lbPlay.textContent = '\u23f8'; lbPlay.setAttribute('aria-pressed', 'true'); lbPlay.setAttribute('aria-label', 'Arr\u00eater le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'block';\n                    resetLbProgressBar();\n                }\n\n                function stopLbSlideshow() {\n                    if ( lbSlideTimer ) { clearInterval( lbSlideTimer ); lbSlideTimer = null; }\n                    lbIsPlaying = false;\n                    if ( lbPlay ) { lbPlay.textContent = '\u25b6'; lbPlay.setAttribute('aria-pressed', 'false'); lbPlay.setAttribute('aria-label', 'Lancer le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'none';\n                    if ( lbProgress ) { lbProgress.style.transition = 'none'; lbProgress.style.width = '0%'; }\n                }\n\n                function resetLbProgressBar() {\n                    if ( ! lbIsPlaying || ! lbProgress ) return;\n                    lbProgress.style.transition = 'none'; lbProgress.style.width = '0%';\n                    requestAnimationFrame(function () {\n                        requestAnimationFrame(function () {\n                            lbProgress.style.transition = 'width ' + ( lbSlideSpeed \/ 1000 ) + 's linear';\n                            lbProgress.style.width = '100%';\n                        });\n                    });\n                }\n\n                slots.forEach(function ( slot, slotIndex ) {\n                    slot.addEventListener('click', function () {\n                        var clickedIndex = ( currentIndex + slotIndex ) % slides.length;\n                        pauseSlider();\n                        openLightbox( clickedIndex );\n                    });\n                });\n\n                if ( lbClose )   lbClose.addEventListener('click', closeLightbox);\n                if ( lbOverlay ) lbOverlay.addEventListener('click', closeLightbox);\n                if ( lbPrev )    lbPrev.addEventListener('click', function () { lbNavigateTo( -1 ); });\n                if ( lbNext )    lbNext.addEventListener('click', function () { lbNavigateTo(  1 ); });\n\n                document.addEventListener('keydown', function ( e ) {\n                    if ( lbWrap.style.display !== 'flex' ) return;\n                    if ( e.key === 'Escape'     ) closeLightbox();\n                    if ( e.key === 'ArrowLeft'  ) lbNavigateTo( -1 );\n                    if ( e.key === 'ArrowRight' ) lbNavigateTo(  1 );\n                });\n\n                if ( lbPlay ) {\n                    lbPlay.addEventListener('click', function () {\n                        lbIsPlaying ? stopLbSlideshow() : startLbSlideshow();\n                    });\n                }\n\n                var lbSpeeds  = [ 2000, 4000, 6000 ];\n                var lbSpeedLb = [ '2s', '4s', '6s' ];\n                if ( lbSpeedBtn ) {\n                    lbSpeedBtn.addEventListener('click', function () {\n                        var idx = ( lbSpeeds.indexOf( lbSlideSpeed ) + 1 ) % lbSpeeds.length;\n                        lbSlideSpeed = lbSpeeds[ idx ];\n                        lbSpeedBtn.textContent = lbSpeedLb[ idx ];\n                        if ( lbIsPlaying ) startLbSlideshow();\n                    });\n                }\n\n                var lbSwipeStartX = 0, lbSwipeHandled = false;\n                if ( lbImg ) {\n                    lbImg.addEventListener('touchstart', function ( e ) {\n                        lbSwipeStartX = e.changedTouches[0].screenX; lbSwipeHandled = false;\n                    }, { passive: true });\n                    lbImg.addEventListener('touchend', function ( e ) {\n                        if ( lbSwipeHandled ) return;\n                        var diff = lbSwipeStartX - e.changedTouches[0].screenX;\n                        if ( Math.abs(diff) > 40 ) { lbSwipeHandled = true; lbNavigateTo( diff > 0 ? 1 : -1 ); }\n                    }, { passive: true });\n                }\n\n                window.addEventListener('resize',            updateMobileNav);\n                window.addEventListener('orientationchange', updateMobileNav);\n\n            } \/\/ fin if(lightbox)\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TEXTES \u2014 buildTextHtml() et updateTextSlot()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            \/\/ \u2500\u2500 buildTextHtml(slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Construit le HTML des textes pour un slide donn\u00e9.\n            \/\/ Les styles CSS sont inject\u00e9s par PHP (esc_js) au rendu de la page\n            \/\/ \u2192 ils sont des constantes, pas des donn\u00e9es utilisateur.\n            \/\/ Les valeurs slide.title etc. sont d\u00e9j\u00e0 esc_html() c\u00f4t\u00e9 PHP\n            \/\/ \u2192 safe pour innerHTML.\n            function buildTextHtml( slide ) {\n                var html = '';\n                if ( showTitle && slide.title ) {\n                    html += '<p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">'\n                          + slide.title + '<\/p>';\n                }\n                if ( showCaption && slide.caption ) {\n                    html += '<p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">'\n                          + slide.caption + '<\/p>';\n                }\n                if ( showAlt && slide.alt ) {\n                    html += '<p class=\"vl-sl-alt\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.alt + '<\/p>';\n                }\n                if ( showDescription && slide.description ) {\n                    html += '<p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.description + '<\/p>';\n                }\n                return html;\n            }\n\n            \/\/ \u2500\u2500 updateTextSlot(slotIndex, slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour overlay ET below d'un slot donn\u00e9 avec les textes du slide.\n            \/\/ Utilis\u00e9 \u00e0 l'initialisation et lors des transitions.\n            function updateTextSlot( slotIndex, slide ) {\n                if ( overlayEls[ slotIndex ] ) {\n                    overlayEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n                if ( belowEls[ slotIndex ] ) {\n                    belowEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ FANT\u00d4MES \u2014 updateGhosts()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            var ghostPeek = false;\n\n            \/\/ \u2500\u2500 updateGhosts() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour les images des fant\u00f4mes selon la position courante.\n            \/\/ Appel\u00e9e apr\u00e8s chaque transition et lors d'un changement via lightbox.\n            \/\/\n            \/\/ Fant\u00f4me gauche = image juste avant currentIndex (boucle circulaire)\n            \/\/ Fant\u00f4me droit  = image juste apr\u00e8s le dernier slot visible\n            \/\/ Si une seule image : les deux fant\u00f4mes montrent la m\u00eame image.\n            function updateGhosts() {\n                if ( ! ghostPeek ) return;\n                var n = slides.length;\n                var prevIdx = n > 1 ? ( currentIndex - 1 + n ) % n : currentIndex;\n                var nextIdx = n > slotCount ? ( currentIndex + slotCount ) % n : currentIndex;\n\n                \/\/ Fade out \u2192 changer src \u2192 fade in \u2014 synchronis\u00e9 avec fadeOutTime du slider\n                var dur = fadeOutTime \/ 1000;\n\n                if ( ghostImgL ) {\n                    ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgL.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgL.src = slides[ prevIdx ].url;\n                        ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgL.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n                if ( ghostImgR ) {\n                    ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgR.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgR.src = slides[ nextIdx ].url;\n                        ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgR.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n            }\n\n            \/\/ Initialisation des fant\u00f4mes au chargement\n            updateGhosts();\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TRANSITION PRINCIPALE \u2014 changeImage()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Cette fonction orchestre la transition de TOUS les slots en m\u00eame temps.\n            \/\/ Elle utilise des setTimeout cha\u00een\u00e9s (pas setInterval) pour \u00e9viter\n            \/\/ les d\u00e9rives de timing.\n            \/\/\n            \/\/ S\u00e9quence pour chaque slot :\n            \/\/   1. Fade OUT de imgActive  (dur\u00e9e: fadeOutTime)\n            \/\/   2. Apr\u00e8s fadeOut : charger imgNext + Fade IN  (dur\u00e9e: fadeInTime)\n            \/\/   3. Apr\u00e8s fadeIn : permuter imgActive \u2194 imgNext (op\u00e9ration instantan\u00e9e)\n            \/\/   4. Attendre displayTime \u2192 lancer le prochain changeImage()\n            \/\/\n            \/\/ currentIndex est avanc\u00e9 au step 3 du DERNIER slot (c === slots.length-1)\n            \/\/ pour \u00e9viter les race conditions avec la lightbox.\n\n            function changeImage() {\n                if ( slides.length < 2 ) return;\n                if ( sliderPaused ) return;\n\n                var nextIndices = [];\n                for ( var c = 0; c < slotCount; c++ ) {\n                    nextIndices.push( ( currentIndex + slotCount + c ) % slides.length );\n                }\n\n                \/\/ Lancer la transition des fant\u00f4mes en m\u00eame temps que les images\n                updateGhosts();\n\n                \/\/ \u2500\u2500 Transition par slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On it\u00e8re sur chaque slot. Les closures setTimeout capturent\n                \/\/ les variables locales (slot, imgActive, imgNext\u2026) par valeur\n                \/\/ gr\u00e2ce aux param\u00e8tres de fonction.\n                slots.forEach(function ( slot, c ) {\n                    var imgActive   = slot.querySelector('.vl-slider-img-active');\n                    var imgNext     = slot.querySelector('.vl-slider-img-next');\n                    var nextSlide   = slides[ nextIndices[c] ];\n                    var slotOverlay = overlayEls[c] || null;\n\n                    \/\/ \u2500\u2500 Step 1 : Fade OUT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    imgActive.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                    imgActive.style.opacity    = 0;\n                    \/\/ L'overlay texte dispara\u00eet en m\u00eame temps que l'image\n                    if ( slotOverlay ) {\n                        slotOverlay.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                        slotOverlay.style.opacity    = 0;\n                    }\n\n                    \/\/ \u2500\u2500 Step 2 : Apr\u00e8s fade OUT \u2192 charger et afficher imgNext \u2500\n                    \/\/ Les param\u00e8tres pass\u00e9s \u00e0 setTimeout \u00e9vitent les probl\u00e8mes\n                    \/\/ de closure (chaque slot a ses propres valeurs captur\u00e9es).\n                    setTimeout(function ( _slot, _imgActive, _imgNext, _nextSlide, _overlay ) {\n\n                        _imgNext.src = _nextSlide.url;\n                        _imgNext.alt = _nextSlide.alt;\n                        void _imgNext.offsetHeight; \/\/ Force reflow \u2192 garantit la transition\n\n                        _imgNext.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                        _imgNext.style.opacity    = 1;\n\n                        \/\/ Mise \u00e0 jour de l'overlay texte avec le contenu du nouveau slide\n                        if ( _overlay ) {\n                            _overlay.innerHTML = buildTextHtml( _nextSlide );\n                            _overlay.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                            _overlay.style.opacity    = 1;\n                        }\n\n                        \/\/ \u2500\u2500 Step 3 : Apr\u00e8s fade IN \u2192 permuter imgActive \u2194 imgNext \u2500\u2500\n                        \/\/ isLast = true pour le dernier slot \u2192 on avance currentIndex ici\n                        setTimeout(function ( isLast ) {\n                            _imgActive.src              = _imgNext.src;\n                            _imgActive.alt              = _imgNext.alt;\n                            _imgActive.style.transition = 'none'; \/\/ Instantan\u00e9\n                            _imgActive.style.opacity    = 1;\n                            _imgNext.style.transition   = 'none';\n                            _imgNext.style.opacity      = 0;\n                            _imgNext.src = ''; \/\/ Lib\u00e8re la m\u00e9moire\n\n                            \/\/ On avance currentIndex une seule fois (au dernier slot)\n                            \/\/ pour \u00e9viter qu'il soit modifi\u00e9 plusieurs fois simultan\u00e9ment\n                            if ( isLast ) {\n                                currentIndex = ( currentIndex + slotCount ) % slides.length;\n                            }\n                        }, fadeInTime, c === slots.length - 1 );\n\n                    }, fadeOutTime, slot, imgActive, imgNext, nextSlide, slotOverlay );\n                }); \/\/ fin slots.forEach\n\n                \/\/ \u2500\u2500 Mise \u00e0 jour des textes \"below\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On les met \u00e0 jour pendant le fadeOut (quand l'ancien slide\n                \/\/ dispara\u00eet), pour un changement invisible.\n                if ( belowEls.length ) {\n                    setTimeout(function () {\n                        nextIndices.forEach(function ( idx, c ) {\n                            if ( belowEls[c] ) {\n                                belowEls[c].innerHTML = buildTextHtml( slides[ idx ] );\n                            }\n                        });\n                    }, fadeOutTime );\n                }\n\n                \/\/ \u2500\u2500 Step 4 : Planifier la prochaine transition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On attend fadeOut + fadeIn (dur\u00e9e totale de la transition)\n                \/\/ puis displayTime avant de lancer le prochain changeImage().\n                setTimeout(function () {\n                    if ( ! sliderPaused ) {\n                        sliderTimer = setTimeout( changeImage, displayTime );\n                    }\n                }, fadeOutTime + fadeInTime );\n\n            } \/\/ fin changeImage()\n\n            \/\/ \u2500\u2500 D\u00e9marrage du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On d\u00e9marre seulement s'il y a plus d'une image ET assez pour\n            \/\/ remplir au moins un \"\u00e9cran\" complet (slotCount).\n            if ( slides.length >= slotCount && slides.length > 1 ) {\n                sliderTimer = setTimeout( changeImage, displayTime );\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ BOUTON TOGGLE \"Afficher les d\u00e9tails\"\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Visible uniquement si text_position=\"below\".\n            \/\/ Au clic : affiche\/masque le bloc vl-slider-below-wrap avec fade.\n            \/\/ Pause le slider quand les textes sont visibles (pour la lisibilit\u00e9).\n\n            var toggleBtn = document.getElementById('vl-slider-inst1-toggle-btn');\n            if ( toggleBtn && belowWrap ) {\n                var textVisible = false;\n                var toggleDelay = 300; \/\/ Dur\u00e9e de la transition CSS opacity en ms\n\n                toggleBtn.addEventListener('click', function () {\n                    textVisible = ! textVisible;\n                    toggleBtn.classList.toggle('active', textVisible);\n                    toggleBtn.setAttribute('aria-pressed', textVisible ? 'true' : 'false');\n                    toggleBtn.querySelector('.vl-sl-btn-label').textContent =\n                        textVisible ? 'Masquer les d\u00e9tails' : 'Afficher les d\u00e9tails';\n                    belowWrap.setAttribute('aria-hidden', textVisible ? 'false' : 'true');\n\n                    if ( textVisible ) {\n                        pauseSlider();\n                        belowWrap.style.display = 'flex'; \/\/ flex pour aligner les blocs c\u00f4te \u00e0 c\u00f4te\n                        belowWrap.style.opacity = '';\n                        requestAnimationFrame(function () {\n                            requestAnimationFrame(function () {\n                                belowWrap.classList.add('vl-sl-texts-visible');\n                            });\n                        });\n                    } else {\n                        \/\/ \u2500\u2500 Fermeture \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                        \/\/ 1. Lance le fade out (retire la classe, CSS prend en charge)\n                        belowWrap.classList.remove('vl-sl-texts-visible');\n                        \/\/ 2. Apr\u00e8s la transition : cacher le bloc + reprendre le slider\n                        setTimeout(function () {\n                            belowWrap.style.display = 'none';\n                            belowWrap.style.opacity = '0';\n                            resumeSlider();\n                        }, toggleDelay );\n                    }\n                });\n            }\n\n        }); \/\/ fin DOMContentLoaded\n    })(); \/\/ fin IIFE\n    <\/script>\n\n    \n\n\n\n<p><strong>Exemple ci-dessus<\/strong><br \/>L\u2019exemple montre mon petit plugin en action. Oui, c\u2019est simple, mais c\u2019est surtout&nbsp;<strong>fonctionnel<\/strong>&nbsp;\u2014 et c\u2019est bien ce qui compte. Pas besoin d\u2019artifices. Et surtout, ne me dites pas :&nbsp;<em>\u00ab Mais \u00e7a existe d\u00e9j\u00e0 en natif ou dans tel plugin ! \u00bb<\/em>\u2026 C\u2019est justement pour \u00e9viter ces solutions encombrantes que je l\u2019ai cr\u00e9\u00e9 !<\/p>\n\n\n\n<p><strong>Interface et \u00e9volutions<\/strong><br \/>L\u2019interface est volontairement simple et intuitive. Un petit effet de&nbsp;<em>\u00ab fade \u00bb<\/em>&nbsp;entre les images. Possibilit\u00e9 d&rsquo;agrandir une image qui passe ou de voir les d\u00e9tails des image sous le d\u00e9filement. Tout cela est bien sur param\u00e9trable dans l&rsquo;admin du slider. Le temps, le temps de la transition, la grandeur sur ordinateur, sur smartphone, la qualit\u00e9&#8230; et j&rsquo;en passe&#8230;<\/p>\n\n\n\n<p><strong>Philosophie et avantages<\/strong><br \/><strong>Aucune interaction avec la base de donn\u00e9es<\/strong>,&nbsp;<strong>aucune biblioth\u00e8que externe<\/strong>,&nbsp;<strong>aucune collecte de donn\u00e9es<\/strong>&nbsp;: mes plugins sont con\u00e7us pour \u00eatre&nbsp;<strong>l\u00e9gers, rapides et stables<\/strong>, sans pubs ni limitations.<br \/><em>Petite exception<\/em>&nbsp;: pour la fonction de notes mais dans la VL galery, j\u2019ai d\u00fb ajouter un stockage local minimal (mais toujours sans d\u00e9pendance lourde ni collecte intrusive). Parce que oui, m\u00eame en restant minimaliste, il faut parfois s\u2019adapter !<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69faf90ac0a60&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69faf90ac0a60\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"941\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-2000x941.png\" alt=\"VL slider de visionlarge.ch\nPlugin de WordPress\" class=\"wp-image-10924\" srcset=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-2000x941.png 2000w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-300x141.png 300w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-150x71.png 150w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-768x361.png 768w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1536x723.png 1536w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-2048x964.png 2048w\" sizes=\"auto, (max-width: 2000px) 100vw, 2000px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Agrandir\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Voici <strong>VL Slider<\/strong> que dor\u00e9navant, vous aurez dans mon site de <strong>visionlarge.ch<\/strong><\/figcaption><\/figure>\n\n\n\n<p><strong>Interface ultra-simple<\/strong><br \/>Son interface est d\u2019une simplicit\u00e9 enfantine :&nbsp;<strong>on copie le shortcode dans l\u2019article, et hop, c\u2019est parti !<\/strong>&nbsp;Pas de configuration compliqu\u00e9e, pas de menu \u00e0 n\u2019en plus finir.<\/p>\n\n\n\n<p><strong>Un r\u00eave (presque) r\u00e9alis\u00e9<\/strong><br \/>J\u2019adorerais pouvoir l\u2019int\u00e9grer directement dans le post principal de la premi\u00e8re page\u2026 mais je crois que WordPress ne le permet pas (ou alors, il faudrait bidouiller le th\u00e8me, et l\u00e0, bonjour les migraines !). Dommage, \u00e7a aurait \u00e9t\u00e9 encore plus pratique.<\/p>\n\n\n\n<p><strong>Pourquoi ce choix ?<\/strong><br \/>Rappel des principes :&nbsp;<strong>pas de base de donn\u00e9es sollicit\u00e9e<\/strong>,&nbsp;<strong>pas de biblioth\u00e8ques externes<\/strong>,&nbsp;<strong>pas de collecte de donn\u00e9es<\/strong>. Juste un outil l\u00e9ger, rapide et sans prise de t\u00eate. M\u00eame la fonction de notes, qui n\u00e9cessite un stockage local minimal, reste dans cette philosophie :&nbsp;<strong>le strict n\u00e9cessaire, sans fioritures<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>VL Galery<\/strong><\/h3>\n\n\n\n<p><strong>VL Galerie le rempla\u00e7ant simple et gratuit d\u2019Envira Gallery<\/strong><\/p>\n\n\n\n<p><strong>Une version cibl\u00e9e, pas un monstre tout-en-un<\/strong><br \/>C\u2019est une autre version de mon plugin. J\u2019aurais pu tout int\u00e9grer dans un seul\u2026 mais \u00e0 force d\u2019ajouter des fonctionnalit\u00e9s, le code devient trop compliqu\u00e9 \u00e0 g\u00e9rer. D\u2019ailleurs,&nbsp;<strong>c\u2019est en partant de celui-ci que j\u2019ai d\u00e9velopp\u00e9 VL Slider<\/strong>.<\/p>\n\n\n\n<p><strong>Pourquoi ce plugin ?<\/strong><br \/>Son but est clair :&nbsp;<strong>remplacer Envira Gallery<\/strong>&nbsp;sans ses lourdeurs. Il permet d\u2019afficher vos images&nbsp;<strong>en grand<\/strong>&nbsp;et d\u2019offrir une&nbsp;<strong>visualisation propre et efficace<\/strong>&nbsp;de vos galeries.<\/p>\n\n\n<div class=\"vl-galerie-wrapper\"><div class=\"vl-toggle-texts-sticky-wrap\"><button class=\"vl-toggle-texts-button\" data-galerie-id=\"vl-galerie-2\" aria-pressed=\"false\" aria-label=\"Afficher les d\u00e9tails\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8z\"><\/path><circle cx=\"12\" cy=\"12\" r=\"3\"><\/circle><\/svg><span class=\"vl-btn-label\">Afficher les d\u00e9tails<\/span><\/button><\/div><div class=\"vl-galerie layout-masonry\" id=\"vl-galerie-2\" role=\"list\" aria-label=\"Galerie d'images\" data-transition=\"fade\" data-transition-speed=\"1500\" data-hint-duration=\"5000\" data-shop=\"true\" style=\"grid-template-columns: repeat(3, 1fr);\"><div class=\"vl-galerie-item\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10812\" data-title=\"Arc-en-Ciel\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Arc-en-Ciel_Sept_2025-scaled.jpg\" data-alt=\"Arc-en-ciel apr\u00e8s l&#039;orage. Prise de mon balcon ;-) Des oiseaux passent dans le sillage de l&#039;arc-en-ciel.\" data-title=\"Arc-en-Ciel\" data-description=\"Arc-en-ciel apr\u00e8s l&#039;orage. Prise de mon balcon ;-) Des oiseaux passent dans le sillage de l&#039;arc-en-ciel.\" data-id=\"10812\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Arc-en-ciel apr\u00e8s l&#039;orage. Prise de mon balcon ;-) Des oiseaux passent dans le sillage de l&#039;arc-en-ciel.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Arc-en-Ciel_Sept_2025-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Arc-en-Ciel_Sept_2025-205x300.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Arc-en-Ciel_Sept_2025-1365x2000.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Arc-en-ciel apr\u00e8s l&#039;orage. Prise de mon balcon ;-) Des oiseaux passent dans le sillage de l&#039;arc-en-ciel.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Arc-en-Ciel<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon 70-200 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Arc-en-ciel apr\u00e8s l'orage. Prise de mon balcon \ud83d\ude09\nDes oiseaux passent dans le sillage de l'arc-en-ciel. <\/div><\/div><\/div><div class=\"vl-galerie-item\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10879\" data-title=\"Cygne au cr\u00e9puscule\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/CygneAuCrepusculeOct2025-scaled.jpg\" data-alt=\"Un cygne fait le beau sur le lac de Neuch\u00e2tel au cr\u00e9puscule. Plage d&#039;Yverdon-les-Bains en 2025\" data-title=\"Cygne au cr\u00e9puscule\" data-description=\"Un cygne fait le beau sur le lac de Neuch\u00e2tel au cr\u00e9puscule. Plage d\u2019Yverdon-les-Bains, 2025.\" data-id=\"10879\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Un cygne fait le beau sur le lac de Neuch\u00e2tel au cr\u00e9puscule. Plage d&#039;Yverdon-les-Bains en 2025\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/CygneAuCrepusculeOct2025-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/CygneAuCrepusculeOct2025-205x300.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/CygneAuCrepusculeOct2025-1365x2000.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Un cygne fait le beau sur le lac de Neuch\u00e2tel au cr\u00e9puscule. Plage d&#039;Yverdon-les-Bains en 2025\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Cygne au cr\u00e9puscule<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon RF 70-200 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Un cygne fait le beau sur le lac de Neuch\u00e2tel au cr\u00e9puscule. Plage d\u2019Yverdon-les-Bains, 2025.<\/div><\/div><\/div><div class=\"vl-galerie-item\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10906\" data-title=\"Lumi\u00e8re d&rsquo;automne\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/NatureDansLaLumiere-scaled.jpg\" data-alt=\"Dans la nature dor\u00e9e de la lumi\u00e8re d&#039;automne. Au bord de la rivi\u00e8re l&#039;Orbe \u00e0 Orbe.\" data-title=\"Lumi\u00e8re d&rsquo;automne\" data-description=\"Dans la nature dor\u00e9e par la lumi\u00e8re d\u2019automne, au bord de la rivi\u00e8re l\u2019Orbe, \u00e0 Orbe.\" data-id=\"10906\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Dans la nature dor\u00e9e de la lumi\u00e8re d&#039;automne. Au bord de la rivi\u00e8re l&#039;Orbe \u00e0 Orbe.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/NatureDansLaLumiere-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/NatureDansLaLumiere-300x205.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/NatureDansLaLumiere-2000x1365.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Dans la nature dor\u00e9e de la lumi\u00e8re d&#039;automne. Au bord de la rivi\u00e8re l&#039;Orbe \u00e0 Orbe.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Lumi\u00e8re d&rsquo;automne<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon 70-200 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Dans la nature dor\u00e9e par la lumi\u00e8re d\u2019automne,\nau bord de la rivi\u00e8re l\u2019Orbe, \u00e0 Orbe.<\/div><\/div><\/div><div class=\"vl-galerie-item\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"11365\" data-title=\"Dans les rues de S\u00e9ville\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/SevilleHasselbladProfil-scaled.jpg\" data-alt=\"Un moment de vie dans les rues color\u00e9es de la ville de S\u00e9ville en Espagne. Ici, j&#039;ai utilis\u00e9 un de mes presets de simulation de film. Je trouve qu&#039;il fonctionne bien avec les belles couleurs des maisons de S\u00e9ville.\" data-title=\"Dans les rues de S\u00e9ville\" data-description=\"Un moment de vie dans les rues color\u00e9es de S\u00e9ville, en Espagne. J\u2019ai utilis\u00e9 ici l\u2019un de mes presets de simulation de film, qui fonctionne particuli\u00e8rement bien avec les belles couleurs des maisons s\u00e9villanes.\" data-id=\"11365\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Un moment de vie dans les rues color\u00e9es de la ville de S\u00e9ville en Espagne. Ici, j&#039;ai utilis\u00e9 un de mes presets de simulation de film. Je trouve qu&#039;il fonctionne bien avec les belles couleurs des maisons de S\u00e9ville.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/SevilleHasselbladProfil-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/SevilleHasselbladProfil-300x205.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/SevilleHasselbladProfil-2000x1365.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Un moment de vie dans les rues color\u00e9es de la ville de S\u00e9ville en Espagne. Ici, j&#039;ai utilis\u00e9 un de mes presets de simulation de film. Je trouve qu&#039;il fonctionne bien avec les belles couleurs des maisons de S\u00e9ville.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Dans les rues de S\u00e9ville<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS M et objectifs du kit EFM<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Un moment de vie dans les rues color\u00e9es de S\u00e9ville, en Espagne. J\u2019ai utilis\u00e9 ici l\u2019un de mes presets de simulation de film, qui fonctionne particuli\u00e8rement bien avec les belles couleurs des maisons s\u00e9villanes.<\/div><\/div><\/div><div class=\"vl-galerie-item\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10750\" data-title=\"Mont-Blanc\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-SoldatsBW-1-scaled.png\" data-alt=\"Le statues des soldats de Chamonix devant la pointe du midi et le Mont-Blanc.\" data-title=\"Mont-Blanc\" data-description=\"La statue des soldats \u00e0 Chamonix, devant la pointe du Midi et le Mont-Blanc.\" data-id=\"10750\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Le statues des soldats de Chamonix devant la pointe du midi et le Mont-Blanc.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-SoldatsBW-1-scaled.png\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-SoldatsBW-1-300x205.png\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-SoldatsBW-1-2000x1365.png\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Le statues des soldats de Chamonix devant la pointe du midi et le Mont-Blanc.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Mont-Blanc<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon RF 24-105 F4 L IS <\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">La statue des soldats \u00e0 Chamonix, devant la pointe du Midi et le Mont-Blanc.<\/div><\/div><\/div><div class=\"vl-galerie-item\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10748\" data-title=\"Le Brevent\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-86-scaled.jpg\" data-alt=\"En partance pour le sommet avec le t\u00e9l\u00e9ph\u00e9rique du Br\u00e9vent, \u00e0 Chamonix-Mont-Blanc. Depuis ce sommet, on se retrouve face au Mont-Blanc.\" data-title=\"Le Brevent\" data-description=\"En partance pour le sommet avec le t\u00e9l\u00e9ph\u00e9rique du Brevent \u00e0 Chamonix-Mont-Blanc. Depuis ce sommet, on se retrouve en face du Mont-Blanc.\" data-id=\"10748\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : En partance pour le sommet avec le t\u00e9l\u00e9ph\u00e9rique du Br\u00e9vent, \u00e0 Chamonix-Mont-Blanc. Depuis ce sommet, on se retrouve face au Mont-Blanc.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-86-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-86-300x205.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-86-2000x1365.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"En partance pour le sommet avec le t\u00e9l\u00e9ph\u00e9rique du Br\u00e9vent, \u00e0 Chamonix-Mont-Blanc. Depuis ce sommet, on se retrouve face au Mont-Blanc.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Le Brevent<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon 24-105 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">En partance pour le sommet avec le t\u00e9l\u00e9ph\u00e9rique du Brevent \u00e0 Chamonix-Mont-Blanc.\nDepuis ce sommet, on se retrouve en face du Mont-Blanc.<\/div><\/div><\/div><div class=\"vl-galerie-item vl-item-hidden\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10796\" data-title=\"Les piques du midi\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-84-Pano-scaled.jpg\" data-alt=\"Les pointes de... Beuhh... C&#039;est celle qui sont \u00e0 c\u00f4t\u00e9 du Mont-Blanc! Un parapentes volent pr\u00e8s de ses magnifiques montagnes.\" data-title=\"Les piques du midi\" data-description=\"Les pointes de... Beuhh... C&#039;est celle qui sont \u00e0 c\u00f4t\u00e9 du Mont-Blanc! Un parapente vol pr\u00e8s de ses magnifiques montagnes.\" data-id=\"10796\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Les pointes de... Beuhh... C&#039;est celle qui sont \u00e0 c\u00f4t\u00e9 du Mont-Blanc! Un parapentes volent pr\u00e8s de ses magnifiques montagnes.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-84-Pano-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-84-Pano-300x157.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-84-Pano-2000x1047.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Les pointes de... Beuhh... C&#039;est celle qui sont \u00e0 c\u00f4t\u00e9 du Mont-Blanc! Un parapentes volent pr\u00e8s de ses magnifiques montagnes.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Les piques du midi<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon RF 24-105 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Les pointes de... Beuhh... C'est celle qui sont \u00e0 c\u00f4t\u00e9 du Mont-Blanc! Un parapente vol pr\u00e8s de ses magnifiques montagnes.<\/div><\/div><\/div><div class=\"vl-galerie-item vl-item-hidden\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10775\" data-title=\"Mont-Blanc\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-53-scaled.jpg\" data-alt=\"Le massif du Mont-blanc au d\u00e9but de l&#039;automne. Les arbres commencent \u00e0 rev\u00eatir leur couleurs de l&#039;automne.\" data-title=\"Mont-Blanc\" data-description=\"Le massif du Mont-Blanc au d\u00e9but de l&#039;automne. Les arbres commencent \u00e0 rev\u00eatir leurs couleurs d&#039;automne.\" data-id=\"10775\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Le massif du Mont-blanc au d\u00e9but de l&#039;automne. Les arbres commencent \u00e0 rev\u00eatir leur couleurs de l&#039;automne.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-53-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-53-300x157.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-53-2000x1047.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Le massif du Mont-blanc au d\u00e9but de l&#039;automne. Les arbres commencent \u00e0 rev\u00eatir leur couleurs de l&#039;automne.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Mont-Blanc<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon RF 24-105 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Le massif du Mont-Blanc au d\u00e9but de l'automne.\nLes arbres commencent \u00e0 rev\u00eatir leurs couleurs d'automne.<\/div><\/div><\/div><div class=\"vl-galerie-item vl-item-hidden\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10747\" data-title=\"Aiguille verte\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-82-Panorama-scaled.jpg\" data-alt=\"Un parapente passe pr\u00e8s de l\u2019aiguille verte. L\u2019ensemble devient une vraie carte postale. Un instant magique dans ce cadre incroyable.\" data-title=\"Aiguille verte\" data-description=\"Un parapente passe pr\u00e8s de l\u2019Aiguille Verte. L\u2019ensemble devient une vraie carte postale. Un instant magique dans ce cadre incroyable.\" data-id=\"10747\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Un parapente passe pr\u00e8s de l\u2019aiguille verte. L\u2019ensemble devient une vraie carte postale. Un instant magique dans ce cadre incroyable.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-82-Panorama-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-82-Panorama-300x157.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-82-Panorama-2000x1047.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Un parapente passe pr\u00e8s de l\u2019aiguille verte. L\u2019ensemble devient une vraie carte postale. Un instant magique dans ce cadre incroyable.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Aiguille verte<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon RF 24-105 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Un parapente passe pr\u00e8s de l\u2019Aiguille Verte. L\u2019ensemble devient une vraie carte postale. Un instant magique dans ce cadre incroyable.<\/div><\/div><\/div><div class=\"vl-galerie-item vl-item-hidden\" role=\"listitem\" style=\"position:relative;\"><button class=\"vl-select-btn\" data-id=\"10746\" data-title=\"Rochers de Fiz\" data-galerie-id=\"vl-galerie-2\" aria-label=\"Ajouter au panier\">\ud83d\uded2<\/button><a href=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-Panorama-scaled.jpg\" data-alt=\"Rochers de Fiz avec tout au fond \u00e0 gauche, en petit, le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.\" data-title=\"Rochers de Fiz\" data-description=\"Rochers de Fiz avec tout au fond \u00e0 gauche en petit le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.\" data-id=\"10746\" class=\"vl-galerie-link\" role=\"button\" aria-label=\"Ouvrir : Rochers de Fiz avec tout au fond \u00e0 gauche, en petit, le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.\"><img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-Panorama-scaled.jpg\" data-src-medium=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-Panorama-300x124.jpg\" data-src-large=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/ChamonixFrance2025-42-Panorama-2000x826.jpg\" class=\"vl-img-galerie vl-load-effect-popin vl-effect-rotate\" alt=\"Rochers de Fiz avec tout au fond \u00e0 gauche, en petit, le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.\" loading=\"lazy\"><\/a><div class=\"vl-image-texts\" data-galerie-id=\"vl-galerie-2\" aria-hidden=\"true\" style=\"font-style: normal; font-weight: normal;\"><p class=\"vl-text-title\" style=\"font-weight: bold; font-style: normal;\">Rochers de Fiz<\/p><p class=\"vl-text-caption\" style=\"color: #666; font-style: italic; font-weight: normal;\">Canon EOS R, Canon 24-105 F4 L IS<\/p><div class=\"vl-text-description\" style=\"font-size: 12px; color: #444; font-style: normal; font-weight: normal;\">Rochers de Fiz avec tout au fond \u00e0 gauche en petit le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.<\/div><\/div><\/div><\/div><div class=\"vl-voir-plus-wrap\"><button class=\"vl-voir-plus-btn\" data-step=\"6\" data-total=\"10\" data-visible=\"6\" data-galerie-id=\"vl-galerie-2\" data-load-effect=\"popin\">Voir plus (6 sur 10)<\/button><\/div><div class=\"vl-panier-wrap\" id=\"vl-panier-vl-galerie-2\" style=\"display:none;\" data-email=\"aW5mb0B2aXNpb25sYXJnZS5jaA==\" data-galerie-id=\"vl-galerie-2\"><div class=\"vl-panier-header\"><span class=\"vl-panier-titre\">\ud83d\uded2 Demande de prix ou information \u2014 <span class=\"vl-panier-count\">0<\/span> image(s) s\u00e9lectionn\u00e9e(s)<\/span><button class=\"vl-panier-clear\">Tout d\u00e9s\u00e9lectionner<\/button><\/div><div class=\"vl-panier-liste\"><\/div><button class=\"vl-panier-envoyer\">\u2709\ufe0f Envoyer ta demande par email<\/button><\/div><div class=\"vl-credit\">VL Galery \u2014 visionlarge.ch<\/div><\/div>\n\n\n\n<p>Bon, je dois avouer :&nbsp;<strong>ce n\u2019est pas aussi joli que la galerie d\u2019Envira<\/strong>. Mais c\u2019est&nbsp;<strong>plus sympa que beaucoup d\u2019autres plugins, parfois payants<\/strong>&nbsp;! La position des \u00e9tiquettes fa\u00e7on&nbsp;<em>Masonry<\/em>&nbsp;n\u2019est pas parfaite \u2014 \u00e7a peut parfois se d\u00e9caller un peu. Techniquement, je pourrais r\u00e9cup\u00e9rer le code de Masonry (je crois que la licence le permet), mais&nbsp;<strong>\u00e7a m\u2019emb\u00eate que mon plugin d\u00e9pende d\u2019un code \u00e0 distance<\/strong>. Donc pour l\u2019instant, je reste sur une solution 100 % locale<\/p>\n\n\n\n<p>Comme l&rsquo;autre plugin, l&rsquo;interface est simple. C&rsquo;est presque la m\u00eame \ud83d\ude09<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69faf90ac10f7&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69faf90ac10f7\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"828\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-2000x828.png\" alt=\"VL Galerie Perso de visionlarge.ch\nPlugin de WordPress\" class=\"wp-image-10937\" srcset=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-2000x828.png 2000w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-300x124.png 300w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-150x62.png 150w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-768x318.png 768w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-1536x636.png 1536w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.30.36-2048x848.png 2048w\" sizes=\"auto, (max-width: 2000px) 100vw, 2000px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Agrandir\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Voici <strong>VL Galerie Perso<\/strong> que dor\u00e9navant, vous aurez dans mon site de <strong>visionlarge.ch<\/strong><\/figcaption><\/figure>\n\n\n\n<p><strong>Une interface ultra-simple<\/strong><br \/>Comme mon autre plugin, l\u2019interface est&nbsp;<strong>volontairement simple<\/strong>&nbsp;\u2014 c\u2019est presque la m\u00eame, d\u2019ailleurs ! Le principe ?<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Vous ajoutez vos images.<\/li>\n\n\n\n<li>Vous pouvez modifier certains param\u00e8tres :&nbsp;<strong>nombre de colonnes, qualit\u00e9, effet au survol, disposition et m\u00eame la transition<\/strong>&nbsp;(oui, celui-ci a bien le&nbsp;<em>fade<\/em>&nbsp;!).<\/li>\n\n\n\n<li>Vous copiez le shortcode dans votre article.<\/li>\n\n\n\n<li><strong>Et voil\u00e0, c\u2019est pr\u00eat !<\/strong><\/li>\n<\/ol>\n\n\n\n<p><strong>Un avenir sans d\u00e9pendances<\/strong><br \/>Gentiment mais s\u00fbrement,&nbsp;<strong>mes galeries vont remplacer les solutions externes<\/strong>&nbsp;\u2014 et le meilleur ?&nbsp;<strong>Mes plugins sont gratuits et seront disponibles tr\u00e8s bient\u00f4t<\/strong>.<\/p>\n\n\n\n<p>Afin d&rsquo;\u00eatre \u00e0 jour sur mes modifications, je met ci-dessous mes am\u00e9liorations sur mon readme.txt.<\/p>\n\n\n\n<p><strong>VL Galerie<\/strong>&nbsp;est un plugin WordPress l\u00e9ger et performant, sp\u00e9cialement con\u00e7u pour cr\u00e9er des galeries d\u2019images \u00e9l\u00e9gantes et responsives. Il offre une&nbsp;<strong>lightbox moderne<\/strong>, des&nbsp;<strong>effets de transition fluides<\/strong>&nbsp;et une&nbsp;<strong>optimisation mobile<\/strong>, le tout (j&rsquo;esp\u00e8re) sans alourdir votre site.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Fonctionnalit\u00e9s principales<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Galeries d\u2019images<\/strong>&nbsp;: Prise en charge des formats JPG, PNG, etc.&nbsp;<em>(Le support vid\u00e9o a \u00e9t\u00e9 retir\u00e9 pour all\u00e9ge le plugin.)<\/em><\/li>\n\n\n\n<li><strong>Lightbox \u00e9l\u00e9gante<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Navigation tactile (<em>swipe<\/em>&nbsp;sur mobile).<\/li>\n\n\n\n<li>Transitions personnalisables (<em>fade<\/em>,&nbsp;<em>slide, zooo, popin ou rotation<\/em>).<\/li>\n\n\n\n<li>Diaporama automatique avec un&nbsp;<strong>compteur d\u2019images int\u00e9gr\u00e9<\/strong>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Effets visuels au survol<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Zoom, ombre, d\u00e9calage,&nbsp;<em>pop-in<\/em>&nbsp;ou rotation.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Dispositions flexibles<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Grille classique ou serr\u00e9e (<em>sans espaces inutiles<\/em>).<\/li>\n\n\n\n<li>Tri automatique des images selon leur ratio (paysage, portrait, carr\u00e9, panorama).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>100 % responsive<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Adaptation parfaite aux smartphones et tablettes.<\/li>\n\n\n\n<li>Masquage intelligent des fl\u00e8ches en mode portrait.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Personnalisation des l\u00e9gendes<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Affichage optionnel du texte issu de l\u2019attribut&nbsp;<em>Alt<\/em>, de la d\u00e9signation, de la l\u00e9gende ou du titre.<\/li>\n\n\n\n<li>Bouton pour masquer les l\u00e9gendes c\u00f4t\u00e9 visiteur.<\/li>\n\n\n\n<li>Contr\u00f4le admin pour choisir ce qui s\u2019affiche.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Interactions utilisateur<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Syst\u00e8me de notation des images.<\/li>\n\n\n\n<li>Possibilit\u00e9 d\u2019envoyer une demande via les images marqu\u00e9es en favori.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Shortcode intuitif<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>G\u00e9n\u00e9ration via une interface admin simple (glisser-d\u00e9poser, aper\u00e7u en temps r\u00e9el).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Optimis\u00e9 pour les performances<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Chargement&nbsp;<em>lazy<\/em>&nbsp;des images.<\/li>\n\n\n\n<li>Code ultra-l\u00e9ger pour ne pas ralentir votre site.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u00c0 quoi sert VL Galerie ?<\/strong><\/h3>\n\n\n\n<p>Ce plugin est id\u00e9al pour :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Les portfolios d\u2019images<\/strong>&nbsp;(artistes, photographes).<\/li>\n\n\n\n<li><strong>Les galeries d\u2019\u00e9v\u00e9nements<\/strong>&nbsp;(mariages, concerts, expositions).<\/li>\n\n\n\n<li><strong>La pr\u00e9sentation de produits<\/strong>&nbsp;(sites e-commerce).<\/li>\n\n\n\n<li><strong>L\u2019int\u00e9gration de contenus multim\u00e9dias<\/strong>&nbsp;sans impact sur les performances.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Pourquoi choisir VL Galerie ?<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Aucune d\u00e9pendance externe<\/strong>&nbsp;: Pas de biblioth\u00e8ques tierces, pas de collecte de donn\u00e9es.<\/li>\n\n\n\n<li><strong>Gratuit et sans publicit\u00e9<\/strong>&nbsp;: Con\u00e7u pour rester accessible et respectueux de vos visiteurs.<\/li>\n<\/ul>\n\n\n\n<p>== Installation ==<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Via WordPress<\/strong> :<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Allez dans <strong>Extensions &gt; Ajouter<\/strong>, puis t\u00e9l\u00e9versez le fichier ZIP du plugin.<\/li>\n\n\n\n<li>Activez-le dans <strong>Extensions &gt; Extensions install\u00e9es<\/strong>.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Manuellement<\/strong> :<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>D\u00e9compressez le fichier ZIP.<\/li>\n\n\n\n<li>Upload le dossier <code>vl-galerie<\/code> dans <code>\/wp-content\/plugins\/<\/code>.<\/li>\n\n\n\n<li>Activez le plugin via le menu <strong>Extensions<\/strong> de WordPress.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Utilisation<\/strong> :<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Un menu <strong>\u00ab\u00a0VL Galerie Perso\u00a0\u00bb<\/strong> appara\u00eet dans le tableau de bord.<\/li>\n\n\n\n<li>Utilisez l\u2019interface pour <strong>g\u00e9n\u00e9rer un shortcode<\/strong> (ex: <code><div class=\"vl-galerie-wrapper\"><div class=\"vl-galerie layout-masonry\" id=\"vl-galerie-3\" role=\"list\" aria-label=\"Galerie d'images\" data-transition=\"fade\" data-transition-speed=\"800\" data-hint-duration=\"5000\" data-shop=\"true\" style=\"grid-template-columns: repeat(3, 1fr);\"><\/div><div class=\"vl-credit\">VL Galery \u2014 visionlarge.ch<\/div><\/div><\/code>).<\/li>\n\n\n\n<li>Collez le shortcode dans vos articles\/pages.<\/li>\n\n\n\n<li>On peut modifier et le code soit m\u00eame et mettre \u00e0 jour la pr\u00e9-visualisation.<\/li>\n<\/ul>\n\n\n\n<p>== Frequently Asked Questions ==<br \/>= Le plugin ralentit-il mon site ? =<br \/>Non ! Les images sont charg\u00e9es en <strong>lazy loading<\/strong>, et le JavaScript est optimis\u00e9 pour ne se charger <strong>uniquement sur les pages o\u00f9 le shortcode est pr\u00e9sent<\/strong>.<\/p>\n\n\n\n<p>= La lightbox est-elle compatible avec les \u00e9crans tactiles ? =<br \/>Oui ! Le plugin d\u00e9tecte automatiquement les <strong>smartphones\/tablettes<\/strong> et active :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>La navigation par <strong>swipe<\/strong> (glisser le doigt).<\/li>\n\n\n\n<li>Le masquage des fl\u00e8ches en mode portrait pour plus de place \u00e0 l\u2019image.<\/li>\n\n\n\n<li>Un bouton de fermeture agrandi pour faciliter la fermeture.<\/li>\n<\/ul>\n\n\n\n<p>= Puis-je personnaliser les effets de transition ? =<br \/>Oui ! Via le shortcode, choisissez exemple :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>transition=\"fade\"<\/code> (fondu, par d\u00e9faut).<\/li>\n\n\n\n<li><code>transition=\"slide\"<\/code> (gliss\u00e9). (marche pas bien pour l&rsquo;instant&#8230;)<\/li>\n\n\n\n<li><code>transition=\"none\"<\/code> (pas d\u2019effet).<\/li>\n<\/ul>\n\n\n\n<p>= Comment ajouter une l\u00e9gende aux images ? =<br \/>Utilisez le champ <strong>\u00ab\u00a0Texte description\u00a0\u00bb<\/strong> (Alt Text) lors de l\u2019upload de l\u2019image dans WordPress. La l\u00e9gende s\u2019affichera automatiquement dans la lightbox.<\/p>\n\n\n\n<p>== Screenshots ==<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Interface admin<\/strong> : G\u00e9n\u00e9rateur de shortcode avec aper\u00e7u en temps r\u00e9el.<\/li>\n\n\n\n<li><strong>Galerie en style Dense<\/strong> : Disposition sans trous, responsive, bon c&rsquo;est pas la vraie\u2026<\/li>\n\n\n\n<li><strong>Lightbox sur mobile<\/strong> : Navigation tactile et boutons adapt\u00e9s.<\/li>\n\n\n\n<li><strong>Effets au survol<\/strong> : Zoom, ombre, ou d\u00e9calage sur les images.<\/li>\n<\/ol>\n\n\n\n<p><strong>== Changelog ==<\/strong><\/p>\n\n\n\n<p><strong>= 3.5 (27 avril 2026)<\/strong> FINAL<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Correction de divers petits bugs sans trop importance.<br \/>Am\u00e9lioration de la s\u00e9curit\u00e9.<\/li>\n\n\n\n<li>Rajout de la partie \u00ab\u00a0caddy\u00a0\u00bb permettant de cr\u00e9er un formulaire avec les images retenues. Possible de mettre des images dans le caddy depuis la Lightbox, ou depuis la galerie de vignettes. Aide aussi avec un message \u00ab\u00a0bulle\u00a0\u00bb qui dit d&rsquo;aller voir en bas de la galerie<\/li>\n\n\n\n<li>Modification pour que le mail soit cach\u00e9 de la page html pour emp\u00eacher les robots de la voir.<\/li>\n\n\n\n<li>Possibilit\u00e9 de cacher le formulaire de caddy si besoin.<\/li>\n\n\n\n<li>Le formulaire du caddy est globale pour pouvoir changer de galerie si besoin. <\/li>\n\n\n\n<li>Bulle d&rsquo;aide en dessus des param\u00e8tres de l&rsquo;admin. Il faut rester 2s pour que l&rsquo;aide s&rsquo;affiche. Elle contient l&rsquo;explication et le shortcode qui en d\u00e9pend.<\/li>\n\n\n\n<li>Modifications de quelques textes et design.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 3.3 (11 avril 2026)<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Correction du bug sur le fade et slide dans la Lightbox et correction pour qu&rsquo;un mode 1 image, 1 colonne l&rsquo;image soit au milieu sur smartphone et ordinateur. <\/li>\n\n\n\n<li>Am\u00e9lioration de la qualit\u00e9 des vignettes si sous smartphone ou tablette en portrait. Passage de m\u00e9dium \u00e0 large.<\/li>\n\n\n\n<li>Correction des noms de classe qui avaient le m\u00eame nom que dans VL Slider pour la croix de fermeture et le fade. Cela s&rsquo;\u00e9crasait lorsque les deux plugin&rsquo;s \u00e9taient sur la m\u00eame page.<\/li>\n\n\n\n<li>Rajout d&rsquo;une max heigh pour les vignettes, afin d&rsquo;\u00e9viter que si une colonne et une image l&rsquo;image portrait soit tr\u00e8s grande \u00e0 cause de la grille qui fait toute la largeur. Dans l&rsquo;admin.<\/li>\n\n\n\n<li>Rajouter dans l&rsquo;admin le param\u00e8tre du temps pour le fade, le slice. 400ms par d\u00e9faut, 2500ms c&rsquo;est sympa. Max 2000ms<\/li>\n\n\n\n<li>Modification de quelques textes.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 3.2 (20 mars 2026)<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Nouveaut\u00e9s<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Ajout d\u2019un syst\u00e8me de&nbsp;<strong>notation des images<\/strong>.<\/li>\n\n\n\n<li>Possibilit\u00e9 pour les visiteurs de&nbsp;<strong>s\u00e9lectionner des images en favori<\/strong>&nbsp;et d\u2019envoyer une demande (affichage d\u2019un \u00ab\u00a0panier\u00a0\u00bb avec l\u2019ID et le nom de l\u2019image, envoy\u00e9 par email).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 3.1 (2 novembre 2025) =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>S\u00e9curit\u00e9<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Ajout de la&nbsp;<strong>sanitization<\/strong>&nbsp;et des&nbsp;<strong>nonce<\/strong>&nbsp;pour renforcer la s\u00e9curit\u00e9 et \u00e9viter les injections de code malveillant via le shortcode.<\/li>\n\n\n\n<li>Correction de bugs critiques apr\u00e8s plusieurs plantages.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 3.0 (26 octobre 2025) =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Nouveaut\u00e9s<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li><strong>Diaporama automatique<\/strong>&nbsp;avec r\u00e9glage de la vitesse.<\/li>\n\n\n\n<li>D\u00e9tection am\u00e9lior\u00e9e des&nbsp;<strong>appareils mobiles\/tablettes<\/strong>&nbsp;(masquage des fl\u00e8ches en mode portrait).<\/li>\n\n\n\n<li>Nouvelle option&nbsp;<code>layout=\"normal\"<\/code>&nbsp;pour une grille classique (vs serr\u00e9e).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Am\u00e9liorations<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Correction des bugs de compatibilit\u00e9 avec&nbsp;<strong>WordPress 6.2<\/strong>.<\/li>\n\n\n\n<li>Optimisation du&nbsp;<strong>CSS\/JS<\/strong>&nbsp;pour r\u00e9duire la taille des fichiers.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Suppressions<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Retrait du support des vid\u00e9os&nbsp;<strong>YouTube et MP4<\/strong>&nbsp;(trop complexe \u00e0 s\u00e9curiser).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 2.0.8 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Stabilisation<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Version stable des effets de&nbsp;<strong>rotation<\/strong>&nbsp;et de&nbsp;<em>pop-in<\/em>&nbsp;au d\u00e9marrage et au survol.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 2.0 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Nouveaut\u00e9s<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Support des&nbsp;<strong>vid\u00e9os YouTube et MP4<\/strong>&nbsp;dans les galeries.<\/li>\n\n\n\n<li>Effets de transition personnalisables (<em>fade\/slide<\/em>).<\/li>\n\n\n\n<li>Interface admin avec&nbsp;<strong>glisser-d\u00e9poser<\/strong>&nbsp;pour organiser les m\u00e9dias.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 1.5 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Effets visuels<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Ajout d\u2019un effet&nbsp;<em>pop-up<\/em>&nbsp;au chargement de la galerie et au survol des vignettes.<\/li>\n\n\n\n<li>Toujours&nbsp;<strong>100 % CSS<\/strong>, avec un script l\u00e9ger pour le chargement.<\/li>\n\n\n\n<li><strong>Aucune biblioth\u00e8que externe<\/strong>&nbsp;utilis\u00e9e.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 1.4 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Corrections<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Fix des bugs sur le bouton d\u2019affichage des&nbsp;<strong>commentaires (alt, l\u00e9gende, titre)<\/strong>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 1.3 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Personnalisation<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Possibilit\u00e9 d\u2019afficher les&nbsp;<strong>textes de l\u2019image<\/strong>&nbsp;(alt, l\u00e9gende, titre) sous les vignettes.<\/li>\n\n\n\n<li>S\u00e9lection des \u00e9l\u00e9ments \u00e0 afficher via l\u2019<strong>admin<\/strong>.<\/li>\n\n\n\n<li>Bouton pour le visiteur pour&nbsp;<strong>masquer\/afficher les d\u00e9tails<\/strong>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 1.2 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tri automatique<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Correction de bugs et am\u00e9lioration du&nbsp;<strong>tri par ratios<\/strong>&nbsp;(paysage, portrait, carr\u00e9, etc.).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 1.1 =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Nouveaut\u00e9<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Ajout du&nbsp;<strong>tri automatique des images selon leur ratio<\/strong>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>= 1.01 (2 novembre 2025) =<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>S\u00e9curit\u00e9 et UX<\/strong>&nbsp;:\n<ul class=\"wp-block-list\">\n<li>Bloquage du&nbsp;<strong>clic droit<\/strong>&nbsp;et du&nbsp;<strong>glisser-d\u00e9poser<\/strong>&nbsp;sur les images.<\/li>\n\n\n\n<li>Ajout d\u2019un&nbsp;<strong>compteur d\u2019images<\/strong>&nbsp;dans les diaporamas (ex : 1\/24).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>== Upgrade Notice ==<\/strong><\/h3>\n\n\n\n<p><strong>= 3.0+ =<\/strong><br \/>Mise \u00e0 jour&nbsp;<strong>fortement recommand\u00e9e<\/strong>&nbsp;pour :<\/p>\n\n\n\n<p>Les nouvelles fonctionnalit\u00e9s (<strong>diaporama automatique<\/strong>, d\u00e9tection mobile am\u00e9lior\u00e9e, s\u00e9curit\u00e9 renforc\u00e9e).<\/p>\n\n\n\n<p>La compatibilit\u00e9 avec&nbsp;<strong>WordPress 6.0+<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Qu\u2019est-ce qu\u2019un plugin ?Un plugin, c\u2019est un petit programme, g\u00e9n\u00e9ralement \u00e9crit en PHP, qui contient des morceaux de code HTML, des scripts et du CSS. Il permet d\u2019ajouter des fonctionnalit\u00e9s pratiques que WordPress ne propose pas nativement, ou d\u2019exploiter des fonctions sp\u00e9cifiques de WordPress. Les plugins de visualisation de photosIl&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/\">La suite? C&#039;est par l\u00e0!<span class=\"screen-reader-text\">De nouveaux plugin&rsquo;s pour vos images. (et surtout les miennes)<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":10936,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[1169,1170,898,1183,1168,1167],"class_list":["post-10908","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-non-classe","tag-galerie-dimages","tag-php","tag-plugin","tag-plugin-gratuit","tag-vl-galerie","tag-vl-slider","excerpt","zoom","full-without-featured","even","excerpt-0"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>De nouveaux plugin&#039;s pour vos images. (et surtout les miennes) &#8212; Visionlarge.ch<\/title>\n<meta name=\"description\" content=\"Visionlarge.ch\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"De nouveaux plugin&#039;s pour vos images. (et surtout les miennes) &#8212; Visionlarge.ch\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/\" \/>\n<meta property=\"og:site_name\" content=\"Visionlarge.ch\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-11T09:50:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-27T10:38:26+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2206\" \/>\n\t<meta property=\"og:image:height\" content=\"1038\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Visionlarge\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@visionlarge\" \/>\n<meta name=\"twitter:site\" content=\"@visionlarge\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Visionlarge\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/\"},\"author\":{\"name\":\"Visionlarge\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#\\\/schema\\\/person\\\/b1280adcf8dd414efb101660dca80274\"},\"headline\":\"De nouveaux plugin&rsquo;s pour vos images. (et surtout les miennes)\",\"datePublished\":\"2025-10-11T09:50:11+00:00\",\"dateModified\":\"2026-04-27T10:38:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/\"},\"wordCount\":2559,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#\\\/schema\\\/person\\\/b1280adcf8dd414efb101660dca80274\"},\"image\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Capture-decran-2025-10-11-a-13.18.48-1.png\",\"keywords\":[\"galerie d'images\",\"php\",\"plugin\",\"plugin gratuit\",\"vl galerie\",\"vl slider\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/\",\"name\":\"De nouveaux plugin's pour vos images. (et surtout les miennes) &#8212; Visionlarge.ch\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Capture-decran-2025-10-11-a-13.18.48-1.png\",\"datePublished\":\"2025-10-11T09:50:11+00:00\",\"dateModified\":\"2026-04-27T10:38:26+00:00\",\"description\":\"Visionlarge.ch\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Capture-decran-2025-10-11-a-13.18.48-1.png\",\"contentUrl\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Capture-decran-2025-10-11-a-13.18.48-1.png\",\"width\":2206,\"height\":1038},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/de-nouveaux-plugin-s-pour-vos-images\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"De nouveaux plugin&rsquo;s pour vos images. (et surtout les miennes)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#website\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/\",\"name\":\"Bovard Alain, mon blog photo\",\"description\":\"C&#039;est toujours plus beau en visionlarge...\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#\\\/schema\\\/person\\\/b1280adcf8dd414efb101660dca80274\"},\"alternateName\":\"visionlarge\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#\\\/schema\\\/person\\\/b1280adcf8dd414efb101660dca80274\",\"name\":\"Visionlarge\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\",\"caption\":\"Visionlarge\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\"},\"sameAs\":[\"http:\\\/\\\/www.visionlarge.ch\\\/Blog\"],\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/author\\\/abovard\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"De nouveaux plugin's pour vos images. (et surtout les miennes) &#8212; Visionlarge.ch","description":"Visionlarge.ch","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/","og_locale":"fr_FR","og_type":"article","og_title":"De nouveaux plugin's pour vos images. (et surtout les miennes) &#8212; Visionlarge.ch","og_url":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/","og_site_name":"Visionlarge.ch","article_published_time":"2025-10-11T09:50:11+00:00","article_modified_time":"2026-04-27T10:38:26+00:00","og_image":[{"width":2206,"height":1038,"url":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1.png","type":"image\/png"}],"author":"Visionlarge","twitter_card":"summary_large_image","twitter_creator":"@visionlarge","twitter_site":"@visionlarge","twitter_misc":{"\u00c9crit par":"Visionlarge","Dur\u00e9e de lecture estim\u00e9e":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#article","isPartOf":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/"},"author":{"name":"Visionlarge","@id":"https:\/\/www.visionlarge.ch\/Blog\/#\/schema\/person\/b1280adcf8dd414efb101660dca80274"},"headline":"De nouveaux plugin&rsquo;s pour vos images. (et surtout les miennes)","datePublished":"2025-10-11T09:50:11+00:00","dateModified":"2026-04-27T10:38:26+00:00","mainEntityOfPage":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/"},"wordCount":2559,"commentCount":0,"publisher":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/#\/schema\/person\/b1280adcf8dd414efb101660dca80274"},"image":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#primaryimage"},"thumbnailUrl":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1.png","keywords":["galerie d'images","php","plugin","plugin gratuit","vl galerie","vl slider"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/","url":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/","name":"De nouveaux plugin's pour vos images. (et surtout les miennes) &#8212; Visionlarge.ch","isPartOf":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#primaryimage"},"image":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#primaryimage"},"thumbnailUrl":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1.png","datePublished":"2025-10-11T09:50:11+00:00","dateModified":"2026-04-27T10:38:26+00:00","description":"Visionlarge.ch","breadcrumb":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#primaryimage","url":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1.png","contentUrl":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Capture-decran-2025-10-11-a-13.18.48-1.png","width":2206,"height":1038},{"@type":"BreadcrumbList","@id":"https:\/\/www.visionlarge.ch\/Blog\/de-nouveaux-plugin-s-pour-vos-images\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.visionlarge.ch\/Blog\/"},{"@type":"ListItem","position":2,"name":"De nouveaux plugin&rsquo;s pour vos images. (et surtout les miennes)"}]},{"@type":"WebSite","@id":"https:\/\/www.visionlarge.ch\/Blog\/#website","url":"https:\/\/www.visionlarge.ch\/Blog\/","name":"Bovard Alain, mon blog photo","description":"C&#039;est toujours plus beau en visionlarge...","publisher":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/#\/schema\/person\/b1280adcf8dd414efb101660dca80274"},"alternateName":"visionlarge","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.visionlarge.ch\/Blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":["Person","Organization"],"@id":"https:\/\/www.visionlarge.ch\/Blog\/#\/schema\/person\/b1280adcf8dd414efb101660dca80274","name":"Visionlarge","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g","caption":"Visionlarge"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g"},"sameAs":["http:\/\/www.visionlarge.ch\/Blog"],"url":"https:\/\/www.visionlarge.ch\/Blog\/author\/abovard\/"}]}},"_links":{"self":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/posts\/10908","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/comments?post=10908"}],"version-history":[{"count":91,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/posts\/10908\/revisions"}],"predecessor-version":[{"id":12133,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/posts\/10908\/revisions\/12133"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/media\/10936"}],"wp:attachment":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/media?parent=10908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/categories?post=10908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/tags?post=10908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}