Décorations d'image fantaisie : masques et effets de survol avancés

Nœud source: 1727388

Bienvenue dans la partie 2 de cette série en trois parties ! Nous décorons toujours des images sans aucun élément supplémentaire ni pseudo-élément. J'espère que tu as déjà pris le temps de digérer Partie 1 parce que nous continuerons à travailler avec beaucoup de dégradés pour créer des effets visuels impressionnants. Nous allons également introduire le CSS mask propriété pour des décorations plus complexes et des effets de survol.

Fantaisie Image Décorations série

  • Magie d'élément unique
  • Masques et effets de survol avancés (Tu es là!)
  • Contours et animations complexes (à venir le 28 octobre )

Passons au premier exemple sur lequel nous travaillons ensemble…

Le timbre-poste

Croyez-le ou non, il suffit de deux dégradés et d'un filtre pour créer un effet CSS de timbre-poste :

img {
  --r: 10px; /* control the radius of the circles */
  padding: calc(2 * var(--r));
  filter: grayscale(.4);
  background: 
    radial-gradient(var(--r),#0000 98%,#fff) round
      calc(-1.5 * var(--r)) calc(-1.5 * var(--r)) / calc(3 * var(--r)) calc(3 * var(--r)),
    linear-gradient(#fff 0 0) no-repeat
      50% / calc(100% - 3 * var(--r)) calc(100% - 3 * var(--r));
}

Comme nous l'avons vu dans l'article précédent, la première étape consiste à faire de l'espace autour de l'image avec padding afin que nous puissions dessiner un dégradé d'arrière-plan et le voir là-bas. Ensuite, nous utilisons une combinaison de radial-gradient() ainsi que linear-gradient() pour couper ces cercles autour de l'image.

Voici une illustration étape par étape qui montre comment les dégradés sont configurés :

Notez l'utilisation du round valeur dans la deuxième étape. C'est très important pour l'astuce car cela garantit que la taille du dégradé est ajustée pour être parfaitement alignée sur tous les côtés, quelle que soit la largeur ou la hauteur de l'image.

Du la spécification: L'image est répétée aussi souvent que possible dans la zone de positionnement de l'arrière-plan. S'il ne rentre pas un nombre entier de fois, il est redimensionné pour qu'il le fasse.

Le cadre arrondi

Regardons une autre décoration d'image qui utilise des cercles…

Cet exemple utilise également un radial-gradient(), mais cette fois j'ai créé des cercles autour l'image au lieu de l'effet de découpe. Remarquez que j'utilise aussi le round valeur à nouveau. La partie la plus délicate ici est l'espace transparent entre le cadre et l'image, où j'atteins le CSS mask propriété:

img {
  --s: 20px; /* size of the frame */
  --g: 10px; /* the gap */
  --c: #FA6900; 

  padding: calc(var(--g) + var(--s));
  background: 
    radial-gradient(farthest-side, var(--c) 97%, #0000) 
      0 0 / calc(2 * var(--s)) calc(2 * var(--s)) round;
  mask:
    conic-gradient(from 90deg at calc(2 * var(--s)) calc(2 * var(--s)), #0000 25%, #000 0)
      calc(-1 * var(--s)) calc(-1 * var(--s)),
    linear-gradient(#000 0 0) content-box;
}

Le masquage nous permet de montrer la zone de l'image — grâce à la linear-gradient() là-dedans - ainsi que 20px autour de chaque côté - grâce à la conic-gradient()L’ 20px n'est rien d'autre que la variable --s qui définit la taille du cadre. En d'autres termes, nous devons masquer l'écart.

Voici ce que je veux dire:

Le dégradé linéaire est la partie bleue de l'arrière-plan tandis que le dégradé conique est la partie rouge de l'arrière-plan. Cette partie transparente entre les deux dégradés est ce que nous avons coupé de notre élément pour créer l'illusion d'une bordure transparente intérieure.

La bordure intérieure transparente

Pour celui-ci, nous n'allons pas créer de cadre mais plutôt essayer quelque chose de différent. Nous allons créer une bordure intérieure transparente à l'intérieur notre image. Probablement pas très utile dans un scénario réel, mais c'est une bonne pratique avec les masques CSS.

Comme dans l'exemple précédent, nous allons nous appuyer sur deux gradients : un linear-gradient() pour la partie intérieure, et un conic-gradient() pour la partie extérieure. Nous allons laisser un espace entre eux pour créer l'effet de bordure transparente.

img {
  --b: 5px;  /* the border thickness */
  --d: 20px; /* the distance from the edge */

  --_g: calc(100% - 2 * (var(--d) + var(--b)));
  mask:
    conic-gradient(from 90deg at var(--d) var(--d), #0000 25%, #000 0)
      0 0 / calc(100% - var(--d)) calc(100% - var(--d)),
    linear-gradient(#000 0 0) 50% / var(--_g) var(--_g) no-repeat;
}

Vous avez peut-être remarqué que le dégradé conique de cet exemple a une syntaxe différente de l'exemple précédent. Les deux sont censés créer la même forme, alors pourquoi sont-ils différents ? C'est parce que nous pouvons arriver au même résultat en utilisant des syntaxes différentes. Cela peut sembler déroutant au début, mais c'est une bonne fonctionnalité. Vous n'êtes pas obligé de trouver le solution pour obtenir une forme particulière. Vous n'avez qu'à trouver une solution qui vous convient parmi les nombreuses possibilités qui s'offrent à vous.

Voici quatre façons de créer le carré extérieur à l'aide de dégradés :

Il y a encore plus de façons de réussir, mais vous comprenez.

Il n'y a pas d'approche Best™. Personnellement, j'essaie de trouver celui avec le code le plus petit et le plus optimisé. Pour moi, toute solution nécessitant moins de gradients, moins de calculs et moins de valeurs répétées est la plus appropriée. Parfois, je choisis une syntaxe plus détaillée car cela me donne plus de flexibilité pour changer les variables et modifier les choses. Cela vient avec l'expérience et la pratique. Plus vous jouez avec les dégradés, plus vous savez quelle syntaxe utiliser et quand.

Revenons à notre bordure transparente intérieure et creusons dans l'effet de survol. Au cas où vous ne l'auriez pas remarqué, il y a un effet de survol sympa qui déplace cette bordure transparente à l'aide d'un font-size astuce. L'idée est de définir la --d variable avec une valeur de 1em. Cette variable contrôle la distance entre la bordure et le bord. Nous pouvons transformer comme ceci :

--_d: calc(var(--d) + var(--s) * 1em)

… nous donnant le CSS mis à jour suivant :

img {
  --b: 5px;  /* the border thickness */
  --d: 20px; /* the distance from the edge */
  --o: 15px; /* the offset on hover */
  --s: 1;    /* the direction of the hover effect (+1 or -1)*/

  --_d: calc(var(--d) + var(--s) * 1em);
  --_g: calc(100% - 2 * (var(--_d) + var(--b)));
  mask:
    conic-gradient(from 90deg at var(--_d) var(--_d), #0000 25%, #000 0)
     0 0 / calc(100% - var(--_d)) calc(100% - var(--_d)),
    linear-gradient(#000 0 0) 50% / var(--_g) var(--_g) no-repeat;
  font-size: 0;
  transition: .35s;
}
img:hover {
  font-size: var(--o);
}

La font-size est initialement égal à 0 ,donc 1em est également égal à 0 ainsi que --_d est égal à --d. En vol stationnaire, cependant, le font-size est égal à une valeur définie par un --o variable qui définit le décalage de la bordure. Ceci, à son tour, met à jour le --_d variable, déplaçant la bordure par le décalage. Ensuite, j'ajoute une autre variable, --s, pour contrôler le signe qui décide si la bordure se déplace vers l'intérieur ou vers l'extérieur.

La font-size Cette astuce est vraiment utile si nous voulons animer des propriétés qui seraient autrement inanimables. Propriétés personnalisées définies avec @property peut résoudre ce problème, mais le soutenir manque encore au moment où j'écris ceci.

La révélation du cadre

Nous avons réalisé l'animation de révélation suivante dans la première partie de cette série :

On peut reprendre la même idée, mais au lieu d'une bordure avec une couleur unie on va utiliser un dégradé comme celui-ci :

Si vous comparez les deux codes, vous remarquerez les changements suivants :

  1. J'ai utilisé la même configuration de dégradé du premier exemple à l'intérieur du mask propriété. J'ai simplement déplacé les dégradés du background propriété à la mask propriété.
  2. J'ai ajouté un repeating-linear-gradient() pour créer la bordure dégradée.

C'est ça! J'ai réutilisé la plupart du même code que nous avons déjà vu - avec de très petites modifications - et j'ai obtenu une autre décoration d'image sympa avec un effet de survol.

/* Solid color border */

img {
  --c: #8A9B0F; /* the border color */
  --b: 10px;   /* the border thickness*/
  --g: 5px;  /* the gap on hover */

  padding: calc(var(--g) + var(--b));
  --_g: #0000 25%, var(--c) 0;
  background: 
    conic-gradient(from 180deg at top var(--b) right var(--b), var(--_g))
     var(--_i, 200%) 0 / 200% var(--_i, var(--b)) no-repeat,
    conic-gradient(at bottom var(--b) left  var(--b), var(--_g))
     0 var(--_i, 200%) / var(--_i, var(--b)) 200% no-repeat;
  transition: .3s, background-position .3s .3s;
  cursor: pointer;
}
img:hover {
  --_i: 100%;
  transition: .3s, background-size .3s .3s;
}
/* Gradient color border */

img {
  --b: 10px; /* the border thickness*/
  --g: 5px;  /* the gap on hover */
  background: repeating-linear-gradient(135deg, #F8CA00 0 10px, #E97F02 0 20px, #BD1550 0 30px);

  padding: calc(var(--g) + var(--b));
  --_g: #0000 25%, #000 0;
  mask: 
    conic-gradient(from 180deg at top var(--b) right var(--b), var(--_g))
     var(--_i, 200%) 0 / 200% var(--_i, var(--b)) no-repeat,
    conic-gradient(at bottom var(--b) left  var(--b), var(--_g))
     0 var(--_i, 200%) / var(--_i, var(--b)) 200% no-repeat,
    linear-gradient(#000 0 0) content-box;
  transition: .3s, mask-position .3s .3s;
  cursor: pointer;
}
img:hover {
  --_i: 100%;
  transition: .3s, mask-size .3s .3s;
}

Essayons une autre animation d'image. Celui-ci est un peu délicat car il a un animation en trois temps:

La première étape de l'animation consiste à agrandir le bord inférieur. Pour cela, nous ajustons le background-size d'un linear-gradient():

Vous vous demandez probablement pourquoi j'ajoute également le bord supérieur. Nous en avons besoin pour la troisième étape. J'essaie toujours d'optimiser le code que j'écris, donc j'utilise un dégradé pour couvrir à la fois les côtés supérieur et inférieur, mais celui du haut est caché et révélé plus tard avec un mask.

Pour la deuxième étape, nous ajoutons un deuxième dégradé pour montrer les bords gauche et droit. Mais cette fois, nous le faisons en utilisant background-position:

On peut s'arrêter là car on a déjà un bel effet avec deux dégradés mais on est là pour repousser les limites alors rajoutons une touche de masque pour réaliser la troisième étape.

L'astuce consiste à masquer le bord supérieur jusqu'à ce que nous affichions le bas et les côtés, puis nous mettons à jour le mask-size (ou mask-position) pour afficher la partie supérieure. Comme je l'ai dit précédemment, nous pouvons trouver de nombreuses configurations de dégradés pour obtenir le même effet.

Voici une illustration des dégradés que j'utiliserai :

J'utilise deux dégradés coniques ayant une largeur égale à 200%. Les deux dégradés couvrent la zone en ne laissant que la partie supérieure découverte (cette partie sera invisible plus tard). Au survol, je fais glisser les deux dégradés pour couvrir cette partie.

Voici une meilleure illustration de l'un des dégradés pour vous donner une meilleure idée de ce qui se passe :

Maintenant, nous mettons cela à l'intérieur du mask propriété et nous avons terminé! Voici le code complet :

img {
  --b: 6px;  /* the border thickness*/
  --g: 10px; /* the gap */
  --c: #0E8D94;

  padding: calc(var(--b) + var(--g));
  --_l: var(--c) var(--b), #0000 0 calc(100% - var(--b)), var(--c) 0;
  background:
    linear-gradient(var(--_l)) 50%/calc(100% - var(--_i,80%)) 100% no-repeat,
    linear-gradient(90deg, var(--_l)) 50% var(--_i,-100%)/100% 200% no-repeat;  
  mask:
    conic-gradient(at 50% var(--b),#0000 25%, #000 0) calc(50% + var(--_i, 50%)) / 200%,
    conic-gradient(at 50% var(--b),#000 75%, #0000 0) calc(50% - var(--_i, 50%)) / 200%;
  transition: 
    .3s calc(.6s - var(--_t,.6s)) mask-position, 
    .3s .3s background-position,
    .3s var(--_t,.6s) background-size,
    .4s transform;
  cursor: pointer;
}
img:hover {
  --_i: 0%;
  --_t: 0s;
  transform: scale(1.2);
}

J'ai également introduit quelques variables pour optimiser le code, mais vous devriez être habitué à cela maintenant.

Qu'en est-il d'une animation en quatre étapes ? Oui c'est possible!

Aucune explication pour cela car ce sont vos devoirs! Prenez tout ce que vous avez appris dans cet article pour disséquer le code et essayez d'articuler ce qu'il fait. La logique est similaire à tous les exemples précédents. L'essentiel est d'isoler chaque dégradé pour comprendre chaque étape de l'animation. J'ai gardé le code non optimisé pour rendre les choses un peu plus faciles à lire. j'ai en effet une version optimisée si cela vous intéresse, mais vous pouvez également essayer d'optimiser le code vous-même et le comparer avec ma version pour plus de pratique.

Emballage en place

C'est tout pour la partie 2 de cette série en trois parties sur les décorations d'images créatives utilisant uniquement le élément. Nous avons maintenant une bonne idée de la façon dont les dégradés et les masques peuvent être combinés pour créer des effets visuels impressionnants, et même des animations - sans rechercher d'éléments supplémentaires ou de pseudo-éléments. Oui, un seul l'étiquette suffit !

Nous avons encore un article dans cette série à parcourir. En attendant, voici une démo bonus avec un effet de survol sympa où j'utilise mask pour assembler une image brisée.

Fantaisie Image Décorations série

  • Magie d'élément unique
  • Masques et effets de survol avancés (Tu es là!)
  • Contours et animations complexes (à venir le 28 octobre )

Horodatage:

Plus de Astuces CSS