Aller au contenu principal
Partagez ce tutoriel :

Ajouter un coin arrondi à l'arrière-plan d'une bordure

Dernière mise à jour : juin 2023

Introduction

Avez-vous déjà tenté d'ajouter un coin arrondi sur l'arrière-plan d'une bordure ? Si tel est le cas, vous avez sans aucun doute remarqué que cela n'était pas possible.

Ci-dessous, une bordure avec dégradé sans arrondi :



.bordure-sans-arrondi{
	
display: grid;
margin:2rem auto;
height: 25vmin;
width: 25vmin;
border: solid 2ch;
border-image: linear-gradient(hsl(248, 78%, 73%), hsl(180, 64%, 63%)) 1;
	

	}


Si vous tentez d'ajouter la propriété border-radius avec n'importe quelle valeur, vous constatez que rien ne se passe.

Il va donc falloir ruser...


Les masques CSS à la rescousse

Nous allons utiliser les masques CSS (article complet sur ce blog).



.bordure-arrondie{
	
display: grid;
margin:2rem auto;
height: 25vmin;
width: 25vmin;
border: solid 2ch;
border-radius: 2ch;
border-image: linear-gradient(hsl(248, 78%, 73%), hsl(180, 64%, 63%)) 1;
--grad: linear-gradient(red, red);
mask: var(--grad) content-box exclude, var(--grad);
	
	}


Cela fonctionne sur Firefox, mais pas sur Chromium (la propriété mask n'étant pas standardisée). De plus, on constate que sur Firefox, le coin arrondi ne suit pas à l'intérieur de l'élément. Retour à la case départ.

Jusqu'ici nous avions utilisé la propriété border-image pour le dégradé.


Bordure avec background-image

Essayons maintenant avec la propriété background-image, bien que cela nous détourne de l'objectif initial, à savoir utiliser une bordure d'arrière-plan et d'y appliquer un arrondi :




.bordure-arrondie{

margin: 2rem auto;	
display: grid;
border-radius: 3ch;
border: solid 2ch transparent;
width: 25vmin;
height: 25vmin;
background: linear-gradient(hsl(248, 78%, 73%), hsl(180, 64%, 63%)) border-box;
--grad: linear-gradient(red, red);
mask: var(--grad) content-box exclude, var(--grad);
		
		
	}	
	

Dans le code ci-dessus, vous noterez que la bordure est devenue invisible avec la valeur transparent et que le coin arrondi est supérieur à la bordure. Pourquoi ? Regardez plutôt le résultat si le coin arrondi est inférieur à la bordure :

On revient une nouvelle fois à la case départ.

De plus, si la bordure est égale au coin arrondi, nous n'obtenons plus le coin arrondi à l'intérieur de l'élément. Vous devez impérativement déclarer un coin arrondi supérieur à la bordure.

Parfait, en appliquant cette méthode, nous obtenons enfin l'effet désiré ! Ah bah non. Si vous êtes sur Chromium, vous constatez que cela ne fonctionne pas.


Retour aux masques avec mask-composite

L'objectif était d'obtenir une bordure contenant une image, compatible avec un maximum de navigateurs et si possible avec un minimum de code. Jusqu'à présent, ce n'est pas une réussite.

Tentons maintenant d'introduire la propriété mask-composite qui va nous permettre d'effectuer une opération de composition entre le masque situé sur la couche et le masque en dessous de notre élément :




.bordure-arrondie{

margin:2rem auto;	
border-radius: 2ch;
border: solid 2ch transparent;
width: 25vmin;
height: 25vmin;
display: grid;
background: linear-gradient(hsl(248, 78%, 73%), hsl(180, 64%, 63%)) border-box;
--grad: linear-gradient(red, red);
-webkit-mask: var(--grad) content-box, var(--grad);
-webkit-mask-composite: destination-out
		
		
	}	

Cependant, la propriété mask-composite n'est compatible avec Chromium qu'en utilisant sa version non standard avec préfixe. Cela fonctionne sur Chromium, mais pas sur Firefox. Et toujours ce problème de coin arrondi qui n'est pas présent à l'intérieur de l'élément...

Heureusement, Firefox supporte le module CSS Masking Level 1. Donc, nous allons conserver les valeurs non-standard pour Chromium (en attendant le support) et ajouter la valeur exclude à la propriété mask-composite pour Firefox :




.bordure-arrondie{

margin:2rem auto;	
border-radius: 3ch;
border: solid 2ch transparent;
width: 25vmin;
height: 25vmin;
display: grid;
background: linear-gradient(hsl(248, 78%, 73%), hsl(180, 64%, 63%)) border-box;
--grad: linear-gradient(red, red);
-webkit-mask: var(--grad) content-box, var(--grad);
-webkit-mask-composite: destination-out;
mask: var(--grad) content-box, var(--grad);
mask-composite: exclude;
		
		
	}	

Il semblerait que tout fonctionne à merveille.

Mais, car il y a encore un mais, le masque nous empêche de placer du texte à l'intérieur de l'élément, ce qui est plutôt logique dans ce cas-ci. Et une fois de plus, les pseudo-éléments viennent à la rescousse.



	
.bordure-arrondie-texte {

margin:2rem auto;	
width: 25vmin;
height: 25vmin;
display: grid;
place-items:center;
position:relative;
z-index:0
}
	
.bordure-arrondie-texte::before {
content:"";
position:absolute;
z-index:-1;
inset:0;
padding: 2ch;
border-radius: 3ch;
background: linear-gradient(hsl(248, 78%, 73%), hsl(180, 64%, 63%)) border-box;
--grad: linear-gradient(red, red);
-webkit-mask: var(--grad) content-box, var(--grad);
-webkit-mask-composite: destination-out;
mask-composite: exclude;
}	
		


Bonus : animation et transition CSS

Petit bonus, parce que ce tutoriel était assez pénible, autant se faire plaisir à présent avec les transitions et animations CSS :

Exemple avec transition :



	
@property --angle{
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}
		
.bordure-arrondie-all-trans{

--angle: 0;
margin: 2rem auto;	
border-radius: 3ch;
border: solid 2ch transparent;
width: 25vmin;
height: 25vmin;
display: grid;
background: linear-gradient(var(--angle),hsl(var(--couleur1)), hsl(var(--couleur1-bis))) border-box;
--grad: linear-gradient(red, red);
-webkit-mask: var(--grad) content-box, var(--grad);
-webkit-mask-composite: destination-out;
mask-composite: exclude;
transition: --angle 1s;
}	
	

.bordure-arrondie-all-trans:hover{
	
--angle: 360deg
	
	
	}
	
		

Ci-dessous, le même exemple mais avec les animations CSS :




@property --angle1 {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}	
	
.bordure-arrondie-all-anim{

--angle1: 0;
margin: 2rem auto;	
border-radius: 3ch;
border: solid 2ch transparent;
width: 25vmin;
height: 25vmin;
display: grid;
background: linear-gradient(var(--angle1),hsl(var(--couleur1)), hsl(var(--couleur1-bis))) border-box;
--grad: linear-gradient(red, red);
-webkit-mask: var(--grad) content-box, var(--grad);
-webkit-mask-composite: destination-out;
mask-composite: exclude;
animation: 2s rotate linear infinite;

}		
	
	
	
@keyframes rotate {

  to {
	
    --angle1: 360deg;
  }
}	


Mais (encore une fois), cela ne fonctionne que sur Chromium pour l'instant.