WordPress: rendre le shorcode [ caption] fluide et responsive

Dans un précédent article, nous avons transformé notre shortcode [ caption] pour qu’il utilise les balises figure et figcaption de HTML 5. Nous allons abordé, maintenant, la question de la fluidité, et de l’adaptation à la taille du support d’affichage (shortcode responsive).

Le code de départ

Pour rappel, notre shortcode [ caption] génère le code HTML suivant:

1
2
3
4
5
6
<figure id="attachment_xxx" class="wp-caption aligncenter" style="width: 310px">
    <a href="image.jpg">
        <img class="size-medium wp-image-xxx" height="80" width="300" alt="" src="thumbnail.jpg" title=" ..." />
    </a>
    <figcaption class="wp-caption-text">Texte / Légende</figcaption>
</figure>

Ce code pose plusieurs problèmes:

  • d’abord, il contient un attribut style, ce qui n’est pas très propre,
  • ensuite, la largeur est indiquée en px (pixels), ce qui n’a rien de fluide,
  • pour finir, la taille de la balise figure ne tient pas compte des styles appliqués à l’image, et/ou au lien. Arbitrairement 10px sont ajoutés à la taille de l’image.

Un problème, des solutions

Pour une image seule, les méthodes sont connues. Si nous avons un code HTML de ce type:

1
<img src="image.jpg" height="80px" width=300px" alt="..." title="..." />

L’aspect «fluide» s’obtient avec le style suivant:

1
2
3
4
5
img {
    max-width: 100%;
    width: auto;
    height: auto;
}

Ce code CSS fonctionne également avec Internet Explorer 7.

L’aspect «responsive», s’obtient avec les media queries de CSS 3:

1
2
3
@media only screen and (max-width: xxx px) {
    img { width: yyy px; }
}

Mais dans notre cas, le conteneur est la balise <figure>, qui pour l’instant, à une taille fixe. Si la taille du conteneur ne s’adapte pas, la taille de son contenu ne s’adaptera pas non plus. Si aucune taille n’est indiquée, la balise <figure> prendra toute la largeur disponible puisqu’elle est déclarée avec l’attribut display: block;.

Il faut donc trouver un moyen de rendre la balise <figure> « fluide » ou  » responsive ».

Plusieurs types de solutions sont possibles:

  1. Des plugins WordPress, comme WP Fluid Images pour rendre les images fluides, ou Simple Responsive Images, plugin récent, mais assez intéressant,
  2. Des scripts Javascript, comme le très connu Respond.js,
  3. Toujours utiliser javascript mais avec une solution «maison»,
  4. Ne pas utiliser de plugin, ni de Javascript, et tenter de gérer ces deux aspects avec les feuilles de styles, comme dans le cas d’une image seule.

La première solution est la plus simple, à condition de trouver le bon plugin. Hors il y en a beaucoup, il faut donc du temps pour les tests.

Je ne suis pas emballé par les solutions Javascript du type Respond.js parce que même si elles sont légères, elles restent intrusives, dans le sens où elles obligent à ajouter du code Javascript au milieu du code HTML.

Nous allons donc explorer les deux dernières solutions.

Solution CSS

Notre code HTML resssemble à cela

1
2
3
<figure id="attachment_xxx" class="wp-caption aligncenter" style="width: 310px">
    ...
</figure>

Pour gérer la balise <figure> avec les styles, il faut

  • Supprimer le style ajouté par le shortcode ( style="width: 310px;" ),
  • Ajouter un identifiant, ou une classe permettant d’y associer facilement des styles. Hors le shortcode ne propose qu’une classe unique (wp-caption), quelle que soit la taille de l’image contenue.

Une solution possible, est d’utiliser la classe associée à la balise img. Lorsque l’on insère une image, WordPress nous permet de choisir la taille de l’image insérée: miniature, moyenne, large, ou Taille originale. WordPress associe, à chacune de ces tailles, une classe CSS: size-thumbnail, size-medium, size-large, et size-full.

Le shortcode ressemble à cela:

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
add_filter('img_caption_shortcode', 'html5_img_caption_shortcode', 1, 3 );
function html5_img_caption_shortcode($string, $attr, $content = null) {
    extract(shortcode_atts(array(
        'id'    => '',
        'align' => 'alignnone',
        'width' => '',
        'caption' => ''
        ),
        $attr)
    );
    $size_class = '';
    $width_style= ' style="width: ' . (10 + (int) $width) . 'px"';
    if (preg_match('/<img class="(size\-thumbnail|size\-medium|size\-large|size\-full)[^"]+/', $content, $matches)>0) {
        $size_class = ' '.$matches[1];
        $width_style= '';
    }
 
    if ( $id ) $id = 'id="' . esc_attr($id) . '" ';
 
    return '<figure ' . $id . 'class="wp-caption ' . esc_attr($align) . $size_class.'"' . $width_style . ' >' .
        do_shortcode( $content ) .
        ($caption!=''?'<figcaption class="wp-caption-text">' .
        $caption . '</figcaption>':'').
        '</figure>';
}

Par défaut, nous gardons la syntaxe HTML telle qu’elle est. Si nous arrivons à extraire la classe CSS de la balise img (ligne 13), nous l’utilisons comme classe pour la balise figure.
Nous obtenons un code HTML de ce type:

1
2
3
4
5
6
<figure id="attachment_xxx" class="wp-caption aligncenter size-medium" >
    <a href="image.jpg">
        <img class="size-medium wp-image-xxx" height="80" width="300" alt="" src="thumbnail.jpg" title=" ..." />
    </a>
    <figcaption class="wp-caption-text">Les 3 bungalows</figcaption>
</figure>

A partir de là, il devient beaucoup plus simple de rendre l’image fluide et/ou responsive.

Par exemple, si votre zone d’affichage est de maximum 560px, avec des tailles d’image de 150px pour les miniatures, 300px pour les tailles moyennes, et 500px pour les tailles larges, la feuille de style devient:

1
2
3
4
5
6
7
8
9
img {
    max-width: 100%;
    width: auto;
    height: auto;
}
 
figure.size-thumbnail { width: 27%;  /* 150/560 */ }
figure.size-medium    { width: 54%;  /* 300/560 */ }
figure.size-large     { width: 89%;  /* 500/560 */ }

De la même façon, ces styles peuvent être aisément utilisés avec les media-queries.

Avec cette méthode, il subsiste un problème: nous savons traiter toutes les tailles d’images, sauf la « taille original » dont nous ne connaissons, à priori pas la taille. J’avoue ne pas avoir trouvé de solution propre pour ce format.

Solution Javascript

La méthode consiste à utiliser un petit script Javascript, qui va

  • Récupérer la taille de l’image contenue dans la balise <figure>,
  • Calculer la valeur adéquate de la largeur, en fonction de la largeur du conteneur de cette même balise <figure>.

Avec cette méthode, il devient inutile de modifier le code HTML généré par le shortcode.

Créons d’abord le fichier figure_responsive.js :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(function() {
    $.fn.addstyle = function(container_width) {
        if (container_width  == 'auto')
            container_width = $(this).parent().width();
        else
            container_width = parseInt(container_width);
 
        child = $(this).children("a");
        if (child)
            child = child.children("img");
 
        $(this).css( "width", Math.ceil(100*child.width()/container_width) + "%" );
    }
    if (typeof(figure_responsive_container) =='undefined')
        figure_responsive_container = 'auto';
    $(".wp-caption").addstyle(figure_responsive_container);
})();

Puis d’ajouter dans un plugin, ou dans le fichier functions.php de votre thème:

1
2
3
4
5
6
7
 <?php
function enqueue_responsive_figure() {
    $url = ... ;
    wp_register_script( 'responsive_figure', $url.'/figure_responsive.js', array('jquery.js'), '1.0', TRUE);
}
add_action('wp_enqueue_scripts', 'enqueue_responsive_figure');
?>

Le script figure_responsive.js sera donc charger dans chacune de vos pages, dans la partie « footer », avec le script jquery.js qui est un pré-requis.

Il ne reste plus qu’à spécifier la largeur du conteneur (si besoin), en plaçant le code suivant dans le fichier header.php de votre thème, dans la partie <head>

1
var figure_responsive_container = xxx;

Après le chargement de la page, le script va analyser toutes les balises <figure> dont la classe CSS est wp-caption, pour ensuite définir leur largeur en %, en fonction de la taille de leur contenu.

L’avantage de cette méthode est qu’elle est universelle: elle fonctionne quelle que soit la taille de l’image.
J’ai identifié deux inconvénients principaux:

  • D’abord, elle est moins facilement « personnalisable » que la méthode précédente,
  • Ensuite, si vous avez des balises figure dans différents conteneurs, de différentes tailles, la méthode ne s’applique plus.

Autre défaut: la méthode utilise la librairie JQuery, dont le poids n’est pas forcement négligeable. Cette argument est discutable, dans le sens où JQuery est une librairie de plus en plus utilisée, et très souvent déjà présente.

Conclusion

Nous venons de présenter deux méthodes pour rendre « fluide » le shortcode [ caption]. Les deux méthodes ne sont pas parfaites, avec chacune, des inconvénients.
Pour l’instant, même si la solution 2, basée sur Javascript est plus universelle, j’ai choisi de rester avec la solution 1 pour deux raisons essentielles:

  • d’abord, comme je surcharge déjà le shortcode [ caption], les modifications à faire au code, se réduisent à seulement quelques lignes de PHP supplémentaires,
  • ensuite, je n’utilise quasiment pas le shortcode avec la taille originale des images.

 

Laisser un commentaire

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