web-dev-qa-db-fra.com

Utilisation de valeurs de pourcentage avec position d'arrière-plan sur un gradient linéaire

Existe-t-il un moyen de faire background-position prendre des valeurs en pourcentage? Actuellement, mon bouton ne fonctionne qu'avec des valeurs explicites pour width et background-position.

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
}

.button {
  display: flex;
  justify-content: center;
  align-items: center;
  text-decoration: none;
  color: white;
  font-weight: bold;
  width: 350px;
  height: 50px;
  border: 1px solid green;
  transition: background 0.5s;
  background-repeat: no-repeat;
  background-image: linear-gradient(to left, #2484c6, #1995c8 51%, #00bbce), linear-gradient(to right, #2484c6 0%, #1995c8 51%, #00bbce 76%);
}
.button-pixel {
  background-position: -350px 0px, 0px 0px;
}
.button-pixel:hover {
  background-position: 0px 0px, 350px 0px;
}
.button-percentage {
  background-position: -100% 0px, 0px 0px;
}
.button-percentage:hover {
  background-position: 0% 0px, 100% 0px;
}
<a href="#" class="button button-pixel">In Pixel</a>
<a href="#" class="button button-percentage">In Percentage</a>
14
Mo.

TL; DR

Toutes les valeurs de pourcentage utilisées avec background-position sont équivalentes lorsque vous utilisez un dégradé comme arrière-plan, vous ne verrez donc aucune différence. Vous devez spécifier un background-size Différent de la taille du conteneur:

body {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
  min-height:90vh;
}

.button {
  text-decoration: none;
  color: white;
  font-weight: bold;
  width: 350px;
  height: 50px;
  text-align:center;
  transition: background 0.5s;
  background-repeat: no-repeat;
  background-image: 
    linear-gradient(to left, #2484c6, #1995c8 51%, #00bbce), 
    linear-gradient(to right, #2484c6 0%, #1995c8 51%, #00bbce 76%);
  background-size:200% 100%; /*Changed this*/
}
.button-pixel {
  background-position: -350px 0px, 0px 0px;
}
.button-pixel:hover {
  background-position: 0px 0px, 350px 0px;
}
.button-percentage {
  background-position: 100% 0px, 0px 0px;
}
.button-percentage:hover {
  background-position: 0% 0px, 100% 0px;
}
<a href="#" class="button button-pixel">Pixel</a>
<a href="#" class="button button-percentage">Percentage</a>

Comment fonctionne la position de fond?

Utilisons une image classique pour expliquer comment fonctionne background-position.

Lorsque vous utilisez des valeurs de pixels, la référence est le coin supérieur/gauche de l'image, quelle que soit sa taille. C'est comme utiliser top/left avec un élément positionné:

.b {
  width:200px;
  height:200px;
  background:url(https://picsum.photos/100/100?image=1069) no-repeat;
  border:1px solid;
  background-position:0 0;
  position:relative;
  animation:back 5s infinite linear alternate;
}
.b:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  width:10px;
  height:10px;
  background:red;
  animation:change 5s infinite linear alternate;
}

@keyframes back{to{background-position:200px 200px;}}
@keyframes change{to{top:200px; left:200px;}}
<div class="b"></div>

Lorsque vous utilisez des valeurs en pourcentage, la référence est différente de lorsque vous utilisez des valeurs en pixels; ce n'est plus le coin haut/gauche:

.b {
  width:200px;
  height:200px;
  background:url(https://picsum.photos/100/100?image=1069) no-repeat;
  border:1px solid;
  background-position:0% 0%;
  position:relative;
  animation:back 3s infinite linear alternate;
}
.b:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  width:10px;
  height:10px;
  background:red;
  animation:change 3s infinite linear alternate;
}
@keyframes back{to{background-position:100% 100%;}}
@keyframes change{to{top:200px; left:200px;}}
<div class="b"></div>

Dans ce cas, nous devons considérer deux paramètres: la taille du conteneur ET la taille de l'image. Voici une illustration de son fonctionnement (j'ai pris un background-position Égal à 30% 30%):

enter image description here

Tout d'abord, nous considérons l'image pour trouver le point de référence que nous allons utiliser pour placer l'image. C'est le point à l'intérieur de l'image qui est positionné à 30% 30% À partir du coin supérieur/gauche en considérant la taille de l'image (comme définie avec les lignes vertes). Ensuite, nous plaçons ce point à l'intérieur du conteneur à 30% 30% À partir du coin supérieur/gauche en considérant la taille du conteneur .

De cette logique, nous pouvons clairement identifier certains cas triviaux comme

50% 50% (Centre) 100% 100% (En bas à droite) 100% 0% (En haut à droite)

enter image description here

Maintenant, il est clair que si la taille de l'image est égale à la taille du conteneur alors rien ne se passera simplement parce que toutes les positions sont équivalentes . Le haut/gauche de l'image est déjà en haut/gauche (0% 0%) du conteneur, le centre est déjà au centre (50% 50%) etc.

.b {
  width:200px;
  height:200px;
  background:url(https://picsum.photos/200/200?image=1069) no-repeat;
  border:1px solid;
  background-position:0% 0%;
  position:relative;
  animation:back 5s infinite linear alternate;
}
.b:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  width:10px;
  height:10px;
  background:red;
  animation:change 5s infinite linear alternate;
}
@keyframes back{to{background-position:100% 100%;}}
@keyframes change{to{top:100%; left:100%;}}
<div class="b"></div>

La logique ci-dessus est la même lorsqu'elle est appliquée aux dégradés car les dégradés sont considérés comme des images, et par défaut, si vous ne spécifiez pas un background-size, La taille d'un dégradé sera la taille de son conteneur, contrairement à l'utilisation d'une image .

Si nous nous référons à la spécification du background-size, Nous pouvons voir comment votre problème se pose:

Si les deux valeurs sont auto, alors la largeur et/ou la hauteur intrinsèque de l'image doit être utilisée , le cas échéant, la dimension manquante (le cas échéant) se comportant comme auto comme décrit ci-dessus. Si l'image n'a ni largeur intrinsèque ni hauteur intrinsèque, sa taille est déterminée comme pour contient .

Et:

contenir

Redimensionnez l'image, tout en préservant son rapport d'aspect intrinsèque (le cas échéant), à la plus grande taille de sorte que sa largeur et sa hauteur puissent tenir à l'intérieur de l'arrière-plan zone de positionnement.

Et aussi:

Une image bitmap (telle que JPG) a toujours des dimensions et des proportions intrinsèques .

Les CSS <gradient> n'ont pas de dimensions intrinsèques ou proportions intrinsèques .ref

Une image a toujours des valeurs intrinsèques, donc dans la plupart des cas elle n'aura pas la même taille que son conteneur, donc background-position Avec des unités de pourcentage aura un effet. Mais les dégradés n'ont pas de valeurs intrinsèques, donc les dimensions d'un dégradé seront égales à la taille de son conteneur, et background-position Avec des valeurs en pourcentage ne fonctionnera jamais sauf si nous spécifions un background-size Différent de son conteneur dimensions.



Plus en profondeur

Nous avons vu dans les exemples ci-dessus comment background-size Fonctionne lorsque vous utilisez des valeurs comprises entre 0% Et 100%, Mais qu'en est-il de l'utilisation de valeurs négatives ou d'une valeur supérieure à 100%? La logique est la même, mais trouver le point de référence sera plus délicat.

Valeurs négatives (<0%)

Supposons que nous voulons placer un arrière-plan à -50% 0. Dans ce cas, le point de référence sera en dehors de l'image. Voici un exemple:

.b {
  width:200px;
  height:200px;
  border:1px solid;
  background:url(https://picsum.photos/100/100?image=1069) -50% 0/100px 100px no-repeat;
}
<div class="b"></div>

enter image description here

Comme nous pouvons le voir dans l'illustration, nous considérons d'abord -50% De l'image, qui est -50px, Afin de définir notre point de référence (c'est-à-dire -50px à partir du bord gauche de l'image) . Ensuite, nous plaçons ce point à -50% Compte tenu de la taille du conteneur (-100 px à partir du bord gauche du conteneur). Ensuite, nous dessinons l'image et nous obtenons le résultat ci-dessus. Seul 100px De l'image est visible.

Nous pouvons également remarquer que les valeurs de pourcentage négatives se comporteront de la même manière que les valeurs fixes négatives lorsque la taille de l'image est inférieure à la taille du conteneur (les deux déplaceront l'image vers la gauche). Dans ce cas, -50% 0 Est identique à -50px 0.

.b {
  width:200px;
  height:200px;
  display:inline-block;
  border:1px solid;
  background:url(https://picsum.photos/100/100?image=1069) -50% 0/100px 100px no-repeat;
}
.a{
  background:url(https://picsum.photos/100/100?image=1069) -50px 0/100px 100px no-repeat;
}
<div class="b">
</div>
<div class="b a">
</div>

Si, par exemple, nous augmentons la taille de l'image à 150px 150px, -50% 0 Sera le même que -25px 0.

Lorsque nous rendons la taille plus grande que le conteneur , les valeurs négatives commenceront à déplacer l'image vers la droite (comme avec les valeurs de pixels positives), ce qui est logique puisque le 50% de l'image augmentera tandis que le 50% du conteneur restera le même.

Si nous considérons l'illustration précédente, c'est comme augmenter la ligne verte supérieure jusqu'à ce qu'elle soit plus grande que celle du bas. Donc le signe seul ne suffit pas pour savoir comment l'image d'arrière-plan sera décalée; nous devons également considérer la taille.

.b{
  width:200px;
  height:200px;
  border:1px solid;
  background:url(https://picsum.photos/300/300?image=1069) -50% 0/50px 50px no-repeat;
  animation:change 2s linear infinite alternate; 
}
@keyframes change{
  to {background-size:300px 300px}
}
<div class="b">
</div>

La même chose se produira logiquement pour les dégradés:

.b {
  width:200px;
  height:200px;
  border:1px solid;
  background:linear-gradient(to right,red,blue) -50% 0/50px 150px no-repeat;
  animation:change 2s linear infinite alternate; 
}
@keyframes change{
  to   {background-size:300px 150px}
}
<div class="b">
</div>

Grandes valeurs (> 100%)

Même logique que précédemment: si nous définissons un arrière-plan à 150% 0, Alors nous considérons notre point de référence 150% À partir du bord gauche (ou 50% À partir du bord droit), alors nous placez-le 150% à partir du bord gauche du conteneur.

.b {
  width:200px;
  height:200px;
  border:1px solid;
  background:url(https://picsum.photos/100/100?image=1069) 150% 0/100px 100px no-repeat;
}
<div class="b"></div>

Dans ce cas, 150% 0 Est équivalent à 150px 0, Et si nous commençons à augmenter la taille de l'arrière-plan, nous aurons le même comportement que précédemment démontré:

.b {
  width:200px;
  height:200px;
  border:1px solid;
  background:url(https://picsum.photos/300/300?image=1069) 150% 0/50px 50px no-repeat;
  animation:change 2s infinite linear alternate;
}
@keyframes change {
  to {background-size:300px 300px}
}
<div class="b"></div>


Cas spéciaux

L'utilisation de valeurs en dehors de la plage [0% 100%] Nous permet de masquer l'image d'arrière-plan, mais comment trouver les valeurs exactes afin de masquer complètement l'image?

Prenons l'exemple ci-dessous:

enter image description here

Notre image a une largeur Ws et le conteneur une largeur Wp et nous devons trouver la valeur de p. À partir de la figure, nous pouvons obtenir la formule suivante:

p * Wp = p * Ws + Ws   <=>   p = Ws/(Wp - Ws)   where p in [0,1]

Si la taille du conteneur est 200px Et l'image est 100px Alors p est 1 Donc 100% (Nous ajoutons bien sûr le signe négatif et c'est -100%).

Nous pouvons rendre cela plus générique si nous considérons des valeurs en pourcentage avec background-size Au lieu de valeurs fixes. Supposons que background-size Soit S%. Ensuite, nous aurons Ws = Wp * s (s in [0,1] and S=s*100%), et la formule sera

p = Ws/(Wp - Ws)   <=>   p = s / (1 - s)

En ajoutant le signe négatif, ce sera p = s / (s - 1).

Maintenant, si nous voulons masquer l'image sur le côté droit, nous faisons la même logique sur la droite (nous considérons un miroir de l'illustration précédente), mais puisque nous considérerons toujours le bord gauche pour trouver le pourcentage que nous devons ajouter 100%.

Le nouveau pourcentage p'% Est 100% + p% Et la formule sera p' = 1 + p --> p' = 1 + s / (1 - s) = 1 / (1 - s).

Voici une animation pour illustrer le calcul ci-dessus:

.b {
  width:200px;
  height:50px;
  margin:5px;
  border:1px solid;
  background:linear-gradient(to right,red,blue) no-repeat;
  background-size:calc(var(--s) * 100%) 100%;
  animation:change 4s linear infinite alternate;
}
@keyframes  change{
   from { /*Hide on the left*/
     background-position:calc(var(--s)/(var(--s) - 1) * 100%)
   }
   to { /*Hide on the right*/
     background-position:calc(1/(1 - var(--s)) * 100%)
   }
}
<div class="b" style="--s:0.5">
</div>
<div class="b" style="--s:0.8">
</div>
<div class="b" style="--s:2">
</div>

Calculons quelques valeurs:

Lorsque s=0.5, Nous avons un background-size Égal à 50%, Et les valeurs en pourcentage seront de -100% À 200%. Dans ce cas, nous avons commencé avec une valeur négative et terminé avec une valeur positive car la taille de l'image est inférieure à la taille du conteneur . Si nous considérons le dernier cas (s=2) Le background-size Est égal à 200%, Et les valeurs en pourcentage seront de 200% À -100%. Nous avons commencé avec une valeur positive et terminé avec une valeur négative car la taille de l'image est plus grande que la taille du conteneur .

Cela confirme ce que nous avons dit précédemment: pour déplacer une image vers la gauche, nous avons besoin de valeurs négatives si la taille est petite, mais nous avons besoin de valeurs positives si la taille est grande (même chose pour la droite).


Relation entre les valeurs de pixel et de pourcentage

Définissons un moyen de calculer des valeurs de pourcentage en fonction des valeurs de pixels, ou vice versa (c'est-à-dire la formule à convertir entre les deux). Pour ce faire, nous devons simplement considérer les points de référence.

enter image description here

Lorsque vous utilisez des valeurs de pixels, nous considérerons les lignes bleues et nous aurons background-position:X Y.

Lorsque vous utilisez des valeurs en pourcentage, nous considérerons les lignes vertes et nous aurons background-position:Px Py.

La formule sera comme suit: Y + Py * Ws = Py * WpWs est la largeur de l'image et Wp est la largeur du conteneur (même formule pour l'axe X en considérant la hauteur).

Nous aurons Y = Py * (Wp - Ws). A partir de cette formule, nous pouvons valider deux points comme expliqué précédemment:

  • Lorsque Wp = Ws, La formule n'est plus valide, ce qui confirme que les valeurs en pourcentage n'ont aucun effet lorsque la taille de l'image est la même que celle du conteneur; il n'y a donc pas de relation entre les valeurs de pixel et de pourcentage.
  • Y et Py auront le même signe quand Wp > Ws Et auront le signe opposé quand Wp < Ws. Cela confirme que le pourcentage se comporte différemment selon la taille de l'image.

Nous pouvons également exprimer la formule différemment si nous considérons la valeur en pourcentage de background-size. Nous aurons Y = Py * Wp * (1-s).

Voici une animation pour illustrer le calcul ci-dessus:

.b {
  width:200px;
  height:50px;
  margin:5px;
  border:1px solid;
  background:linear-gradient(to right,red,blue) no-repeat;
  background-size:calc(var(--s) * 100%) 100%;
  animation:percentage 2s linear infinite alternate;
}
.box.a {
  animation-name:pixel; 
}
@keyframes  percentage{
   from { background-position:-50%;}
   to { background-position:150%;}
}
@keyframes  pixel{
   from { background-position:calc(-0.5 * 200px * (1 - var(--s))) }
   to {  background-position:calc(1.5 * 200px * (1 - var(--s)));}
}
<div class="b" style="--s:0.5">
</div>
<div class="b a" style="--s:0.5">
</div>

<div class="b" style="--s:2">
</div>
<div class="b a" style="--s:2">
</div>


Modification de la référence

Dans les calculs ci-dessus, nous avons toujours considéré le coin supérieur/gauche de l'image et le conteneur afin d'appliquer notre logique soit pour les valeurs en pixels soit pour les valeurs en pourcentage. Cette référence peut être modifiée en ajoutant plus de valeurs à background-position.

Par défaut, background-position: X Y Équivaut à background-position: left X top Y (Position à X dans le left et à Y dans le top ). En ajustant top et/ou left, nous modifions la référence et la façon dont l'image est placée. Voici quelques exemples:

.b {
  width:150px;
  height:150px;
  display:inline-block;
  background:url(https://picsum.photos/70/70?image=1069) no-repeat;
  border:1px solid;
  position:relative;
}

body {
 margin:0;
}
<div class="b"></div>
<div class="b" style="background-position:left 0 bottom 0"></div>
<div class="b" style="background-position:right 0 bottom 0"></div>
<div class="b" style="background-position:right 0 top 0"></div>


<div class="b" style="background-position:right 10% top 30%"></div>
<div class="b" style="background-position:right 10% bottom 30%"></div>
<div class="b" style="background-position:right 10px top 20px"></div>
<div class="b" style="background-position:left 50% bottom 20px"></div>

Il est clair que pour la valeur X, nous ne pouvons utiliser que left et right (la position horizontale) et avec la valeur Y, nous ne pouvons utiliser que bottom et top (la position verticale). Avec toutes les différentes combinaisons, nous pouvons logiquement obtenir les 4 coins différents.

Cette fonctionnalité est également utile pour optimiser certains calculs. Dans l'exemple de la section cas particuliers, nous avons fait un premier calcul pour masquer l'image à gauche puis un autre pour la masquer à droite. Si nous envisageons de changer la référence, nous n'avons qu'à effectuer un seul calcul. Nous prenons la formule utilisée pour le côté gauche et nous utilisons la même chose pour le côté droit.

Voici la nouvelle version:

.b {
  width:200px;
  height:50px;
  margin:5px;
  border:1px solid;
  background:linear-gradient(to right,red,blue) no-repeat;
  background-size:calc(var(--s) * 100%) 100%;
  animation:change 4s linear infinite alternate;
}
@keyframes  change{
   from { 
     background-position:left  calc(var(--s)/(var(--s) - 1) * 100%) top 0
   }
   to { 
     background-position:right calc(var(--s)/(var(--s) - 1) * 100%) top 0
   }
}
<div class="b" style="--s:0.5">
</div>
<div class="b" style="--s:0.8">
</div>
<div class="b" style="--s:2">
</div>

Pour s=0.5 Nous n'animerons plus de -100% À 200% MAIS ce sera de left -100% À right -100%.

Voici un autre exemple utilisant des valeurs de pixels où nous pouvons clairement voir à quel point il est facile de traiter le calcul lors du changement de référence:

.b {
  width:200px;
  height:200px;
  background:url(https://picsum.photos/100/100?image=1069) no-repeat;
  border:1px solid;
  background-repeat:no-repeat;
  animation:change 2s infinite linear;
}


@keyframes change{
  0%{background-position:left 20px top 20px;}
  25%{background-position:right 20px top 20px;}
  50%{background-position:right 20px bottom 20px;}
  75%{background-position:left 20px bottom 20px;}
  100%{background-position:left 20px top 20px;}
}
<div class="b"></div>

Il serait difficile de réaliser la même animation en gardant la même référence. Donc, si nous voulons faire une animation symétrique, nous faisons notre logique d'un côté et utilisons la même chose de l'autre côté en changeant la référence.


Combinaison de valeurs de pixels et de pourcentages

En CSS3, nous pouvons utiliser calc() afin de faire des calculs complexes impliquant différentes unités. Par exemple, nous pouvons écrire width:calc(100px + 20% + 12em) et le navigateur calculera la valeur calculée en considérant le fonctionnement de chaque unité et nous terminerons avec une valeur de pixel (dans ce cas).

Qu'en est-il de background-position? Si nous écrivons calc(50% + 50px), cela sera-t-il évalué en pourcentage ou en pixel? la valeur du pixel sera-t-elle convertie en pourcentage ou l'inverse?

Le résultat ne sera pas converti en valeur de pixel ou en pourcentage, mais plutôt les deux seront utilisés ensemble! background-position A un comportement spécial lors du mélange de valeurs de pourcentage et de pixels à l'intérieur de calc() et la logique est la suivante:

  1. Nous utilisons d'abord la valeur en pourcentage pour positionner l'image en appliquant toute la logique liée aux valeurs en pourcentage.
  2. Nous considérons la position de (1) comme référence et nous utilisons la valeur de pixel pour positionner à nouveau l'image en appliquant toute la logique liée aux valeurs de pixel.

Donc calc(50% + 50px) signifie: centrer l'image, puis la décaler de 50 pixels vers la gauche.

Cette fonctionnalité peut simplifier beaucoup de calculs. Voici un exemple:

.b {
  width:200px;
  height:200px;
  display:inline-block;
  border:1px solid;
  background-image:
    linear-gradient(red,red),
    linear-gradient(red,red),
    linear-gradient(red,red),
    linear-gradient(red,red);
 background-size:20px 20px;
 background-position:
    calc(50% + 20px) 50%,
    calc(50% - 20px) 50%,
    50% calc(50% - 20px),
    50% calc(50% + 20px);
 background-repeat:no-repeat;
 transition:0.5s;
}
.b:hover {
  background-position:50%;
}
<div class="b"></div>
<div class="b" style="width:100px;height:100px;"></div>

Il serait fastidieux de trouver le pourcentage ou les valeurs de pixels corrects pour placer les 4 carrés rouges comme ci-dessus, mais en mélangeant les deux à l'aide de calc() c'est assez facile.

Supposons maintenant que nous ayons quelque chose comme ceci: calc(10% + 20px + 30% + -10px + 10% + 20px). Comment le navigateur va-t-il gérer cela?

Dans ce cas, le navigateur évaluera d'abord chaque unité pour obtenir la forme simplifiée calc(X% + Ypx) puis appliquera la logique ci-dessus pour positionner l'image.

calc(10% + 20px + 30% + -10px + 10% + 20px) 
calc((10% + 30% + 10%) + (20px + -10px +20px)) 
calc(50% + 30px)
.box {
  display:inline-block;
  width:200px;
  height:200px;
  background-image:url(https://picsum.photos/100/100?image=1069);
  border:1px solid;
  background-position:calc(10% + 20px + 30% + -10px + 10% + 20px) 0;
  background-repeat:no-repeat;
}
.alt {
  background-position:calc(50% + 30px) 0;
}
 
<div class="box"></div>
<div class="box alt"></div>

Quelle que soit la complexité de la formule, le navigateur évaluera toujours les valeurs en pourcentage et en pixels séparément.


Utilisation de background-Origin

Voici une autre propriété importante qui peut être utilisée pour modifier la position de l'image d'arrière-plan. Cette propriété s'appuie sur le modèle de boîte. Permet donc d'obtenir un rappel rapide de son fonctionnement:

enter image description here

Chaque élément contient 3 cases différentes: border-box, padding-box et content-box. background-Origin Spécifie quelle case nous devons considérer afin de faire toute notre logique précédente.

Voici un exemple explicite:

.b {
  display:inline-block;
  width:200px;
  height:200px;
  background:
    url(https://picsum.photos/100/100?image=1069) no-repeat,
    linear-gradient(to right,red,blue) bottom/100% 20% no-repeat;
  border:20px solid rgba(0,0,0,0.1);
  padding:20px;
  box-sizing:border-box;

  background-Origin:border-box;
}
.p {
  background-Origin:padding-box; /*the default value*/
}
.c {
  background-Origin:content-box;
}
<div class="b"></div>
<div class="b p"></div>
<div class="b c"></div>

Il devrait être clair maintenant que lorsque nous n'avons pas de rembourrage content-box Est équivalent à padding-box, Et quand nous n'avons pas de bordure border-box Est équivalent à padding-box.


Faire en sorte que le pourcentage se comporte différemment

Dans le cas où nous vraiment devons avoir la taille de l'image égale à la taille du conteneur et la déplacer en utilisant un pourcentage comme le pixel, nous pouvons considérer les idées ci-dessous.

  • Utilisation d'un pseudo-élément comme calque d'arrière-plan:
.b {
  width:200px;
  height:200px;
  border:1px solid;
  position:relative;
  z-index:0;
  overflow:hidden;
}
.b:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  width:100%;
  height:100%;
  z-index:-1;
  background:url(https://picsum.photos/200/200?image=1069);
  background-size:100% 100%;
  transition:1s;
}
.b:hover::before {
  transform:translate(100%,100%);
}
<div class="b"></div>

Nous devons noter que translate considère la taille du pseudo-élément, mais comme il s'agit du même conteneur que nous n'aurons aucun problème. Nous pouvons également utiliser left/top mais transform aura de meilleures performances.

  • Utilisation de background-Origin

L'astuce est d'avoir un rembourrage, de restreindre l'origine à la zone de contenu et de rendre la taille plus grande que 100% Pour couvrir le rembourrage et que l'image remplisse le conteneur.

.b {
  width:200px;
  height:200px;
  outline:1px solid;
  padding:0 100px 100px 0;
  box-sizing:border-box;
  z-index:0;
  overflow:hidden;
  background:url(https://picsum.photos/200/200?image=1069) no-repeat;
  background-Origin:content-box;
  background-size:200% 200%;
  transition:0.8s;
}

.b:hover {
  background-position:-200% -200%; 
  /* We use [0%,-200%] to cover [0%,100%]*/
}
<div class="b"></div>

Dans ce qui précède, j'ai fait le rembourrage de la moitié de la taille, donc logiquement, je dois utiliser 200% Dans background-size Pour rectifier. Pour le background-position, Il est maintenant facile de trouver la valeur requise en fonction de l'explication ci-dessus.

Un autre exemple:

.b {
  width:200px;
  height:200px;
  outline:1px solid;
  padding:50px;
  box-sizing:border-box;
  z-index:0;
  overflow:hidden;
  background:url(https://picsum.photos/200/200?image=1069) no-repeat;
  background-Origin:content-box;
  background-size:200% 200%;
  background-position:50% 50%;
  transition:0.8s;
}

.b:hover {
  background-position:-150% -150%; 
  /* We use [50%,-150%] to cover [0%,100%]*/
}
<div class="b"></div>



Notez que d'autres unités comme em, ch, etc., se comportent de la même manière que px. Ils sont appelés longueurs .

38
Temani Afif