WordPress: rendre le shortcode [ gallery] fluide et responsive

Suite des améliorations des shortcodes standards de WordPress, pour les rendre conforme à HTML 5, mais également fluide et responsive. Nous allons traiter maintenant du shortcode [ gallery]

Code généré par le shortcode

Après transformation, le shortcode génère le code HTML suivant:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 <aside id='gallery-x' class='gallery galleryid-xxxx gallery-columns-3 gallery-size-thumbnail'>
    <figure class='gallery-item'>
        <span class='gallery-icon'>
            <a href=""image_1.jpg" title=" ... ... ">
                <img width="100" height="100" src="thumbnail_1.jpg" class="attachment-thumbnail" alt="... ..." title=" ... ... " />
            </a>
        </span>
        <figcaption> ... caption text ... </figcaption>
    </figure>
    <figure class='gallery-item'>
        <span class='gallery-icon'>
            <a href=""image_2.jpg" title=" ... ... ">
                <img width="100" height="100" src="thumbnail_2.jpg" class="attachment-thumbnail" alt="... ..." title=" ... ... " />
            </a>
        </span>
        <figcaption> ... caption text ... </figcaption>
    </figure>
    <br style="clear: both" />
    ... ...
    <figure class='gallery-item'>
        <span class='gallery-icon'>
            <a href=""image_n.jpg" title=" ... ... ">
                <img width="100" height="100" src="thumbnail_n.jpg" class="attachment-thumbnail" alt="... ..." title=" ... ... " />
            </a>
        </span>
        <figcaption> ... caption text ... </figcaption>
    </figure>
    <br style="clear: both" />
</aside>

La balise conteneur est <aside>. Ensuite chaque image est contenue dans une balise <figure>. A noter que le « saut de ligne » est assuré par la balise <br style="clear: both;" />, mais nous y reviendrons.

Le code généré par le shortcode d’origine est assez similaire, et surtout nous disposons des mêmes styles. En effet, contrairement au shortcode [ caption], [ gallery] utilise un grand nombre de styles qui vont nous permettre un meilleur contrôle du format de nos galeries. Nous avons notamment

  • gallery-columns-x (x nombre de colonnes),
  • gallery-size-xxx (taille des vignettes, thumbnail, medium, large, full).

Fluidité

En pratique, le shortcode [ gallery] est déjà en grande partie « fluide », puisque le shortcode génère des styles CSS de ce type:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style type='text/css'>
    #{$gallery-xx} {
        margin: auto;
    }
    #{$gallery-xx} .gallery-item {
        float: left;
        margin-top: 10px;
        text-align: center;
        width: {$itemwidth}%;
    }
    #{$gallery-xx} img {
        border: 2px solid #cfcfcf;
    }
    #{$gallery-xx} .gallery-caption {
        margin-left: 0;
    }
</style>

xx est un numéro d’instance (1, 2, …), et itemwidth est le résultat du calcul 100/nombre de colonnes.

Ces styles posent plusieurs problèmes:

  • d’abord, ils sont générés au milieu du code HTML, ce qui n’est pas très propre,
  • ensuite, ils apparaissent au-dessus de chaque galerie, ce qui alourdit les pages,
  • la balise img n’est pas fluide,
  • pour finir, les styles sont assez basiques, notamment pour la balise img.

Etape 1: Supprimer les styles « embarqués »

WordPress nous donne la possibilité de modifier ces styles, grâce au filtre gallery_style, mais la méthode la plus « propre » (et la plus simple finalement), et de les supprimer, pour pouvoir les ajouter à la feuille de styles du thème.

La suppression des styles s’effectue en plaçant le code suivant dans le fichier functions.php du thème:

1
add_filter('use_default_gallery_style', create_function('','return FALSE;'));

Etape 2: Mettre en place nos styles

Nous pouvons maintenant gérer nos propres styles, dans le fichier style.css, avec par exemple:

 aside.gallery {
    width: 90%;
    margin: 0 auto;
}
 
figure.gallery-item {
    float: left;
    margin: 2em 2%;
    text-align: center;
}
 
.gallery-columns-2 figure.gallery-item { width: 46%; }
.gallery-columns-3 figure.gallery-item { width: 29%; }
.gallery-columns-4 figure.gallery-item { width: 21%; }
.gallery-columns-5 figure.gallery-item { width: 16%; }
 
span.gallery-icon img {
    max-width: 100%;
    width: auto;
    height: auto;
    border: 1px solid #333;
    padding: 4%;
}
 
figcaption.gallery-caption {
    padding: 0.5em 2%;
}

Ces différentes opérations nous conduisent à une galerie de ce type. La galerie est fluide, puisque si nous réduisons la fenêtre, nous avons ceci.

Galerie fluide pleine largeur
Galerie fluide, largeur réduite

Responsive

Même si notre galerie est fluide, tous les problèmes ne sont pas réglés pour autant. En effet, en dessous d’une certaine résolution, la galerie n’est plus très élégante ou très lisible.

L’idée pourrait être de modifier dynamiquement le nombre de colonnes: une galerie de trois colonnes au départ, peut passer à 2 colonnes lorsque la largeur devient insuffisante.

Solution 1: Utiliser les media-queries

Les media-queries sont faites pour cela. Tout en conservant les styles déjà décrits précédemment, nous pouvons ajouter, par exemple :

@media only screen and (max-width: 480px) {
    aside.gallery-columns-3 figure.gallery-item { width: 46%; }
    aside.gallery-columns-4 figure.gallery-item { width: 29%; }
    aside.gallery-columns-5 figure.gallery-item { width: 21%; }
}

Lorsque la largeur n’est plus suffisante, en modifiant la largeur des éléments, nous réduisons le nombre de colonnes. Par exemple, dans le premier cas, les galeries de 3 colonnes, passent à 2 colonnes.

Dans notre exemple, nous obtenons bien 2 colonnes, mais nous perdons l’alignement.

Galerie responsive: Solution 1

Le shortcode par défaut ajoute une balise <br style="clear: both;" />  à chaque fin de ligne. Par exemple, si une galerie comporte 3 colonnes, la balise apparaîtra tous les trois éléments <figure>. Donc même si nous transformons nos galeries de 3 colonnes en galeries de 2 colonnes avec CSS, les balises <br />, elles, ne bougent pas.

Etape 2: Supprimer les balises <br />

Nous allons donc modifier le shortcode, pour supprimer les balises <br style="clear: both;" />. Nous allons revenir, pour cela, à la fonction écrite dans l’article précédent.

1
2
3
4
5
6
7
8
9
10
11
function my_own_gallery_shortcode($attr) {
    // Generate the HTML code
    $attr['itemtag'] = 'figure';
    $attr['icontag']   = 'span';
    $attr['captiontag'] = 'figcaption';
 
    return ( str_replace('<br style="clear: both;" />', '', gallery_shortcode($attr) ) );
 
} // End of function new_gallery_shortcode
remove_shortcode('gallery');
add_shortcode('gallery', 'my_own_gallery_shortcode');

Résultat: tout va bien lorsque nous commutons sur deux colonnes, les alignements sont préservés. Mais en mode 3 colonnes, nous avons un petit souci:

Problème avec les bloc float

Ce défaut d’alignement est typique du comportement des éléments float: left. Si un élément est plus haut que d’autres, il va bloquer le positionnement des éléments qui le suivent. Ici la seconde ligne ne démarre pas correctement. Le shortcode utilisait justement la balise <br style="clear: both;" />  pour justement garantir des « sauts de lignes » corrects.

Quelles sont les solutions possibles?

Il faut donc trouver autre chose pour notre galerie garde de bons alignements, quoiqu’il arrive.
Pour cela, nous allons étudier deux pistes:

  • Une solution peut-elle être trouvée par modification du shortcode?
  • Peut-on gérer ces problèmes d’alignement avec uniquement des styles CSS?

Etape 3: Modification du shortcode

Nous repartons du shortcode écrit dans l’article précédent. L’objectif est d’ajouter des balises que nous pourrons ensuite facilement « styliser », pour avoir un contrôle total de notre galerie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function my_own_gallery_shortcode($attr) {
    // Generate the HTML code
    $attr['itemtag'] = 'figure';
    $attr['icontag']   = 'span';
    $attr['captiontag'] = 'figcaption';
    $html = gallery_shortcode($attr);
 
    // Extract the HTML code inside the div tag
    $pattern = '%<div([^>]+)>(.*?)</div>%si';
    $result = preg_match_all( $pattern,   $html, $inside);
    if ($result == 1) {
 
        // Extract / keep only figure tag, and what is inside
        $pattern = '%<figure(.*?)</figure>%si';
        $result = preg_match_all( $pattern,   $inside[2][0], $out);
        if ($result > 1) {
            $i=0;
            $columns = (isset($attr['columns']) ? $attr['columns'] : 3);
            $html = '<aside'.$inside[1][0].'>';
            // insert span tags
            foreach ($out[0] as $figure) {
                $html .= $figure;
                $class = '';
                if ( $columns > 1 ) {
                    if ( ++$i % 2 == 0 ) $class .= ' separator-2';
                    if ( $i % 3 == 0 ) $class .= ' separator-3';
                    if ( $i % 4 == 0 ) $class .= ' separator-4';
                }
                if ($class) $html .= '<span class="'.$class.'"></span>';
            } // End of for each
            $html .= '</aside>';
        } // End of get figure blocks
    } // End of get code inside div
    return $html;
} // End of function my_own_gallery_shortcode

Le code HTML obtenu ressemble à cela:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<aside ... ...>
    <figure ... ...> ... ... </figure>
    <figure ... ...> ... ... </figure>
    <span class="separator-2"></span>
    <figure ... ...> ... ... </figure>
    <span class="separator-3"></span>
    <figure ... ...> ... ... </figure>
    <span class="separator-2 separator-4"></span>
    <figure ... ...> ... ... </figure>
    <figure ... ...> ... ... </figure>
    <span class="separator-2 separator-3"></span>
    <figure ... ...> ... ... </figure>
    <figure ... ...> ... ... </figure>
    <span class="separator-2 separator-4"></span>
    <figure ... ...> ... ... </figure>
    <span class="separator-3"></span>
</aside>

Nous sommes maintenant armés pour transformer notre galerie comme bon nous semble. Voici la nouvelle feuille de styles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
aside.gallery {
    width: 90%;
    margin: 0 auto;
}
 
aside.gallery-columns-2 figure.gallery-item,
aside.gallery-columns-3 figure.gallery-item,
aside.gallery-columns-4 figure.gallery-item {
    float: left;
    margin: 2em 2%;
    text-align: center;
 }
 
aside.gallery-columns-2 figure.gallery-item { width: 46%; }
aside.gallery-columns-3 figure.gallery-item { width: 29%; }
aside.gallery-columns-4 figure.gallery-item { width: 21%; }
 
aside.gallery-columns-2 span.separator-2,
aside.gallery-columns-3 span.separator-3,
aside.gallery-columns-4 span.separator-4 { clear:both; display:block; }
 
@media-queries only screen and (max-width: 480px) {
    aside.gallery-columns-3 figure.gallery-item { width: 46%; }
    aside.gallery-columns-4 figure.gallery-item { width: 29%; }
 
    aside.gallery-columns-2 span.separator-2,
    aside.gallery-columns-3 span.separator-3,
    aside.gallery-columns-4 span.separator-4 { clear:none; display:inline; }
 
    aside.gallery-columns-3 span.separator-2,
    aside.gallery-columns-4 span.separator-3,
    aside.gallery-columns-5 span.separator-4  { clear:both; display:block; }
}

Quelques explications: en fonction des media-queries (et donc de la largeur de la fenêtre), nous modifions, à la fois, la largeur des colonnes, et les propriétés des séparateurs. Si nous voulons une galerie de 2 colonnes, la largeur sera de 46% (+ 2 x 2% de marges), et le séparateur span class="separator-2" aura l’attribut display:block, alors que tous les autres ne seront pas utilisés (display: none;).

Nous obtenons bien maintenant, l’effet souhaité, dans tous les cas:

Galerie fluide et responsive

Les avantages:

  • La technique est robuste,
  • Elle permet d’avoir un contrôle total des sauts de ligne.

Les inconvénients:

  • La compatibilité se limite aux navigateurs qui comprennent les media-queries,
  • Nous ajoutons une certaine quantité de balises HTML (mais si c’est plus propre que les balises br du shortcode par défaut).

Etape 3: Solutions CSS

Nous repartons du shortcode développé à l’étape 2, et qui génère un code HTML de ce type:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 <aside id='gallery-1' class='gallery galleryid-xxxx gallery-columns-3 gallery-size-thumbnail'>
    <figure class='gallery-item'>
        <span class='gallery-icon'>
            <a href=""image_1.jpg" title=" ... ... ">
                <img width="100" height="100" src="thumbnail_1.jpg" class="attachment-thumbnail" alt="... ..." title=" ... ... " />
            </a>
        </span>
        <figcaption> ... caption text ... </figcaption>
    </figure>
    <figure class='gallery-item'>
        <span class='gallery-icon'>
            <a href=""image_2.jpg" title=" ... ... ">
                <img width="100" height="100" src="thumbnail_2.jpg" class="attachment-thumbnail" alt="... ..." title=" ... ... " />
            </a>
        </span>
        <figcaption> ... caption text ... </figcaption>
    </figure>
    ... ...
    <figure class='gallery-item'>
        <span class='gallery-icon'>
            <a href=""image_n.jpg" title=" ... ... ">
                <img width="100" height="100" src="thumbnail_n.jpg" class="attachment-thumbnail" alt="... ..." title=" ... ... " />
            </a>
        </span>
        <figcaption> ... caption text ... </figcaption>
    </figure>
</aside>

Dans l’arsenal des solutions CSS, j’ai d’abord pensé aux sélecteurs nth-child, qui permettent de sélectionner le n-ième sous-élément d’un conteneur. Dans notre feuille de style, nous pourrions avoir, par exemple,

1
2
3
4
.gallery-columns-2 figure.gallery-item { width: 46%; }
.gallery-columns-2 figure.gallery-item:nth-child(2n) { clear:right;}
.gallery-columns-3 figure.gallery-item { width: 29%; }
.gallery-columns-3 figure.gallery-item:nth-child(3n) { clear:right;}

Avec ces styles, pour les galeries de 2 colonnes, nous supprimons l’attribut float des éléments pairs.
Cette méthode pose le même problème que l’exemple de l’étape 2. Si les éléments sont de différentes hauteurs, certains peuvent rester bloqués, et ne pas s’aligner à gauche.

La seconde idée a été d’utiliser l’attribut display: table-cell, qui donne aux éléments contiguës les mêmes propriétés que des cellules de tableaux (notamment même hauteur). Cette méthode me pose plusieurs problèmes:

  • d’abord, elle va de pair avec une structure HTML, qui inclut la gestion des lignes. Dans beaucoup d’exemples rencontrés, j’ai trouvé des conteneurs du type <div class="row"> autour des balises <figure>,
  • ensuite le résultat est extrêmement dépendant du navigateur utilisé, même s’il est récent.

La troisième voie de recherche a été l’attribut display:inline-block. Pour résumer, un élément inline-block dispose des caractéristiques de positionnement des éléments inline, mais accepte, dans le même temps, les attributs d’un élément block  (comme text-align, vertical-align, …).

Toujours sans rien toucher de notre shortcode de l’étape 2, nous allons modifier les styles de la balise <figure>:

1
2
3
4
5
6
7
8
figure.gallery-item {
    display: inline-block;
    vertical-align: top;
    margin: 2em 2%;
    text-align: center;
}
.gallery-columns-2 figure.gallery-item { width: 46%; }
.gallery-columns-3 figure.gallery-item { width: 29%; }

Les résultats obtenus sont parfaits avec un navigateur dit « moderne ».

Le cas de Internet Explorer 7

Le navigateur Internet Explorer 7 nécessite, comme d’habitude quelques aménagements. L’attribut inline-block  n’est pas supportée par ce navigateur. La solution consiste à utiliser display:inline, et de fixer la largeur des éléments.

1
2
3
4
5
6
7
8
9
10
figure.gallery-item {
    display: inline-block;
    vertical-align: top;
    margin: 2em 2%;
    text-align: center;
    zoom: 1;
    *display: inline;
}
.gallery-columns-2 figure.gallery-item { width: 46%; *width: 150px;}
.gallery-columns-3 figure.gallery-item { width: 29%; *width: 150px;}

Nous perdons la fluidité, et le contrôle sur le nombre de colonnes. Mais nous obtenons une galerie « responsive », dans le sens ou IE7 va effectuer un saut de ligne à chaque fois qu’il n’a plus la place pour afficher l’élément suivant. Dans l’extrait de code ci-dessus, j’ai considéré une largeur de 150px par colonne.

Si vous souhaitez garder le contrôle du nombre de colonnes, enlevez simplement *width: 150px;, mais vous perdrez le côté responsive de la galerie.

La solution complète

Résumons-nous: nous avons obtenus les meilleurs résultats, en supprimant la balise <br /> du shortcode, et en utilisant l’attribut display:inline-block dans nos styles. Et nous avons même une solution pour Internet Explorer 7.

La solution consiste donc à copier le code suivant dans le fichier functions.php de votre thème:

1
2
3
4
5
6
7
8
9
10
11
function my_own_gallery_shortcode($attr) {
    // Generate the HTML code
    $attr['itemtag'] = 'figure';
    $attr['icontag']   = 'span';
    $attr['captiontag'] = 'figcaption';
 
    return ( str_replace('<br style="clear: both;" />', '', gallery_shortcode($attr) ) );
 
} // End of function new_gallery_shortcode
remove_shortcode('gallery');
add_shortcode('gallery', 'my_own_gallery_shortcode');

Dans la feuille de style du thème, vous ajoutez les styles suivants:

aside.gallery {
    width: 90%;
    margin: 0 auto;
}
 
figure.gallery-item {
    display:inline-block;
    vertical-align: top;
    margin: 2em 2%;
    text-align: center;
    zoom:1;
    *display:inline;
}
 
.gallery-columns-2 figure.gallery-item {
    width: 46%;
    *width: 150px;
}
.gallery-columns-3 figure.gallery-item {
    width: 29%;
    *width: 150px;
}
.gallery-columns-4 figure.gallery-item {
    width: 21%;
    *width: 150px;
}
 
span.gallery-icon img {
    max-width: 100%;
    width: auto;
    height: auto;
    border: 1px solid #333;
    padding: 4%;
}
 
figcaption.gallery-caption {
    padding: 0.5em 2%;
}
 
@media only screen and (max-width: 480px) {
    .gallery-columns-3 figure.gallery-item {
        width: 46%;
    }
    .gallery-columns-4 figure.gallery-item {
        width: 29%;
    }
}

Conclusion

Avec la solution proposée, nous avons une galerie, fluide, responsive, et qui utilise les balises sémantiques de HTML5. Le code HTML obtenu est plus propre que celui du shortcode d’origine.

Personnellement, la découverte de l’attribut display: inline-block m’a beaucoup intéressé, parce que son champ d’application est tout simplement énorme. Je pense notamment à tous les menus horizontaux que l’on traite souvent avec des balises <li> flottantes, et des balises <a> en mode block, et qui pourraient ainsi être considérablement simplifiés.

Référence

La solution CSS de cet article est en grande partie basée sur cet excellent tutoriel: Table free gallery grid view.

1 thought on “WordPress: rendre le shortcode [ gallery] fluide et responsive”

  1. Bien vu, merci pour cette solution. Juste une question la limite de 150 Pc ne s’applique que à je 7?

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *