Zoom sur les images dans une disposition en grille PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Zoom sur des images dans une mise en page en grille

Créer une grille d'images est simple, grâce à CSS Grid. Mais faire en sorte que la grille fasse des choses fantaisistes après les images ont été placées peuvent être difficiles à réaliser.

Supposons que vous souhaitiez ajouter un effet de survol sophistiqué aux images là où elles grandissent et zoomer au-delà des lignes et des colonnes où elles se trouvent ? Nous pouvons faire ça!

Cool, non ? Si vous vérifiez le code, vous ne trouverez ni JavaScript, ni sélecteurs complexes, ni même nombres magiques. Et ce n’est qu’un exemple parmi tant d’autres que nous allons explorer !

Construire la grille

Le code HTML pour créer la grille est aussi simple qu'une liste d'images dans un conteneur. Nous n’avons pas besoin de plus que cela.

<div class="gallery">
  <img>
  <img>
  <img>
  <!-- etc. -->
</div>

Pour le CSS, nous commençons d’abord par définir la grille en utilisant ce qui suit :

.gallery {
  --s: 150px; /* controls the size */
  --g: 10px;  /* controls the gap */

  display: grid;
  gap: var(--g);
  width: calc(3*var(--s) + 2*var(--g)); /* 3 times the size plus 2 times the gap */
  aspect-ratio: 1;
  grid-template-columns: repeat(3, auto);
}

En bref, nous avons deux variables, une qui contrôle la taille des images et une qui définit la taille de l'écart entre les images. aspect-ratio aide à garder les choses proportionnées.

Vous vous demandez peut-être pourquoi nous définissons uniquement trois colonnes mais pas de lignes. Non, je n'ai pas oublié les lignes : nous n'avons tout simplement pas besoin de les définir explicitement. CSS Grid est capable de placer automatiquement des éléments sur lignes et colonnes implicites, ce qui signifie que nous obtenons autant de lignes que nécessaire pour n'importe quel nombre d'images que nous lui lançons. Nous pouvons définir explicitement les lignes à la place, mais nous devons ajouter grid-auto-flow: column pour vous assurer que le navigateur créera les colonnes nécessaires pour nous.

Voici un exemple pour illustrer les deux cas. La différence est que l'on circule dans un row direction et l'autre dans un column direction.

Vérifier cet autre article que j'ai écrit pour en savoir plus sur les grilles implicites et l'algorithme de placement automatique.

Maintenant que nous avons notre grille, il est temps de styliser les images :

.gallery > img {
  width: 0;
  height: 0;
  min-height: 100%;
  min-width: 100%;
  object-fit: cover;
}

L'effet de survol que nous créons repose sur ce CSS. Cela vous semble probablement étrange que nous créions des images qui n'ont ni largeur ni hauteur, mais qui ont une largeur et une hauteur minimales de 100 %. Mais vous verrez que c’est une astuce plutôt intéressante pour ce que nous essayons de réaliser.

Ce que je fais ici, c'est dire au navigateur que les images doivent avoir 0 largeur et hauteur mais doivent également avoir une hauteur minimale égale à 100%… mais 100% de quoi? Lorsque vous utilisez des pourcentages, la valeur est par rapport à autre chose. Dans ce cas, notre image est placée à l'intérieur d'un cellule de la grille et nous devons connaître cette taille pour savoir ce que c'est 100% est relatif à.

Le navigateur ignorera d'abord min-height: 100% pour calculer la taille des cellules de la grille, mais il utilisera le height: 0 dans son calcul. Cela signifie que nos images ne contribueront pas à la taille des cellules de la grille… car elles n'ont techniquement aucune taille physique. Cela se traduira par trois colonnes et lignes égales basées sur la taille de la grille (que nous avons définie sur le .galleryla largeur et aspect-ratio). La hauteur de chaque cellule de la grille n'est rien d'autre que la variable --s nous avons défini (idem pour la largeur).

Zoom sur des images dans une mise en page en grille

Maintenant que nous avons les dimensions des cellules de notre grille, le navigateur va les utiliser avec min-height: 100% (Et min-width: 100%) ce qui forcera les images à remplir complètement l'espace de chaque cellule de la grille. L'ensemble peut paraître un peu déroutant mais l'idée principale est de s'assurer que la grille définit la taille des images plutôt que l'inverse. Je ne veux pas que l'image définisse la taille de la grille et vous comprendrez pourquoi après avoir ajouté l'effet de survol.

Création de l'effet de survol

Ce que nous devons faire, c’est augmenter l’échelle des images lorsqu’elles sont survolées. Nous pouvons le faire en ajustant la taille d'une image width ainsi que height on :hover:

.gallery {
  --f: 1.5; /* controls the scale factor */
}

.gallery img:hover{
  width:  calc(var(--s) * var(--f));
  height: calc(var(--s) * var(--f));
}

J'ai ajouté une nouvelle variable personnalisée, --f, au mixage comme facteur d'échelle pour contrôler la taille en survol. Remarquez comment je multiplie la variable de taille, --s, par celui-ci pour calculer la nouvelle taille de l'image.

Mais vous avez dit que la taille de l'image devait être de 0. Que se passe-t-il ? Je suis perdu…

Ce que j'ai dit est toujours vrai mais je fais une exception pour l'image survolée. Je dis au navigateur qu'une seule image aura une taille qui n'est pas égale à zéro — elle contribuera donc à la dimension de la grille — tandis que toutes les autres resteront égales à 0.

Zoom sur les images dans une disposition en grille PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Zoom sur des images dans une mise en page en grille

Le côté gauche montre la grille dans son état naturel sans aucune image survolée, ce que montre le côté droit. Toutes les cellules de la grille sur le côté gauche sont de taille égale puisque toutes les images n'ont pas de dimensions physiques.

Sur le côté droit, la deuxième image de la première ligne est survolée, ce qui lui donne des dimensions qui affectent la taille de la cellule de la grille. Le navigateur agrandira cette cellule de grille spécifique en survol, ce qui contribue à la taille globale. Et comme la taille de la grille entière est définie (parce que nous définissons une taille fixe width sur le .gallery), les autres cellules de la grille répondront logiquement en devenant plus petites afin de conserver la .galleryLa taille globale de Tact.

C'est notre effet zoom en action ! En augmentant la taille d'une seule image, nous affectons la configuration entière de la grille, et nous avons dit précédemment que la grille définit la taille des images de sorte que chaque image s'étire à l'intérieur de sa cellule de grille pour remplir tout l'espace.

A cela, nous ajoutons une touche de transition et utilise object-fit pour éviter la distorsion de l'image et l'illusion est parfaite !

Je sais que la logique derrière cette astuce n’est pas facile à comprendre. Ne vous inquiétez pas si vous ne le comprenez pas complètement. Le plus important est de comprendre la structure du code utilisé et comment le modifier pour obtenir plus de variations. C'est ce que nous ferons ensuite !

Ajouter plus d'images

Nous avons créé une grille 3×3 pour expliquer l’astuce principale, mais vous avez probablement deviné que nous n’aurions pas besoin de nous arrêter là. Nous pouvons rendre le nombre de colonnes et de lignes variables et ajouter autant d'images que nous le souhaitons.

.gallery {
  --n: 3; /* number of rows*/
  --m: 4; /* number of columns */
  --s: 150px; /* control the size */
  --g: 10px;  /* control the gap */
  --f: 1.5;   /* control the scale factor */

  display: grid;
  gap: var(--g);
  width:  calc(var(--m)*var(--s) + (var(--m) - 1)*var(--g));
  height: calc(var(--n)*var(--s) + (var(--n) - 1)*var(--g));
  grid-template-columns: repeat(var(--m),auto);
}

Nous avons deux nouvelles variables pour le nombre de lignes et de colonnes. Ensuite, nous définissons simplement la largeur et la hauteur de notre grille en les utilisant. Pareil pour grid-template-columns qui utilise le --m variable. Et comme avant, nous n’avons pas besoin de définir explicitement les lignes puisque la fonction de placement automatique de la grille CSS fera le travail à notre place, quel que soit le nombre d’éléments d’image que nous utilisons.

Pourquoi pas des valeurs différentes pour la largeur et la hauteur ? Nous pouvons faire ça:

.gallery {
  --n: 3; /* number of rows*/
  --m: 4; /* number of columns */
  --h: 120px; /* control the height */
  --w: 150px; /* control the width */
  --g: 10px;  /* control the gap */
  --f: 1.5;   /* control the scale factor */

  display: grid;
  gap: var(--g);
  width:  calc(var(--m)*var(--w) + (var(--m) - 1)*var(--g));
  height: calc(var(--n)*var(--h) + (var(--n) - 1)*var(--g));
  grid-template-columns: repeat(var(--m),auto);
}

.gallery img:hover{
  width:  calc(var(--w)*var(--f));
  height: calc(var(--h)*var(--f));
}

Nous remplaçons --s avec deux variables, une pour la largeur, --w, et un autre pour la hauteur, --h. Ensuite, nous ajustons tout le reste en conséquence.

Nous avons donc commencé avec une grille avec une taille et un nombre d'éléments fixes, mais nous avons ensuite créé un nouvel ensemble de variables pour obtenir la configuration souhaitée. Tout ce que nous avons à faire est d'ajouter autant d'images que nous le souhaitons et d'ajuster les variables CSS en conséquence. Les combinaisons sont illimitées !

Et pourquoi pas une version plein écran ? Oui, c'est aussi possible. Tout ce dont nous avons besoin est de savoir quelles valeurs nous devons attribuer à nos variables. Si nous voulons N rangées d'images et nous voulons que notre grille soit en plein écran, nous devons d'abord déterminer une hauteur de 100vh:

var(--n) * var(--h) + (var(--n) - 1) * var(--g) = 100vh

Même logique pour la largeur, mais en utilisant vw au lieu de vh:

var(--m) * var(--w) + (var(--m) - 1) * var(--g) = 100vw

On fait le calcul pour obtenir :

--w: (100vw - (var(--m) - 1) * var(--g)) / var(--m)
--h: (100vh - (var(--n) - 1) * var(--g)) / var(--n)

Terminé!

C'est exactement le même HTML mais avec quelques variables mises à jour qui modifient la taille et le comportement de la grille.

Notez que j'ai omis la formule que nous avons définie précédemment sur le .gallery's width ainsi que height et les a remplacés par 100vw ainsi que 100vh, respectivement. La formule nous donnera le même résultat, mais puisque nous savons quelle valeur nous voulons, nous pouvons abandonner toute cette complexité supplémentaire.

On peut aussi simplifier le --h ainsi que --w en supprimant l'écart de l'équation au profit de ceci :

--h: calc(100vh / var(--n)); /* Viewport height divided by number of rows */
--w: calc(100vw / var(--m)); /* Viewport width divided by number of columns */

Cela fera agrandir l'image survolée un peu plus que dans l'exemple précédent, mais ce n'est pas grave puisque nous pouvons contrôler l'échelle avec le --f variable que nous utilisons comme multiplicateur.

Et comme les variables sont utilisées au même endroit, nous pouvons toujours simplifier le code en les supprimant complètement :

Il est important de noter que cette optimisation s’applique uniquement à l’exemple plein écran et non aux exemples que nous avons abordés. Cet exemple est un cas particulier où nous pouvons alléger le code en supprimant une partie du travail de calcul complexe dont nous avions besoin dans les autres exemples.

Nous avons en fait tout ce dont nous avons besoin pour créer le modèle populaire de panneaux extensibles :

Creusons encore plus profondément

Avez-vous remarqué que notre facteur d'échelle peut être inférieur à 1? Nous pouvons définir la taille de l'image survolée comme étant plus petite que --h or --w mais l'image s'agrandit au survol.

La taille initiale des cellules de la grille est égale à --w ainsi que --h, alors pourquoi des valeurs plus petites font-elles que la cellule de la grille plus gros? La cellule ne devrait-elle pas faibles, ou au moins conserver sa taille initiale ? Et quelle est la taille finale de la cellule de la grille ?

Nous devons approfondir la façon dont l’algorithme CSS Grid calcule la taille des cellules de la grille. Et cela implique de comprendre la valeur par défaut de CSS Grid étirement de l'alignement.

Voici un exemple pour comprendre la logique.

Sur le côté gauche de la démo, j'ai défini une colonne à deux avec auto largeur. Nous obtenons le résultat intuitif : deux colonnes égales (et deux cellules de grille égales). Mais la grille que j'ai configurée sur le côté droit de la démo, où je mets à jour l'alignement en utilisant place-content: start, semble n'avoir rien.

DevTools nous aide à nous montrer ce qui se passe réellement dans les deux cas :

Zoom sur les images dans une disposition en grille PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Zoom sur des images dans une mise en page en grille

Dans la deuxième grille, nous avons deux colonnes, mais leurs largeurs sont égales à zéro, nous obtenons donc deux cellules de grille réduites dans le coin supérieur gauche du conteneur de grille. C'est ne sauraient un bug mais la conséquence logique de l’alignement de la grille. Lorsque nous dimensionnons une colonne (ou une ligne) avec auto, cela signifie que son contenu dicte sa taille — mais nous avons un espace vide div sans contenu pour faire de la place.

Mais depuis stretch est l'alignement par défaut et nous avons suffisamment d'espace à l'intérieur de notre grille, le navigateur étendra les deux cellules de la grille de manière égale pour couvrir toute cette zone. C’est ainsi que la grille de gauche se termine par deux colonnes égales.

Du la spécification:

Notez que certaines valeurs de justify-content ainsi que align-content peut entraîner un espacement des pistes (space-around, space-between, space-evenly) ou à redimensionner (stretch).

Notez le « à redimensionner » qui est la clé ici. Dans le dernier exemple, j'ai utilisé place-content qui est le raccourci pour justify-content ainsi que align-content

Et ceci est enterré quelque part dans l'algorithme de dimensionnement de la grille Fiche technique:

Cette étape développe les pistes qui ont un auto fonction de dimensionnement maximum des pistes en divisant tout positif restant, précis espace libre également entre eux. Si l'espace libre est indéfini, Mais l' conteneur de grille a un certain largeur/hauteur minimale, utilisez plutôt cette taille pour calculer l'espace libre pour cette étape.

« De manière égale » explique pourquoi nous nous retrouvons avec des cellules de grille égales, mais cela s'applique à « l'espace libre » qui est très important.

Prenons l'exemple précédent et ajoutons du contenu à l'un des divs:

Nous avons ajouté un carré 50px image. Voici une illustration de la façon dont chaque grille de notre exemple répond à cette image :

Zoom sur les images dans une disposition en grille PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Zoom sur des images dans une mise en page en grille

Dans le premier cas, on voit que la première cellule (en rouge) est plus grande que la seconde (en bleu). Dans le second cas, la taille de la première cellule change pour s'adapter à la taille physique de l'image tandis que la deuxième cellule reste sans dimensions. L'espace libre est divisé de manière égale, mais la première cellule contient plus de contenu, ce qui la rend plus grande.

Voici le calcul pour déterminer notre espace libre :

(grid width) - (gap) - (image width) = (free space)
200px - 5px - 50px = 145px 

Divisé par deux – le nombre de colonnes – nous obtenons une largeur de 72.5px pour chaque colonne. Mais on ajoute la taille de l'image, 50px, à la première colonne ce qui nous laisse une colonne à 122.5px et le second égal à 72.5px.

La même logique s’applique à notre grille d’images. Toutes les images ont une taille égale à 0 (pas de contenu) tandis que l'image survolée contribue à la taille - même si ce n'est que 1px — rendant sa cellule de grille plus grande que les autres. Pour cette raison, le facteur d’échelle peut être n’importe quelle valeur supérieure à 0 même des décimales entre 0 ainsi que 1.

Pour obtenir la largeur finale des cellules de la grille, nous effectuons le même calcul pour obtenir ce qui suit :

(container width) - (sum of all gaps) - (hovered image width) = (free space)

La largeur du conteneur est définie par :

var(--m)*var(--w) + (var(--m) - 1)*var(--g)

…et tous les écarts sont égaux à :

(var(--m) - 1)*var(--g)

…et pour l’image survolée nous avons :

var(--w)*var(--f)

Nous pouvons calculer tout cela avec nos variables :

var(--m)*var(--w) - var(--w)*var(--f) = var(--w)*(var(--m) - var(--f))

Le nombre de colonnes est défini par --m , nous divisons donc cet espace libre de manière égale pour obtenir :

var(--w)*(var(--m) - var(--f))/var(--m)

…ce qui nous donne la taille des images non survolées. Pour les images survolées, nous avons ceci :

var(--w)*(var(--m) - var(--f))/var(--m) + var(--w)*var(--f)
var(--w)*((var(--m) - var(--f))/var(--m) + var(--f))

Si nous voulons contrôler la taille finale de l'image survolée, nous considérons la formule ci-dessus pour obtenir la taille exacte souhaitée. Si, par exemple, nous voulons que l'image soit deux fois plus grande :

(var(--m) - var(--f))/var(--m) + var(--f) = 2

Donc, la valeur de notre multiplicateur d'échelle, --f, doit être égal à :

var(--m)/(var(--m) - 1)

Pour trois colonnes nous aurons 3/2 = 1.5 et c'est le facteur d'échelle que j'ai utilisé dans la première démo de cet article car je voulais rendre l'image deux fois plus grande en survol !

La même logique s'applique au calcul de la hauteur et si nous souhaitons contrôler les deux indépendamment, nous devrons prendre en compte deux facteurs d'échelle pour nous assurer d'avoir une largeur et une hauteur spécifiques en survol.

.gallery {
  /* same as before */
   --fw: 1.5; /* controls the scale factor for the width */
   --fh: 1.2; /* controls the scale factor for the height */

  /* same as before */
}

.gallery img:hover{
  width:  calc(var(--w)*var(--fw));
  height: calc(var(--h)*var(--fh));
}

Maintenant, vous connaissez tous les secrets pour créer tout type de grille d'images avec un effet de survol sympa tout en contrôlant la taille souhaitée à l'aide des calculs que nous venons de couvrir.

Emballage en place

Dans mon dernier article, nous avons créé une grille d’apparence complexe avec quelques lignes de CSS qui utilisent la grille implicite et les fonctionnalités de placement automatique de CSS Grid. Dans cet article, nous nous sommes appuyés sur des astuces de dimensionnement de grille CSS pour créer une grille sophistiquée d'images qui zooment au survol et permettent à la grille de s'ajuster en conséquence. Tout cela avec un code simplifié et facile à ajuster grâce aux variables CSS !

Dans le prochain article, nous jouerons avec les formes ! Nous combinerons la grille CSS avec le masque et le chemin de clip pour obtenir une grille d'images sophistiquée.

Horodatage:

Plus de Astuces CSS