Comment placer une image entre deux colonnes en CSS ?
4 (7)

Placer une image entre deux colonnes en CSS a longtemps été une véritable gageure, voire carrément impossible à réaliser. C’est désormais faisable avec un peu d’astuces et quelques propriétés CSS encore peu connues, le tout judicieusement combinées avec d’autres propriétés plus anciennes.

Comment placer une image entre deux colonnes en CSS ?
Placer une image entre deux colonnes en CSS c’est désormais possible.

Ainsi, pour être en mesure de placer une image entre deux colonnes en CSS avec un habillage façon magazine, il sera nécessaire d’utiliser les propriétés suivantes : float (left et right), margin (et ses variantes top, left, right), hyphens, shape-outside et shape-margin. Si float et margin existent depuis très longtemps, ce n’est pas le cas des trois dernières encore peu connues parce que relativement récentes dans le petit monde du CSS.

Les propriétés shape-outside et shape-margin

Shape-outside permet au texte d’épouser les contours du sujet d’une image en s’affranchissant des très classiques formes rectangulaires ou carrées. Alors que shape-margin vient en complément pour établir une marge entre les contours et le texte qui les borde. Combinée ensemble, le résultat est un habillage de texte façon magazine du plus bel effet.

Image avec la propriété shape-outside et shape-margin
Shape-outside et shape-margin permettent de suivre les contours d’une image.

Toutefois il est fortement conseillé d’opter pour un format d’image capable de gérer les fonds transparents tout en donnant accès à une large palette de couleurs. Le PNG est particulièrement bien adapté à nos besoins. Il est donc souhaitable de créer des images avec un détourage précis du sujet le tout sur fond transparent.

Un logiciel de traitement d’image (tel que Photoshop, Gimp ou Afinity Photo) peut s’avérer utile. À défaut il est possible de trouver des images sur internet répondant à ces critères. Attention toutefois aux licences proposées.

Hyphens et la gestion automatique des césures dans un texte

Hyphens indique au navigateur comment gérer les traits d’union lors des sauts de ligne sur des mots plus ou moins longs. En typographie française cela s’appelle des césures. Cette propriété nous sera utile pour harmoniser l’espace entre les mots, notamment sur les petits écrans ou si nos colonnes sont étroites.

Notons que cette propriété est dépendante de l’attribut lang indiqué dans la balise <html>. D’autre part, au moment où est rédigé cet article, il est important de retenir que hyphens n’est pas encore totalement opérationnelle sur tous les navigateurs (d’où la présence de préfixes dans le code CSS), exception faite pour Firefox et Chrome. Ceci aura donc une influence sur le rendu final pour les navigateurs ne prenant pas totalement en charge cette propriété. À ce propos je vous invite à consulter le site caniuse pour en savoir plus.

#colonnes article {
    background-color: #A079C8;
    padding: 1px 20px;
    text-align: justify;

    /*HYPHENS*/
    -ms-hyphens: auto;
    -webkit-hyphens: auto;
    hyphens: auto;
}

Mise en place de nos deux colonnes

Ce préambule étant clos, construisons maintenant nos deux colonnes. Contrairement à ce que nous pourrions penser, nous n’allons pas utiliser les propriétés spécifiques de colonnage en CSS. En effet, elles sont hélas inadaptées pour ce que nous voulons réaliser. Nous allons employer le très puissant module Flexbox CSS et profiter de sa capacité à placer des balises de type block les unes à côté des autres. C’est ainsi que nous créerons nos colonnes.

Structure du code HTML

<section id="colonnes">
    <div class="container colonnes">
        <h1>Titre de la section</h1>
        <article> <!--conteneur flex-->
            <div> <!--flex item-->
                <img class="bad-rabbit-left" src="img/bad-rabbit-1.png" alt="Bad rabbit">
                <h2>Titre de l'article</h2>
                <p>Lorem ipsum, ...</p>
                <p>...</p>
                <p>...</p>
                <p>...</p>
            </div>
        
            <div> <!--flex item-->
                <img class="bad-rabbit-right" src="img/bad-rabbit-1.png" alt="Bad rabbit">
                <p>...</p>
                <p>...</p>
                <p>...</p>
            </div>
        </article>
    </div>
</section>

Structure du code CSS

*{
    /*annule l'effet de gonflement dû au padding*/
    box-sizing: border-box; 
}
body{
    color: #fff;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 18px;
    line-height: 1.8;
    margin: 0;
}

.container{
    margin: auto;
    width: 1320px;
}

#colonnes .colonnes{
    background-color: #7C4EAB;
    padding: 20px;
}

/**** Mise en place des deux colonnes ***/
#colonnes article { /*conteneur flex*/
    display: flex; 
    flex-wrap: wrap;
    justify-content: space-between;
}

#colonnes article div { /*flex items*/
    background-color: #A079C8;

    /*Gestion de l'espace entre les 2 colonnes*/
    flex-basis: calc(50% - 10px);

    padding: 1px 20px;
    text-align: justify;
    -ms-hyphens: auto;
    -webkit-hyphens: auto;
    hyphens: auto;
}
/****************************************/

#colonnes h1{
    margin-top: 0;
}

/*** Ajustement du texte dans les 2 colonnes ***/
#colonnes article h2{
    margin-bottom: 0;
}

#colonnes article div:first-of-type p:first-of-type{
    margin-top: 12px;
}
/***********************************************/

/*** Placement des deux images au milieu des 2 colonnes ***/
#colonnes .bad-rabbit-left{
    float: right; /* force l'image à droite*/
    margin-left: 20px; /*évite que le texte ne touche le sujet*/
    margin-right: -135px; /*on déplace l'image vers la droite*/
}

#colonnes .bad-rabbit-right{
    float: left; /* force l'image à gauche*/
    margin-right: 20px; /*évite que le texte ne touche le sujet*/
    margin-left: -125px; /*on déplace l'image vers la gauche*/
}

/*s'applique sur les deux image en même temps*/
#colonnes [alt="Bad rabbit"]{ 
    /*ajoute une ombre qui suit les contours du sujet*/
    filter: drop-shadow(-10px 10px 10px rgba(0,0,0,0.5));
    margin-top: 235px; /*on déplace l'image vers le bas*/
    
    /*on appelle la même image pour que le texte épouse 
    parfaitement les contours du sujet*/
    shape-outside: url(../img/bad-rabbit-1.png);

    /*on ajoute une marge qui épouse les contours*/
    shape-margin: 20px;

    width: 200px; /*lageur des deux images*/
}
/**********************************************************/

Analysons le code. Pour placer nos deux colonnes l’une à côté de l’autre (les deux <div> placées dans la balise <article>), appliquons la propriété display: flex; sur <article> afin de la transformer en conteneur flex. Nos deux <div> deviennent alors des flex items selon la terminologie en vigueur dans le module flexbox.

<article> <!--conteneur flex-->
    <div> <!--flex item-->
        ...
    </div>

    <div> <!--flex item-->
        ...
    </div>
</article>

Remarquons également dans la feuille de style la présence de la propriété justify-content associée à la valeur space-between. Celles-ci nous assurent que le premier item sera toujours placé au maximum à gauche tandis que le dernier item sera au maximum à droite. De même, l’écart entre chaque élément sera automatiquement calculé en fonction de la largeur de ces derniers.

Quant à la propriété flex-wrap: wrap, elle nous garantit que s’il n’y a pas assez d’espace pour nos deux items ils se placeront automatiquement l’un en dessous de l’autre. Pratique pour gérer le responsive design sur de petits d’écrans de type mobile par exemple.

#colonnes article { /*conteneur flex*/
    display: flex; 
    flex-wrap: wrap;
    justify-content: space-between;
}

Astuce pour gérer un espace constant entre les items

Afin de conserver un espace constant entre les deux colonnes, quelle que soit la largeur de l’écran, nous combinons la propriété flex-basis (qui détermine la largeur des items), avec la fonction calc(). Commençons par diviser la largeur maximum disponible (soit 100%), par le nombre de colonnes (ici deux) pour connaître la largeur qu’occupera chacun de nos items.

Ainsi, chaque <div> a une largeur de 50%. Par conséquent, nos deux colonnes se touchent. Certes il suffirait de mettre moins de 50% pour régler cela. Mais dans ce cas l’espace entre les deux <div> fluctue en fonction de la largeur de l’écran. Or, esthétiquement ce n’est pas ce que nous voulons.

L’astuce consiste à soustraire automatiquement une valeur fixe en pixel au pourcentage appliqué sur la propriété flex-basis. C’est là qu’intervient la fonction calc(). Ce qui nous donne le code ci-après. Au final, nous sommes certains d’obtenir toujours le même espace quelle que soit la largeur de l’écran.

#colonnes article div { /*flex items*/
    background-color: #A079C8;

    /*Gestion de l'espace entre les 2 colonnes*/
    flex-basis: calc(50% - 10px);
    /******************************************/

    padding: 1px 20px;
    text-align: justify;
    -ms-hyphens: auto;
    -webkit-hyphens: auto;
    hyphens: auto;
}

Mentionnons enfin que flex-basis, contrairement aux autres propriétés du module flexbox, est appliqué sur les items et non sur le conteneur flex. Ceci est logique puisque flex-basis est utilisé pour déterminer la largeur des items et pas celle du conteneur.

Pour parfaire l’ensemble il est nécessaire d’apporter quelques ajustements pour que le texte s’aligne parfaitement entre les deux colonnes. C’est à cela que servent les lignes de code ci-après. Les valeurs peuvent bien sûr être différentes en fonction de la police utilisée et du niveau de titrage choisi (h1, h2, etc.). À noter également que la plus grande quantité de texte devra toujours être dans la colonne de gauche.

/*** Ajustement du texte dans les 2 colonnes ***/
    #colonnes article h2{
        margin-bottom: 0;
    }
    
    #colonnes article div:first-of-type p:first-of-type{
        margin-top: 12px;
    }
    /***********************************************/

Placer une image entre deux colonnes en CSS

Passons maintenant aux choses sérieuses et allons enfin placer une image entre deux colonnes en CSS. Vous aurez certainement remarqué que ladite image est appelée en deux exemplaires. Une au début de chaque colonne. C’est le secret.

<article> <!--conteneur flex-->
    <div> <!--flex item-->
        <img class="bad-rabbit-left" src="img/bad-rabbit-1.png" alt="Bad rabbit">
        <h2>Titre de l'article</h2>
        <p>...</p>
    </div>

    <div> <!--flex item-->
        <img class="bad-rabbit-right" src="img/bad-rabbit-1.png" alt="Bad rabbit">
        <p>...</p>
    </div>
</article>

En premier lieu, pour que les propriétés shape-outside et shape-margin fonctionnent, nous devons d’abord appliquer un float sur les images afin qu’elles s’insèrent dans le texte. Toutefois, en fonction de la valeur choisie (left ou right), l’effet d’habillage se fera soit à gauche, soit à droite de l’image, mais pas des deux côtés en même temps.

C’est justement ça le problème ! Comme il est impossible qu’une seule image puisse avoir un habillage des deux côtés, nous allons utiliser la même image dans chaque colonne et leur appliquer un float avec une valeur différente.

Par conséquent, l’image de la colonne de gauche reçoit un float: right; pour que le texte l’encadre par la gauche, alors qu’un float: left; est appliqué sur l’image de droite afin d’obtenir l’effet inverse. Reste maintenant à fusionner les deux images.

Pour cela faisons appel à la propriété margin et ces variantes. Une margin-right est ainsi appliquée sur l’image de gauche et une margin-left sur l’image de droite. Toutes deux reçoivent une valeur négative, pas forcément identiques d’ailleurs. L’idée est que les deux images se chevauchent pour n’en faire plus qu’une tout en étant placées au milieu, entre les deux colonnes.

/*** Placement des deux images au milieu des 2 colonnes ***/
#colonnes .bad-rabbit-left{
    float: right; /* force l'image à droite*/
    margin-left: 20px; /*évite que le texte ne touche le sujet*/
    margin-right: -135px; /*on déplace l'image vers la droite*/
}

#colonnes .bad-rabbit-right{
    float: left; /* force l'image à gauche*/
    margin-right: 20px; /*évite que le texte ne touche le sujet*/
    margin-left: -125px; /*on déplace l'image vers la gauche*/
}

Ceci fait, il nous reste à positionner l’ensemble sur l’axe vertical pour qu’il soit enrobé de toutes parts par le texte. C’est la propriété margin-top qui est sollicitée, avec cette fois-ci une valeur positive. Notons que pour nous faciliter la tâche nous avons appliqué une même valeur à l’attribut alt des deux images. Cela nous permet ensuite de se coller dessus en CSS grâce au sélecteur d’attribut.

Appliquons maintenant la propriété shape-outside associée à la fonction url() et indiquons simplement le chemin d’accès vers la même image que celle utilisée dans le code HTML. C’est la méthode la plus simple pour que le texte épouse parfaitement les contours de nos deux images.

Reste ensuite à ajouter la propriété shape-margin pour que le texte ne se colle pas contre le sujet détouré des deux images. Pour parfaire l’ensemble il est souvent nécessaire d’ajouter une margin-left pour l’image de la colonne de gauche et une margin-right pour celle de droite avec la même valeur que celle appliquée sur la propriété shape-margin.

Pour conclure cet article sur comment placer une image entre deux colonnes en CSS, utilisons une dernière propriété également peu connue, juste pour l’aspect esthétique. Il s’agit de filter associé ici à la fonction drop-shadow(). Ce binôme permet d’appliquer une ombre qui épouse parfaitement les contours d’une image détourée sur fond transparent. L’effet est plutôt cool.

/*s'applique sur les deux image en même temps*/
#colonnes [alt="Bad rabbit"]{
    /*ajoute une ombre qui suit les contours du sujet*/
    filter: drop-shadow(-10px 10px 10px rgba(0,0,0,0.5));
    margin-top: 235px; /*on déplace l'image vers le bas*/

    /*on appelle la même image pour que le texte épouse
    parfaitement les contours du sujet*/
    shape-outside: url(../img/bad-rabbit-1.png);

    /*on ajoute une marge qui épouse les contours*/
    shape-margin: 20px;

    width: 200px; /*lageur des deux images*/
}
/**********************************************************/

Voilà ! J’espère que cet article vous ouvrira de nouvelles perspectives de mise en page. Vous trouverez ici un lien vers une réalisation responsive design, afin de vous démontrer que cela est compatible. Le code source est quant à lui disponible ici

Retour vers la page d’accueil du blog.

Laisser un commentaire

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

Nom *