[CSS]Effet de coin plié, folded corner

NoSmoking

Réalisation d'un effet de coin plié, folded corner en anglais. Cet effet est simple à réaliser et à comprendre.

On va utiliser le pseudo-élément ::before pour créer le coin plié que l'on positionnera et stylera suivant le besoin.

Affichage statique

CSS commun

[class*="folded-corner"] {
  position: relative;             /* pour servir de référent */
}
[class*="folded-corner"]::before {
  content: "";
  position: absolute;
  width: 2em;
  height: 2em;
  border: 1px solid transparent;  /* mise en place d'une bordure */
  border-color: inherit;          /* couleur du parent par défaut */
  background: #FFF;               /* pas vraiment nécessaire */
}

En positionnant le pseudo-élément et en lui affectant un background, nous obtenons :

Corner top left

Lorem ....
.folded-corner-top-left::before {
  top: -1px;                          /* positionnement sur bordure */
  left: -1px;
  border-width: 0 1px 1px 0;
  background: linear-gradient(-45deg, #AAA,#FFF 40%,#999 50%,#FFF 50%);
  box-shadow: 3px 3px 3px #CCC;       /* petit effet d'ombre */
}

Corner top right

Lorem ....
.folded-corner-top-right::before {
  top: -1px;                          /* positionnement sur bordure */
  right: -1px;
  border-width: 0 0 1px 1px;
  background: linear-gradient(45deg, #AAA,#FFF 40%,#999 50%,#FFF 50%);
  box-shadow: -3px 3px 3px #CCC;     /* petit effet d'ombre */
}

Corner bottom right

Lorem ....
.folded-corner-bottom-right::before {
  right: -1px;                        /* positionnement sur bordure */
  bottom: -1px;
  border-width: 1px 0 0 1px;
  background: linear-gradient(135deg, #AAA,#FFF 40%,#999 50%,#FFF 50%);
  box-shadow: -3px -3px 3px #CCC;     /* petit effet d'ombre */
}

Corner bottom left

Lorem ....
.folded-corner-bottom-left::before {
  bottom: -1px;                       /* positionnement sur bordure */
  left: -1px;
  border-width: 1px 1px 0 0;
  background: linear-gradient(225deg, #AAA,#FFF 40%,#999 50%,#FFF 50%);
  box-shadow: 3px -3px 3px #CCC;      /* petit effet d'ombre */
}

Affichage au survol

Si l'on ne souhaite afficher les coins repliés qu'au survol de l'élément, il suffit de déclarer la largeur et la hauteur à 0, et d'ajouter une propriété transition, le CSS initial devient :

[class*="folded-corner"]::before {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border: 1px solid transparent;
  border-color: inherit;
  background: #FFF;
  transition: width .3s,height .3s;
}

Il ne faut bien sûr pas oublier la règle à appliquer au survol :

[class*="folded-corner"]:hover::before {
  width: 3em;
  height: 3em;
}

Il ne reste plus qu'à tester :

Remarques

On utilise un sélecteur « d'attribut », comme [class*="folded-corner"] {}, mais celui-ci est réputé moins performant. Il n'est peut-être pas nécessaire de le conserver si vous n'utilisez qu'une sorte de coin.

On aurait pu utiliser une rotation pour la définition des différents coins, mais lors de l'animation il apparaît des effets indésirables, apparition disparition de la bordure du cadre du conteneur à l'endroit du coin, liés au repositionnement de l'élément en cours de redimensionnement.

Si l'on souhaite avoir une largeur du coin différente de la hauteur il faut recalculer les angles à appliquer au background:linear-gradient(), c'est de la trigonométrie.

// exemple pour hauteur = 1.5 x largeur
const height = 3;
const width = 2;
const alpha = Math.atan(height / width) / Math.PI * 180;
const linearDeg = {
  "top-left": -alpha,             // -56.31...
  "top-right": alpha,             //  56.31...
  "botom-right": 180 - alpha,     // 123.69...
  "bottom-left": 180 + alpha      // 236.31...
};

Si l'on ne veut pas mettre de bordure aux coins il suffit de supprimer la déclaration CSS border:1px solid transparent.

Ressources