Fermer

février 23, 2021

Créez des effets d'image réactifs avec des dégradés CSS et des proportions18 minutes de lecture



À propos de l'auteur

Stephanie Eckles est une SWE front-end chez Microsoft. Elle est également l'auteur de ModernCSS.dev qui fournit des solutions modernes à d'anciens problèmes CSS en profondeur…
En savoir plus sur
Stéphanie

Un problème classique dans CSS est de maintenir le rapport hauteur / largeur des images à travers les composants associés, tels que les cartes. La propriété aspect-ratio nouvellement prise en charge en combinaison avec object-fit offre un remède à ce mal de tête du passé! Apprenons à utiliser ces propriétés, en plus de créer un effet d'image dégradé réactif pour plus de flair.

To préparez-vous pour nos futurs effets d'image, nous allons mettre en place un composant de carte qui a une grande image en haut suivie d'un titre et d'une description. Le problème commun avec cette configuration est que nous n'avons pas toujours un contrôle parfait sur ce que l'image est, et plus important encore sur notre mise en page, quelles sont ses dimensions . Et bien que cela puisse être résolu en recadrant à l'avance, nous pouvons toujours rencontrer des problèmes dus à des conteneurs de taille réactive. Une conséquence est des positions inégales du contenu de la carte qui se démarque vraiment lorsque vous présentez une rangée de cartes.

Une autre solution précédente en plus du recadrage a peut-être été de passer d'un inline img à un blanc div qui n'existait que pour présenter l'image via background-image . J'ai moi-même mis en œuvre cette solution plusieurs fois dans le passé. Un avantage de ceci est d'utiliser une astuce plus ancienne pour le rapport hauteur / largeur qui utilise un élément de hauteur nulle et définit une valeur padding-bottom . La définition d’une valeur de remplissage sous forme de pourcentage donne une valeur calculée finale relative à la largeur de l’élément. Vous avez peut-être également utilisé cette idée pour conserver un rapport 16: 9 pour les incorporations vidéo, auquel cas la valeur de remplissage est trouvée avec la formule: 9/16 = 0,5625 * 100% = 56,26% . Mais nous allons explorer deux propriétés CSS modernes qui n'impliquent pas de mathématiques supplémentaires, nous donnent plus de flexibilité, et permettent également de conserver la sémantique fournie en utilisant un réel img au lieu de un vide div .

Tout d'abord, définissons la sémantique HTML, y compris l'utilisation d'une liste non ordonnée comme conteneur des cartes:

  •  http://www.smashingmagazine.com/

    A Super Wonderful Headline

    Lorem ipsum sit dolor amit

Ensuite, nous allons créer un ensemble minimal de styles de base pour le composant .card . Nous allons définir quelques styles visuels de base pour la carte elle-même, une mise à jour rapide du titre attendu h3 puis des styles essentiels pour commencer à styliser l'image de la carte.

 .card {
  couleur de fond: #fff;
  rayon de la frontière: 0,5rem;
  boîte-ombre: 0.05rem 0.1rem 0.3rem -0.03rem rgba (0, 0, 0, 0.45);
  rembourrage en bas: 1rem;
}

.card>: dernier-enfant {
  marge inférieure: 0;
}

.card h3 {
  margin-top: 1rem;
  taille de la police: 1,25rem;
}

img {
  rayon de la frontière: 0,5rem 0,5rem 0 0;
  largeur: 100%;
}

img ~ * {
  marge gauche: 1rem;
  marge droite: 1rem;
}

La dernière règle utilise le combinateur général des frères et sœurs pour ajouter une marge horizontale à tout élément qui suit img puisque nous voulons que l'image elle-même affleure les côtés de la carte .

Et nos progrès jusqu'à présent nous amènent à l'apparence de la carte suivante:

 Une carte avec les styles de base décrits précédemment appliqués et comprenant une image d'Unsplash d'un dessert sur une petite assiette à côté d'une boisson chaude dans une tasse
Une carte avec les styles de base décrits précédemment appliqués et comprenant une image d'Unsplash d'un dessert sur une petite assiette à côté d'une boisson chaude dans une tasse. ( Grand aperçu )

Enfin, nous allons créer les styles .card-wrapper pour une mise en page réactive rapide en utilisant la grille CSS. Cela supprimera également les styles de liste par défaut.

 .card-wrapper {
  style liste: aucun;
  rembourrage: 0;
  marge: 0;
  affichage: grille;
  grid-template-columns: répéter (auto-fit, minmax (30ch, 1fr));
  écart de grille: 1,5rem;
}

Note : Si cette technique de grille ne vous est pas familière, passez en revue l'explication dans mon tutoriel sur les solutions modernes pour la grille à 12 colonnes .

] Avec cela appliqué et avec toutes les cartes contenant une image avec un chemin source valide, nos styles .card-wrapper nous donnent la disposition suivante:

 Trois cartes sont affichées dans une rangée en raison de l'enveloppe de la carte styles de mise en page appliqués. Chaque carte a une image unique qui a des proportions naturelles différentes, la dernière carte ayant une image orientée verticalement qui est plus de deux fois la hauteur des autres images de la carte
Trois cartes sont affichées dans une rangée en raison de la disposition de l'emballage de la carte styles appliqués. Chaque carte a une image unique qui a des rapports d'aspect naturels différents, la dernière carte ayant une image orientée verticalement qui est plus de deux fois la hauteur des autres images de la carte. ( Grand aperçu )

Comme le montre l'image d'aperçu, ces styles de ligne de base ne sont pas suffisants pour contenir correctement les images étant donné leurs dimensions naturelles variables. Nous avons besoin d'une méthode pour contraindre ces images de manière uniforme et cohérente.

Activer des tailles d'image uniformes avec object-fit

Comme indiqué précédemment, vous avez peut-être déjà effectué une mise à jour dans ce scénario pour changer les images à ajouter via background-image à la place et utiliser background-size: cover pour bien redimensionner l'image. Ou vous avez peut-être essayé d'imposer le recadrage à l'avance (toujours un objectif valable puisque toute réduction de la taille de l'image améliorera les performances!).

Maintenant, nous avons la propriété object-fit disponible qui permet un img balise pour servir de conteneur pour l'image. Et, il est livré avec une valeur cover qui se traduit par un effet similaire à la solution d'image d'arrière-plan, mais avec l'avantage de conserver la sémantique d'une image en ligne. Appliquons-le et voyons comment cela fonctionne.

Nous devons l'associer à une dimension height pour obtenir des conseils supplémentaires sur la façon dont nous voulons que le conteneur d'images se comporte (rappelons que nous avions déjà ajouté width : 100% ). Et nous allons utiliser la fonction max () pour sélectionner soit 10rem ou 30vh selon ce qui est plus grand dans un contexte donné, ce qui empêche l'image hauteur de trop rétrécir sur des fenêtres plus petites ou lorsque l'utilisateur a réglé un grand zoom.

 img {
  / * ... styles existants * /
  ajustement de l'objet: couverture;
  hauteur: max (10rem, 30vh);
}

Astuce d'accessibilité supplémentaire : Vous devriez toujours tester vos mises en page avec un zoom de 200% et 400% sur le bureau. Bien qu'il n'y ait pas actuellement de requête multimédia zoom des fonctions telles que max () peuvent aider à résoudre les problèmes de mise en page. Un autre contexte dans lequel cette technique est utile est l'espacement entre les éléments.

Avec cette mise à jour, nous avons définitivement amélioré les choses, et le résultat visuel est comme si nous utilisions l'ancienne technique d'image d'arrière-plan:

 Les trois -les images de cartes semblent maintenant avoir une hauteur uniforme et le contenu de l'image est centré dans l'image comme s'il s'agissait d'un conteneur
Les images à trois cartes semblent maintenant avoir une hauteur uniforme et le contenu de l'image est centré dans l'image comme si c'était un conteneur. ( Grand aperçu )

Dimensionnement d'image cohérent et réactif avec le format

Lors de l'utilisation de object-fit seul, un inconvénient est que nous continuons à besoin de définir des indices de dimension.

Une propriété à venir (actuellement disponible dans les navigateurs Chromium) appelée aspect-ratio améliorera notre capacité à dimensionner systématiquement les images.

En utilisant cette propriété, nous pouvons ] définissent un rapport pour redimensionner l'image au lieu de définir des dimensions explicites. Nous continuerons à l'utiliser en combinaison avec object-fit pour nous assurer que ces dimensions n'affectent que l'image en tant que conteneur, sinon l'image pourrait apparaître déformée.

Voici notre règle d'image mise à jour complète:

 img {
  rayon de la frontière: 0,5rem 0,5rem 0 0;
  largeur: 100%;
  ajustement de l'objet: couverture;
  rapport hauteur / largeur: 4/3;
}

Nous allons commencer avec un rapport d'image de 4 3 pour notre contexte de carte, mais vous pouvez choisir n'importe quel rapport. Par exemple, 1 1 pour un carré, ou 16 9 pour les incorporations vidéo standard.

Voici la mise à jour cartes, bien qu'il soit probablement difficile de remarquer la différence visuelle dans ce cas particulier, car le rapport hauteur / largeur correspond étroitement à l'apparence que nous avons obtenue en définissant la hauteur pour object-fit uniquement .

 Les images à trois cartes ont des dimensions de largeur et de hauteur identiques, qui sont légèrement différentes de la solution d'ajustement d'objet précédente
Les images à trois cartes ont des dimensions de largeur et de hauteur identiques, qui sont légèrement différentes de celles de l'objet précédent solution adaptée. ( Grand aperçu )

La définition d'un rapport hauteur / largeur entraîne le maintien du rapport au fur et à mesure que les éléments grandissent ou rétrécissent, alors que lorsque vous ne définissez que l'ajustement et la hauteur de l'objet, le rapport d'image sera constamment en mouvement. les dimensions du conteneur changent.

Ajout d'effets réactifs avec des dégradés et des fonctions CSS

OK, maintenant que nous savons comment configurer des images de taille cohérente, amusons-nous avec eux en ajoutant un effet de dégradé!

Notre objectif avec ceci l'effet est de donner l'impression que l'image s'estompe dans le contenu de la carte. Vous pourriez être tenté d'envelopper l'image dans son propre conteneur pour ajouter le dégradé, mais grâce au travail que nous avons déjà effectué sur le dimensionnement de l'image, nous pouvons trouver comment le faire en toute sécurité sur le main .card .

La première étape consiste à définir un gradient . Nous allons utiliser une propriété personnalisée CSS pour ajouter les couleurs de dégradé afin de permettre de permuter facilement l'effet de dégradé, en commençant par le bleu vers le rose. La dernière couleur du dégradé sera toujours le blanc pour maintenir la transition vers l'arrière-plan du contenu de la carte et créer le bord «à plumes».

 .card {
  - carte-dégradé: # 5E9AD9, # E271AD;

  background-image: gradient-linéaire (
    var (- carte-gradient),
    blanc max (9.5rem, 27vh)
  );
  / * ... styles existants * /
}

Mais attendez – est-ce une fonction CSS max () ? Dans un dégradé? Oui, c'est possible, et c'est la magie qui rend ce dégradé efficace de manière réactive!

Cependant, si je devais ajouter une capture d'écran, nous ne verrions pas encore le dégradé avoir un effet sur l'image. Pour cela, nous devons introduire la propriété mix-blend-mode et dans ce scénario, nous utiliserons la valeur overlay :

 img {
  / * ... styles existants * /
  mix-blend-mode: superposition;
}

La propriété mix-blend-mode est similaire à l'application des styles de fusion de calque disponibles dans les logiciels de manipulation de photos comme Photoshop. Et la valeur de superposition aura pour effet de permettre aux tons moyens de l'image de se fondre avec le dégradé derrière, conduisant au résultat suivant: [19659055] Chaque image de carte a un effet de dégradé qui commence par un bleu clair en haut, qui se fond dans un rose rougeâtre, puis se termine par un contour progressif en blanc avant le reste du contenu textuel de la carte « />

Chaque image de carte a un effet de mélange dégradé qui commence par un bleu clair en haut, qui se fond dans un rose rougeâtre, puis se termine par un dégradé en blanc avant le reste du contenu du texte de la carte. ( Grand aperçu )

À ce stade, nous nous appuyons uniquement sur la valeur du rapport hauteur / largeur pour redimensionner l'image. Et si nous redimensionnons le conteneur et provoquons la redistribution de la mise en page de la carte, le changement de hauteur de l'image entraîne des incohérences dans le cas où le dégradé devient blanc.

Nous allons donc ajouter un max-height ainsi que également utilise la fonction max () et contient des valeurs légèrement supérieures à celles du gradient. Le comportement résultant est que le gradient s'alignera (presque toujours) correctement avec le bas de l'image.

 img {
  / * ... styles existants * /
  hauteur max: max (10rem, 30vh);
}

Il est important de noter que l’ajout d’une hauteur maximale modifie le comportement des proportions. Au lieu de toujours utiliser le rapport exact, il ne sera utilisé que s'il y a suffisamment d'espace alloué compte tenu de la nouvelle contrainte supplémentaire de hauteur maximale.

Cependant, aspect-ratio continuera à garantir les images redimensionner de manière cohérente, tout comme l'avantage par rapport uniquement à object-fit . Essayez de commenter rapport hauteur / largeur dans la démo finale de CodePen pour voir la différence que cela fait entre les tailles de conteneurs.

Puisque notre objectif initial était d'activer de manière cohérente des dimensions d'image réactives nous ' J'ai toujours frappé la marque. Pour votre propre cas d'utilisation, vous devrez peut-être modifier les valeurs de rapport et de hauteur pour obtenir l'effet souhaité.

Autre: mix-blend-mode And Adding A Filter

Using overlay car la valeur mix-blend-mode était le meilleur choix pour l'effet de fondu au blanc que nous recherchions, mais essayons une autre option pour un effet plus spectaculaire.

Nous allons mettre à jour notre solution pour ajouter une propriété personnalisée CSS pour la valeur mix-blend-mode et également mettre à jour les valeurs de couleur pour le dégradé:

 .card {
  - carte-dégradé: tomate, orange;
  --card-blend-mode: multiplier;
}

img {
  / * ... styles existants * /
  mix-blend-mode: var (- card-blend-mode);
}

La valeur multiplier a un effet assombrissant sur les tons moyens, mais conserve le blanc et le noir tels quels, ce qui donne l'apparence suivante:

 Chaque image de carte a une forte teinte orange du nouveau dégradé qui commence va d'un rouge-orange à l'orange pur. Les zones blanches sont toujours blanches et les zones noires sont toujours noires.
Chaque image de carte a une forte teinte orange du nouveau dégradé qui commence du rouge-orange à l'orange pur. Les zones blanches sont toujours blanches et les zones noires sont toujours noires. ( Grand aperçu )

Bien que nous ayons perdu le fondu et que nous ayons maintenant un bord dur au bas de l'image, la partie blanche de notre dégradé est toujours importante pour garantir que le dégradé se termine avant le contenu de la carte.

Une modification supplémentaire que nous pouvons ajouter est l'utilisation du filtre et, en particulier, utiliser la fonction niveaux de gris () pour supprimer le les couleurs de l'image et donc que le dégradé soit la seule source de coloration de l'image.

 img {
  / * ... styles existants * /
  filtre: échelle de gris (100);
}

L'utilisation de la valeur de niveaux de gris (100) permet de supprimer complètement les couleurs naturelles de l'image et de la transformer en noir et blanc. Voici la mise à jour pour comparaison avec la capture d'écran précédente de son effet lors de l'utilisation de notre dégradé orange avec multiplier :

 Maintenant, chaque image de carte a toujours le dégradé orange mais toutes les autres couleurs sont supprimées et remplacées par des nuances de gris
Maintenant, chaque image de carte a toujours le dégradé orange mais toutes les autres couleurs sont supprimées et remplacées par des nuances de gris. ( Grand aperçu )

Utilisez le format comme une amélioration progressive

Comme mentionné précédemment, actuellement le format n'est pris en charge que dans le dernier version des navigateurs Chromium (Chrome et Edge). Cependant, tous les navigateurs prennent en charge object-fit et cela, avec nos contraintes de height aboutit à un résultat moins idéal mais toujours acceptable, vu ici pour Safari:

 La hauteur de l'image de la carte est plafonnée, mais chaque carte a une hauteur réalisée légèrement différente
La hauteur de l'image de la carte est plafonnée, mais chaque carte a une hauteur réalisée légèrement différente. ( Grand aperçu )

Sans le rapport d'aspect le résultat ici est que finalement la hauteur de l'image est plafonnée mais les dimensions naturelles de chaque image sont toujours conduire à une certaine variance entre les hauteurs d'image de la carte. Vous pouvez à la place changer pour ajouter un max-height ou utiliser à nouveau la fonction max () pour aider à rendre un max-height plus réactif.

Extension des effets de dégradé

Depuis que nous avons défini les arrêts de couleur du dégradé comme une propriété personnalisée CSS, nous avons facilement accès pour les modifier dans différents contextes. Par exemple, nous pourrions changer le dégradé pour qu'il présente plus fortement l'une des couleurs si la carte est survolée ou a l'un de ses enfants au point.

Tout d'abord, nous mettrons à jour chaque carte h3 pour contenir un lien, tel que:

A Super Wonderful Headline

Ensuite, nous pouvons utiliser l'un de nos derniers sélecteurs disponibles – : focus-within – pour modifier le dégradé de la carte lorsque le lien est au point. Pour une couverture supplémentaire des interactions possibles, nous allons coupler cela avec : hover . Et nous réutiliserons notre idée max () pour attribuer une seule couleur pour prendre en charge la couverture de la partie image de la carte. L'inconvénient de cet effet particulier est que les arrêts de dégradé et les changements de couleur ne peuvent pas être animés de manière fiable – mais ils le seront bientôt grâce à CSS Houdini .

Pour mettre à jour la couleur et ajouter le nouvel arrêt de couleur, nous il suffit de réaffecter la valeur de - card-gradient dans cette nouvelle règle:

 .card: focus-within,
.card: hover {
  - carte-gradient: # 24a9d5 max (8.5rem, 20vh);
}

Nos valeurs max () sont inférieures à l'original utilisé pour blanc pour maintenir le bord en plumes. Si nous utilisions les mêmes valeurs, cela rencontrerait le blanc et créerait une séparation clairement rectiligne.

En créant cette démo, j'ai essayé à l'origine un effet qui utilisait transform avec ] échelle pour un effet de zoom. Mais j'ai découvert qu'en raison de l'application du mode mix-blend-mode le navigateur ne repeignait pas systématiquement l'image, ce qui provoquait un scintillement désagréable. Il y aura toujours des compromis à faire en demandant au navigateur d'exécuter des effets et des animations uniquement CSS, et bien que ce que nous pouvons faire, il est toujours préférable de vérifier l'impact sur les performances de vos effets.

Amusez-vous à expérimenter!

Le CSS moderne nous a donné quelques outils géniaux pour mettre à jour nos boîtes à outils de conception Web, avec aspect-ratio étant le dernier ajout. Alors allez-y, et expérimentez avec object-fit aspect-ratio et ajoutez des fonctions comme max () dans vos dégradés pour des effets réactifs amusants! Assurez-vous simplement de vérifier les éléments entre les navigateurs (pour le moment!) Et les différentes fenêtres et tailles de conteneurs.

Voici le CodePen, y compris les fonctionnalités et les effets que nous avons examinés aujourd'hui:

See the Pen [Responsive Image Effects with CSS Gradients and aspect-ratio] ( https://codepen.io/smashingmag/pen/WNoERXo) par Stephanie Eckles .

Voir le stylo Effets d'image réactifs avec dégradés CSS et rapport hauteur / largeur par Stephanie Eckles .

Vous en voulez plus? Assurez-vous de consulter notre guide CSS ici sur Smashing →

 Smashing Editorial "width =" 35 "height =" 46 "loading =" lazy "decoding =" async (vf, il )






Source link

0 Partages