web-dev-qa-db-fra.com

Effet de bordure dégradé étrange

Lors de l'application d'une bordure transparente sur un élément avec un linear-gradient comme arrière-plan, j'obtiens un effet bizarre.

enter image description here

Notez que les côtés gauche et droit de l'élément n'ont pas les bonnes couleurs (ils sont en quelque sorte commutés) et sont étrangement plats.

[~ # ~] html [~ # ~]

<div class="colors">
</div>

[~ # ~] css [~ # ~]

.colors {
    width: 100px;
    border: 10px solid rgba(0,0,0,0.2);
    height: 50px;
    background: linear-gradient(to right, 
        #78C5D6,
        #459BA8,
        #79C267,
        #C5D647,
        #F5D63D,
        #F08B33,
        #E868A2,
        #BE61A5);
}

Pourquoi est-ce que cela montre un effet étrange sur les côtés gauche et droit de l'élément, et Quoi puis-je faire à ce sujet?

Voici le violon: http://jsfiddle.net/fzndodgx/3/

71
Afonso Matos

En effet, les points de début et de fin du gradient sont aux bords du padding-box et border est rendu en dehors de padding-box. Ainsi, les bordures sont drôles parce que le background est répété de chaque côté en dehors du padding-box pour couvrir le border-box.

Le box-shadow:inset est rendu à l'intérieur du padding-box (comme l'arrière-plan) et donne visuellement le même effet qu'un border, vous pouvez donc essayer de l'utiliser à la place de border:

box-shadow: inset 0 0 0 10px rgba(0,0,0,0.2);
padding: 10px;

Parce qu'un box-shadow ne prend pas de place, vous devez augmenter votre rembourrage en conséquence.

Illustration de padding-box et border-boxenter image description here

Démo http://jsfiddle.net/ilpo/fzndodgx/5/

50
Okku

Solution

La façon la plus simple de résoudre ce problème serait de définir la valeur de la propriété background-Origin Sur border-box.

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-Origin: border-box;
}
<div class="colors"></div>

Raison du comportement mentionné en question

Voici les propriétés background pertinentes qui déterminent la façon dont le dégradé d'arrière-plan est affiché dans ce cas:

  • background-Origin - La valeur par défaut est padding-box. Cela signifie que l'arrière-plan est en fait positionné par rapport à la zone de remplissage et commence donc après le border.
  • background-repeat - La valeur par défaut est repeat. Cela signifie que l'image doit être répétée autant que nécessaire pour couvrir toute la zone de peinture de fond.
  • background-clip - La valeur par défaut pour cela est border-box. Cela signifie que l'image doit également être présente sous la zone occupée par les bordures de la boîte.

Maintenant, en combinant les trois, nous pouvons voir que la bordure doit être répétée autant que possible pour qu'elle soit présente même sous les bordures et que sa position de départ est après la bordure de la boîte. Cela implique que l'arrière-plan doit être répété de manière cyclique afin de remplir la zone sous la bordure sur le côté gauche. Pour cette raison, la bordure gauche a la couleur comme l'extrémité droite du dégradé et vice-versa.

En le changeant en border-box, Nous faisons en sorte que l'arrière-plan soit positionné par rapport à la zone de bordure. Ce paramètre a également un effet sur la taille de l'image d'arrière-plan et sa raison est décrite ci-dessous en détail.


Pourquoi box-sizing: border-box Ne fonctionne pas?

La définition de box-sizing Sur border-box N'entraîne aucune modification car cette propriété affecte uniquement la taille de la boîte. Cela n'a absolument aucun effet sur les éléments suivants:

  • La taille de l'image du gradient (la logique de calcul réelle est décrite ci-dessous)
  • Le point de départ (ou position) de l'image en dégradé
  • La répétition de l'image d'arrière-plan

Comment est calculée la taille du dégradé?

Selon Spécifications W3C , voici comment les dimensions de l'image sont calculées lorsqu'aucune taille explicite n'est fournie (la valeur par défaut est auto).

Si l'image n'a ni largeur intrinsèque ni hauteur intrinsèque, sa taille est déterminée comme pour "contenir"

Notez comment il parle de la taille de l'image et non de celle de la boîte. En substance, quelle que soit la taille de la boîte, la taille de l'image d'arrière-plan serait calculée sur la base de la définition du mot-clé contain lorsque l'image elle-même n'a pas de hauteur intrinsèque ( quels gradients CSS ne font pas ' t ont des images différentes ).

La définition de contain est la suivante:

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 dans la zone de positionnement d'arrière-plan .

La zone de positionnement d'arrière-plan est définie comme suit (sous la définition de propriété background-Origin):

Pour les éléments rendus sous la forme d'une seule boîte, spécifie la zone de positionnement d'arrière-plan

Ainsi, lorsque l'image n'a pas de hauteur intrinsèque (et dans ce cas pas de background-size Aussi), la taille de l'image serait égale à celle de la valeur de background-Origin (Qui dans notre cas est padding-box).

C'est pourquoi même définir le box-sizing Comme border-box N'a aucun effet.

Remarque: l'accent mis dans les textes cités est tout à moi


Si vous définissez explicitement le background-size Comme taille de la boîte, vous remarquerez comment le problème est résolu sur le côté droit mais pas sur le côté gauche. En effet, l'image est maintenant suffisamment grande pour ne pas se répéter sous la bordure droite, mais son point de départ est toujours après la bordure gauche.

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-size: 110px 60px;
}
.colors-2 {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  box-sizing: border-box;
  background-size: 100px 50px;
}
<div class="colors">
</div>
<div class="colors-2">
</div>
43
Harry

Le fond se répète sous la frontière. L'arrière-plan s'exécute uniquement dans le "corps" de l'élément, sous la bordure se trouve une expansion et la répétition commence.

Voir l'exemple this avec no-repeat à la frontière.

[~ # ~] mise à jour [~ # ~]

Jouer avec l'arrière-plan position & size peut aider en développant l'arrière-plan puis en ajustant son emplacement.

Vérifiez ce violon out.

Ou consultez l'extrait:

.colors {
  padding: 10px;
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-size: 117%;
  background-position-x: 130px;
}
<div class="colors"></div>
13
JNF

La valeur par défaut de background-Origin la propriété est padding-box ce qui signifie que l'arrière-plan est positionné et dimensionné par rapport à la zone de remplissage.

L'arrière-plan ( s'étend également sous la bordure depuis le background-clip par défaut, la propriété est border-box; il se répète simplement sous la frontière. C'est pourquoi vous voyez le côté droit de l'arrière-plan sous la bordure gauche et vice versa.

Donc, changez simplement l'origine:

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-Origin: border-box;
}
<div class="colors"></div>

Alternativement, vous pouvez jouer avec la taille et la position de l'arrière-plan: ajoutez 20px à la taille de l'arrière-plan et positionnez-la à -10px -10px:

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-position: -10px -10px;
  background-size: calc(100% + 20px) calc(100% + 20px);
}
<div class="colors"></div>
4
Salman A

D'autres réponses ont déjà montré comment résoudre le problème, mais j'ai pensé que je devrais simplement signaler que si vous augmentez le border-width il devient évident que l'arrière-plan se répète réellement.

.colors {
    width: 100px;
    border: 100px solid rgba(0,0,0,0.2);
    height: 50px;
    background: linear-gradient(to right, 
        #78C5D6,
        #459BA8,
        #79C267,
        #C5D647,
        #F5D63D,
        #F08B33,
        #E868A2,
        #BE61A5);
}

produira

enter image description here

4
mflodin

Le dégradé commence dans la zone de remplissage selon le comportement du modèle de boîte CSS par défaut, il est donc logique que les couleurs de début et de fin apparaissent jusqu'à l'infini de chaque côté du dégradé, là où se trouverait la bordure.

Il en va de même pour ce gradient (NSFW):

A GOD AWFUL EYE SORE

Il se poursuit à l'infini dans la valeur de départ (Violet) à gauche, et se poursuit à l'infini avec la valeur de fin (orange) à droite. Il peut continuer infiniment vers le haut avec ce gradient, et il en est ainsi.

C'est ma compréhension de pourquoi cela apparaît ainsi, une solution consisterait à utiliser un modèle de boîte différent.

4
bitten

Si vous ne souhaitez pas utiliser box-shadow, vous pouvez utiliser border-image et ajustez les couleurs du dégradé: http://jsfiddle.net/9pcuj8bw/5/

.colors {
    width:100px;
    height: 50px;
    background: linear-gradient(to right, 
        #78C5D6,
        #459BA8,
        #79C267,
        #C5D647,
        #F5D63D,
        #F08B33,
        #E868A2,
        #BE61A5) no-repeat;
    border: 10px solid;
    border-image: linear-gradient(to right, 
        #0bc3b8,
        #068e8c,
        #f8c617,
        #ea5f24,
        #b2492c) 1;
}
<div class="colors"></div>

Attention cela ne fonctionne pas sur IE10 ou inférieur: http://caniuse.com/#feat=border-image

3
Wavemaster

Son fonctionne correctement. Vous aviez utilisé une bordure transparente sur un bloc pour voir la couleur bg. Son dégradé linéaire donc sa couleur unie à gauche et à droite. Si vous utilisez une bordure pleine, vous pouvez voir l'effet approprié. http://prntscr.com/7mo5jm

0
Kumar