web-dev-qa-db-fra.com

Comment faire un triangle arrondi à 3 coins en CSS

J'aimerais obtenir une forme de couleur personnalisée comme celle-ci sans Javascript: 3 corner rounded triangle

Actuellement, je superpose une image du "cadre" sur un div rectangulaire orange, mais c'est assez hacky. Je suppose que je pourrais utiliser un élément de canevas généré dynamiquement, mais cela nécessite non seulement JS, mais le support de canevas HTML5. Des idées?

35
Murray Smith

Ma meilleure tentative: http://dabblet.com/Gist/4592062 final

La perfection des pixels à toutes les tailles, utilise des mathématiques plus simples que la solution originale d'Ana et est plus intuitive à mon avis :)

.triangle {
        position: relative;
        background-color: orange;
        text-align: left;
}
.triangle:before,
.triangle:after {
        content: '';
        position: absolute;
        background-color: inherit;
}
.triangle,
.triangle:before,
.triangle:after {
        width:  10em;
        height: 10em;
        border-top-right-radius: 30%;
}

.triangle {
        transform: rotate(-60deg) skewX(-30deg) scale(1,.866);
}
.triangle:before {
        transform: rotate(-135deg) skewX(-45deg) scale(1.414,.707) translate(0,-50%);
}
.triangle:after {
        transform: rotate(135deg) skewY(-45deg) scale(.707,1.414) translate(50%);
}
<div class="triangle"></div>
90
Murray Smith

démo dabblet

.triangle, .triangle:before, .triangle:after { width: 4em; height: 4em; }
.triangle {
        overflow: hidden;
        position: relative;
        margin: 7em auto 0;
        border-radius: 20%;
        transform: translateY(50%) rotate(30deg) skewY(30deg) scaleX(.866);
        cursor: pointer;
        pointer-events: none;
} 
.triangle:before, .triangle:after {
        position: absolute;
        background: orange;
        pointer-events: auto;
        content: '';
}
.triangle:before {
        border-radius: 20% 20% 20% 53%;
        transform: scaleX(1.155) skewY(-30deg) rotate(-30deg) translateY(-42.3%) 
                        skewX(30deg) scaleY(.866) translateX(-24%);
}
.triangle:after {
        border-radius: 20% 20% 53% 20%;
        transform: scaleX(1.155) skewY(-30deg) rotate(-30deg) translateY(-42.3%) 
                        skewX(-30deg) scaleY(.866) translateX(24%);
}

/** extra styles to show how it works **/

.triangle:hover { overflow: visible; }
.triangle:hover:before, .triangle:hover:after { background: none; }
.triangle:hover, .triangle:hover:before, .triangle:hover:after {
        border: dashed 1px;
}
<div class='triangle'></div>

L'idée est vraiment simple: vous appliquez d'abord une série de transformations à votre .triangle élément (qui a overflow: hidden; - vous pouvez supprimer cela pour voir ce qui se passe;)) afin d'obtenir un losange.

Ensuite, vous appliquez les mêmes transformations au :before et :after pseudo-éléments, plus quelques autres pour les rendre également rhomboïdaux.

Et à la fin, vous avez trois losanges qui se croisent, la forme orange étant leur intersection. Survolez le triangle pour voir les formes qui se croisent;)

Il évolue bien, il suffit de changer le width et le height du .triangle élément.

Pour Firefox, Chrome et Safari, seul le triangle orange aux coins arrondis est sensible au survol (grâce à pointer-events: none; sur le .triangle élément et pointer-events: auto; sur les pseudo-éléments). Sinon, cela pourrait être réalisé en enveloppant .triangle dans un élément ayant les mêmes width et height (et les mêmes border-radius) et overflow: hidden;.


Remarques

  • Vous pouvez également le faire avec des dégradés CSS. Cependant, contrairement aux transformations 2D , les dégradés CSS ne fonctionneront pas dans IE9 .
  • J'aurais aimé ne pas avoir à déséquilibrer les pseudo-élémets qui héritent du biais de leurs parents uniquement pour les biaiser à nouveau après une rotation, mais cela ne semble pas fonctionner autrement.
24
Ana

Utilisez une image quelconque. C'est à ça que servent les images. Si vous en avez besoin pour évoluer, SVG est un bon choix , sinon, utilisez simplement un png comme arrière-plan, ou un <img> élément s'il fait partie du contenu.

Si vous devez absolument l'avoir dans un fichier CSS, vous pouvez essayer data: urls (non pris en charge dans IE7 et ci-dessous) .

9
zzzzBov

Joué avec Murray Smiths la version la plus votée. Je l'ai écrit en tant que mixage de stylet et corrigé certains problèmes de marge et ajouté une option de direction. Le mixin redimensionne également le triangle à une taille légèrement pixelisée. Pas très bien testé. Utiliser avec précaution

http://codepen.io/perlundgren/pen/VYGdwX

    triangle(direction = up, color = #333, size = 32px)
        position: relative
        background-color: color
        width:  2*(round(size/3.25))
        height: 2*(round(size/3.25))
        border-top-right-radius: 30%
        &:before,
        &:after
          content: ''
          position: absolute
          background-color: inherit
          width:  2*(round(size/3.25))
          height: 2*(round(size/3.25))
          border-top-right-radius: 30%

        if direction is up
          transform: rotate(-60deg) skewX(-30deg) scale(1,.866)
          margin: (@width/4) (@width/2.5) (@width/1.2) (@width/2.5)

        if direction is down
          transform: rotate(-120deg) skewX(-30deg) scale(1,.866)
          margin: 0 (@width/1.5) (@width/1.5) (@width/6)

        if direction is left
          transform: rotate(-30deg) skewX(-30deg) scale(1,.866)
          margin: (@width/5) 0 (@width) (@width/1.4)

        if direction is right
          transform: rotate(-90deg) skewX(-30deg) scale(1,.866)
          margin: (@width/5) (@width/1.4) (@width) 0

        &:before
          transform: rotate(-135deg) skewX(-45deg) scale(1.414,.707) translate(0,-50%)
        &:after
          transform: rotate(135deg) skewY(-45deg) scale(.707,1.414) translate(50%)

puis ajoutez simplement le mixin à votre classe

    .triangle
      &.up
        triangle()
      &.down
        triangle(down)
      &.left
        triangle(left)
      &.right
        triangle(right)
5
Per Lundgren

La réponse d'Ana m'a inspiré à essayer une autre approche, qui est tout aussi loin d'être parfaite, mais au moins symétrique. Voici un aperçu en taille réelle et agrandi. Il s'agit simplement d'un triangle de hack de bordure enveloppé dans un cercle de détourage/rayon de bordure:

Preview

Et le code (ajustez la taille globale via un simple font-size propriété):

.triangle {
    font-size: .8em;
    position: relative;
    width: 3.8em;
    height: 3.8em;
    text-align: center;
    margin: 10% auto 0;
    overflow: hidden;
    border-radius: 100%;
} 
.triangle:before {
    content: '';
    position: absolute;
    width:0;
    height: 0;
    border: solid 2em transparent;
    border-bottom-color: orange;
    border-bottom-width: 3.2em;
    border-top-width: 0;
    margin: -.3em -2em;
}

Jouez avec ici: http://dabblet.com/Gist/4590714

5
Murray Smith

J'ai vu qu'il y avait quelqu'un qui demandait un triangle isocèle et à travers une falsification de la réponse acceptée ci-dessus, j'ai trouvé comment le manipuler pour obtenir ce que je voulais, étant donné que j'avais besoin du même. Cela devrait aider tous ceux qui recherchent un léger changement dans le triangle aux coins arrondis.

Vous remarquerez que j'ai séparé la largeur, la hauteur et le rayon en haut à droite, puis j'ai changé le rayon en haut à droite pour façonner les coins. La seule autre chose que j'ai modifiée était la propriété transform directement sur l'élément. Vous pouvez le façonner comme bon vous semble, mais ceux-ci semblent être les seuls changements nécessaires.

.diff-arrow {
  margin-left:30px;
  position: relative;
  background-color: #20C0F1;
  text-align: left;
  width: 10em;
  height: 10em;
  border-top-right-radius: 20%;
}

.diff-arrow:before,
.diff-arrow:after {
  content: '';
  position: absolute;
  background-color: inherit;
  width: 10em;
  height: 10em;
  border-top-right-radius: 15%;
}

.diff-arrow {
  transform: rotate(-45deg) skewX(0deg) scale(0.5);
}

.diff-arrow:before {
  transform: rotate(-135deg) skewX(-45deg) scale(1.414, .707) translate(0, -50%);
}

.diff-arrow:after {
  transform: rotate(135deg) skewY(-45deg) scale(.707, 1.414) translate(50%);
}
<div class="diff-arrow"></div>
1
Jester