top - Comment fonctionnent les triangles CSS?




triangle top right css (12)

CSS Triangles: une tragédie en cinq actes

Comme alex dit , les frontières de largeur égale butt contre l'autre à des angles de 45 degrés:

Lorsque vous n'avez pas de bordure supérieure, cela ressemble à ceci:

Ensuite, vous lui donnez une largeur de 0 ...

... et une hauteur de 0 ...

... et enfin, vous rendez les deux bords latéraux transparents:

Cela résulte en un triangle.

Il y a beaucoup de différentes formes CSS sur CSS Tricks - Formes de CSS et je suis particulièrement intrigué par un triangle:

#triangle-up {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
}
<div id="triangle-up"></div>

Comment et pourquoi ça marche?


SASS (SCSS) triangle mixin

J'ai écrit ceci pour le rendre plus facile (et DRY) pour générer automatiquement un triangle CSS:

// Triangle helper mixin (by Yair Even-Or)
// @param {Direction} $direction - either `top`, `right`, `bottom` or `left`
// @param {Color} $color [currentcolor] - Triangle color
// @param {Length} $size [1em] - Triangle size
@mixin triangle($direction, $color: currentcolor, $size: 1em) {
  $size: $size/2;
  $transparent: rgba($color, 0);
  $opposite: (top:bottom, right:left, left:right, bottom:top);

  content: '';
  display: inline-block;
  width: 0;
  height: 0;
  border: $size solid $transparent;
  border-#{map-get($opposite, $direction)}-color: $color;
  margin-#{$direction}: -$size;
}

exemple de cas d'utilisation:

span {
  @include triangle(bottom, red, 10px);
}

Playground page

Note importante:
Si le triangle semble pixellisé dans certains navigateurs, essayez l'une des méthodes décrites here .


C'est une vieille question, mais je pense que ça vaudra la peine de partager comment créer une flèche en utilisant cette technique de triangle.

Étape 1:

Permet de créer 2 triangles, pour le second nous utiliserons la classe pseudo :after et la positionnerons juste en dessous de l'autre:

.arrow{
    width: 0;
    height: 0;
    border-radius: 50px;
    display: inline-block;
    position: relative;
}

    .arrow:after{
        content: "";
        width: 0;
        height: 0;
        position: absolute;
    }


.arrow-up{
     border-left: 50px solid transparent;
     border-right: 50px solid transparent;
     border-bottom: 50px solid #333;
}
    .arrow-up:after{
         top: 5px;
         border-left: 50px solid transparent;
         border-right: 50px solid transparent;
         border-bottom: 50px solid #ccc;
         right: -50px;
    }
<div class="arrow arrow-up"> </div>

Étape 2

Maintenant, nous devons juste définir la couleur de la bordure prédominante du second triangle à la même couleur de l'arrière-plan:

.arrow{
    width: 0;
    height: 0;
    border-radius: 50px;
    display: inline-block;
    position: relative;
}

    .arrow:after{
        content: "";
        width: 0;
        height: 0;
        position: absolute;
    }


.arrow-up{
     border-left: 50px solid transparent;
     border-right: 50px solid transparent;
     border-bottom: 50px solid #333;
}
    .arrow-up:after{
         top: 5px;
         border-left: 50px solid transparent;
         border-right: 50px solid transparent;
         border-bottom: 50px solid #fff;
         right: -50px;
    }
<div class="arrow arrow-up"> </div>

Fiddle avec toutes les flèches:
http://jsfiddle.net/tomsarduy/r0zksgeu/


Commencez avec un carré de base et des frontières. Chaque bordure aura une couleur différente afin que nous puissions les différencier:

.triangle {
    border-color: yellow blue red green;
    border-style: solid;
    border-width: 200px 200px 200px 200px;
    height: 0px;
    width: 0px;
}

ce qui vous donne this :

this

Mais il n'y a pas besoin de la bordure supérieure, alors définissez sa largeur à 0px . Maintenant, notre bas-frontière de 200px rendra notre triangle 200px grand.

.triangle {
    border-color: yellow blue red green;
    border-style: solid;
    border-width: 0px 200px 200px 200px;
    height: 0px;
    width: 0px;
}

et nous aurons this :

this

Ensuite, pour masquer les deux triangles latéraux, définissez la couleur de la bordure sur transparent. Étant donné que la bordure supérieure a été effacée, nous pouvons également définir la couleur border-top en transparence.

.triangle {
    border-color: transparent transparent red transparent;
    border-style: solid;
    border-width: 0px 200px 200px 200px;
    height: 0px;
    width: 0px;
}

finalement nous obtenons this :

this


D'autres ont déjà bien expliqué cela. Laissez-moi vous donner une animation qui vous expliquera rapidement: http://codepen.io/chriscoyier/pen/lotjh

Voici un code pour jouer avec et apprendre les concepts.

HTML:

<html>
  <body>
    <div id="border-demo">
    </div>
  </body>
</html>

CSS:

/*border-width is border thickness*/
#border-demo {
    background: gray;
    border-color: yellow blue red green;/*top right bottom left*/
    border-style: solid;
    border-width: 25px 25px 25px 25px;/*top right bottom left*/
    height: 50px;
    width: 50px;
}

Jouez avec cela et voyez ce qui se passe. Réglez la hauteur et la largeur à zéro. Ensuite, supprimez la bordure supérieure et faites-la transparente à gauche ou à droite, ou regardez simplement le code ci-dessous pour créer un triangle css:

#border-demo {
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 100px solid blue;
}

Disons que nous avons le div suivant:

<div id="triangle" />

Maintenant, éditez le CSS étape par étape, de sorte que vous aurez une idée claire de ce qui se passe autour

ÉTAPE 1: JSfiddle Link:

 #triangle {
        background: purple;
        width :150px;
        height:150PX;
        border-left: 50px solid black ;
        border-right: 50px solid black;
        border-bottom: 50px solid black;
        border-top: 50px solid black;
    }

Ceci est une div simple. Avec un CSS très simple. Donc, un profane peut comprendre. Div a des dimensions de 150 x 150 pixels avec la bordure de 50 pixels. L'image est jointe:

ÉTAPE 2: JSfiddle Link:

#triangle {
    background: purple;
    width :150px;
    height:150PX;
    border-left: 50px solid yellow ;
    border-right: 50px solid green;
    border-bottom: 50px solid red;
    border-top: 50px solid blue;
}

Maintenant, je viens de changer la couleur de la bordure de tous les 4 côtés. L'image est attachée.

ÉTAPE: 3 JSfiddle Link:

#triangle {
    background: purple;
    width :0;
    height:0;
    border-left: 50px solid yellow ;
    border-right: 50px solid green;
    border-bottom: 50px solid red;
    border-top: 50px solid blue;
}

Maintenant, je viens de changer la hauteur et la largeur de div de 150 pixels à zéro. L'image est attachée

ÉTAPE 4: JSfiddle:

#triangle {
    background: purple;
    width :0px;
    height:0px;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 50px solid red;
    border-top: 50px solid transparent;
}

Maintenant j'ai rendu toutes les frontières transparentes à l'exception de la bordure inférieure. L'image est attachée ci-dessous.

ÉTAPE 5: JSfiddle Link:

#triangle {
    background: white;
    width :0px;
    height:0px;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 50px solid red;
    border-top: 50px solid transparent;
}

Maintenant, je viens de changer la couleur de fond en blanc. L'image est attachée.

D'où nous avons eu le triangle dont nous avions besoin.



Les bordures utilisent un bord incliné où elles se croisent (angle de 45 ° avec des bordures de largeur égale, mais la modification des largeurs de bordure peut fausser l'angle).

jsFiddle .

En masquant certaines bordures, vous pouvez obtenir l'effet triangle (comme vous pouvez le voir ci-dessus en rendant les différentes parties différentes couleurs). transparent est souvent utilisé comme une couleur de bord pour atteindre la forme du triangle.


Presque toutes les réponses se concentrent sur le triangle construit en utilisant la bordure, donc je vais élaborer la méthode linéaire-gradient (comme commencé dans la réponse de @lima_fil ).

L'utilisation d'une valeur de degré de 45 ° nous obligera à respecter un rapport de taille spécifique afin d'obtenir le triangle que nous voulons et cela ne sera pas réceptif:

.tri {
  width:100px;
  height:100px;
  background:linear-gradient(45deg, transparent 50%,red 0);
  
  /*To illustrate*/
  border:1px solid;
}
Good one
<div class="tri"></div>
bad one
<div class="tri" style="width:150px"></div>
bad one
<div class="tri" style="height:30px"></div>

Au lieu de faire cela, nous devrions considérer des valeurs de direction prédéfinies comme to bottom , to top , etc. Dans ce cas, nous pouvons obtenir n'importe quelle forme de triangle tout en restant réactif.

1) Triangle rectangle

Pour obtenir un tel triangle, nous avons besoin d'une direction linéaire et diagonale comme to bottom right , to top left , to bottom left , etc.

.tri-1,.tri-2 {
  display:inline-block;
  width:100px;
  height:100px;
  background:linear-gradient(to bottom left, transparent 50%,red 0);
  border:1px solid;
  animation:change 2s linear infinite alternate;
}
.tri-2 {
  background:linear-gradient(to top right, transparent 50%,red 0);
  border:none;
}

@keyframes change {
  from {
    width:100px;
    height:100px;
  }
  to {
    height:50px;
    width:180px;
  }
}
<div class="tri-1"></div>
<div class="tri-2"></div>

2) triangle isocèle

Pour celui-ci nous aurons besoin de 2 gradient-linéaire comme ci-dessus et chacun prendra la moitié de la largeur (ou de la hauteur). C'est comme si nous créons une image miroir du premier triangle.

.tri {
  display:inline-block;
  width:100px;
  height:100px;
  background-image:
  linear-gradient(to bottom right, transparent 50%,red 0),
  linear-gradient(to bottom left, transparent 50%,red 0);
  background-size:50.9% 100%; /* I use a value slightly bigger than 50% to avoid having a small gap between both gradient*/
  background-position:left,right;
  background-repeat:no-repeat;
  
  animation:change 2s linear infinite alternate;
}


@keyframes change {
  from {
    width:100px;
    height:100px;
  }
  to {
    height:50px;
    width:180px;
  }
}
<div class="tri"></div>

3) triangle équilatéral

Celui-ci est un peu délicat à gérer car nous devons garder une relation entre la hauteur et la largeur du dégradé. Nous aurons le même triangle que précédemment mais nous rendrons le calcul plus complexe pour transformer le triangle isocèle en triangle équilatéral.

Pour le rendre facile, nous considérerons que la largeur de notre div est connue et que la hauteur est assez grande pour pouvoir dessiner notre triangle ( height >= width ).

Nous avons nos deux gradient g1 et g2 , la ligne bleue est la largeur du div w et chaque gradient en aura 50% ( w/2 ) et chaque côté du triangle devrait être égal à w . La ligne verte est la hauteur des deux gradient hg et nous pouvons facilement obtenir la formule ci-dessous:

(w/2)² + hg² = w² ---> hg = (sqrt(3)/2) * w ---> hg = 0.866 * w

Nous devons donc nous appuyer sur cacl() pour faire notre calcul et obtenir le résultat nécessaire:

.tri {
  --w:100px;
  width:var(--w);
  height:100px;
  display:inline-block;
  background-image:
  linear-gradient(to bottom right, transparent 50%,red 0),
  linear-gradient(to bottom left, transparent 50%,red 0);
  background-size:calc(var(--w)/2 + 0.5%)  calc(0.866 * var(--w));
  background-position:
    left bottom,right bottom;
  background-repeat:no-repeat;
  
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>

4) Triangle aléatoire

Pour obtenir un triangle aléatoire, c'est facile car il suffit de supprimer la condition de 50% de chacun, MAIS on devrait garder deux conditions (les deux devraient avoir la même hauteur et la somme des deux devrait être de 100%).

.tri-1 {
  width:100px;
  height:100px;
  display:inline-block;
  background-image:
  linear-gradient(to bottom right, transparent 50%,red 0),
  linear-gradient(to bottom left, transparent 50%,red 0);
  background-size:20% 60%,80% 60%;
  background-position:
    left bottom,right bottom;
  background-repeat:no-repeat;
  
 
}
<div class="tri-1"></div>

Mais que faire si nous voulons définir une valeur pour chaque côté? Nous avons simplement besoin de faire des calculs à nouveau!

Définissons hg1 et hg2 comme la hauteur de notre gradient (les deux sont égaux à la ligne rouge) puis wg1 et wg2 comme largeur de notre gradient ( wg1 + wg2 = a ). Je ne vais pas détailler le calcul mais à la fin nous aurons:

wg2 = (a²+c²-b²)/(2a)
wg1 = a - wg2
hg1 = hg2 = sqrt(b² - wg1²) = sqrt(c² - wg2²)

Maintenant nous avons atteint la limite de CSS car même avec calc() nous ne pourrons pas implémenter ceci, donc nous avons simplement besoin de rassembler le résultat final manuellement et de l'utiliser comme taille fixe:

.tri {
  --wg1: 20px; 
  --wg2: 60px;
  --hg:30px; 
  width:calc(var(--wg1) + var(--wg2));
  height:100px;
  display:inline-block;
  background-image:
  linear-gradient(to bottom right, transparent 50%,red 0),
  linear-gradient(to bottom left, transparent 50%,red 0);

  background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
  background-position:
    left bottom,right bottom;
  background-repeat:no-repeat;
  
}
<div class="tri" ></div>

<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>

Prime

Nous ne devrions pas oublier que nous pouvons également appliquer la rotation et / ou l'inclinaison et nous avons plus d'option pour obtenir plus de triangle:

.tri {
  --wg1: 20px; 
  --wg2: 60px;
  --hg:30px; 
  width:calc(var(--wg1) + var(--wg2));
  height:100px;
  display:inline-block;
  background-image:
  linear-gradient(to bottom right, transparent 50%,red 0),
  linear-gradient(to bottom left, transparent 50%,red 0);

  background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
  background-position:
    left bottom,right bottom;
  background-repeat:no-repeat;
  
}
<div class="tri" ></div>

<div class="tri" style="transform:skewY(25deg)"></div>

<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>


<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;transform:rotate(20deg)" ></div>

Et bien sûr, nous devrions garder à l'esprit la solution SVG qui peut être plus appropriée dans certaines situations:

svg {
 width:100px;
 height:100px;
}

polygon {
  fill:red;
}
<svg viewBox="0 0 100 100"><polygon points="0,100 0,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,23 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="20,60 50,43 80,100" /></svg>


Une approche différente. Avec gradient linéaire (pour IE, seulement IE 10+). Vous pouvez utiliser n'importe quel angle:

.triangle {
    margin: 50px auto;
    width: 100px;
    height: 100px;
/* linear gradient */
    background: -moz-linear-gradient(-45deg,  rgba(255,0,0,0) 0%, rgba(255,0,0,0) 50%, rgba(255,0,0,1) 50%, rgba(255,0,0,1) 100%);
 /* FF3.6+ */
    background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,1)), color-stop(100%,rgba(255,0,0,1)));
 /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(-45deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
 /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(-45deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
 /* Opera 11.10+ */
    background: -ms-linear-gradient(-45deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
 /* IE10+ */
    background: linear-gradient(135deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
 /* W3C */;
}
<div class="triangle"></div>

Voici jsfiddle


Voici une animation dans JSFiddle que j'ai créée pour la démonstration.

Voir aussi l'extrait ci-dessous.

Ceci est un GIF animé à partir d'un Screencast

transforms = [
         {'border-left-width'   :'30', 'margin-left': '70'},
         {'border-bottom-width' :'80'},
         {'border-right-width'  :'30'},
         {'border-top-width'    :'0', 'margin-top': '70'},
         {'width'               :'0'},
         {'height'              :'0', 'margin-top': '120'},
         {'borderLeftColor'     :'transparent'},
         {'borderRightColor'    :'transparent'}
];


$('#a').click(function() {$('.border').trigger("click");});
(function($) {
    var duration = 1000
    $('.border').click(function() {
		  for ( var i=0; i < transforms.length; i++ ) {
        $(this)
         .animate(transforms[i], duration)
		  }
    }).end()
}(jQuery))
.border {
    margin: 20px 50px;
    width: 50px;
    height: 50px;
    border-width: 50px;
    border-style: solid;
    border-top-color: green;
    border-right-color: yellow;
    border-bottom-color: red;
    border-left-color: blue;
    cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>

Version aléatoire

/**
 * Randomize array element order in-place.
 * Using Durstenfeld shuffle algorithm.
 */
function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

transforms = [
         {'border-left-width'   :'30', 'margin-left': '70'},
         {'border-bottom-width' :'80'},
         {'border-right-width'  :'30'},
         {'border-top-width'    :'0', 'margin-top': '70'},
         {'width'               :'0'},
         {'height'              :'0'},
         {'borderLeftColor'     :'transparent'},
         {'borderRightColor'    :'transparent'}
];
transforms = shuffleArray(transforms)



$('#a').click(function() {$('.border').trigger("click");});
(function($) {
    var duration = 1000
    $('.border').click(function() {
		  for ( var i=0; i < transforms.length; i++ ) {
        $(this)
         .animate(transforms[i], duration)
		  }
    }).end()
}(jQuery))
.border {
    margin: 50px;
    width: 50px;
    height: 50px;
    border-width: 50px;
    border-style: solid;
    border-top-color: green;
    border-right-color: yellow;
    border-bottom-color: red;
    border-left-color: blue;
    cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>

Version à la fois

$('#a').click(function() {$('.border').trigger("click");});
(function($) {
    var duration = 1000
    $('.border').click(function() {
        $(this)
         .animate({'border-top-width': 0            ,
         					 'border-left-width': 30          ,
         					 'border-right-width': 30         ,
         					 'border-bottom-width': 80        ,
         					 'width': 0                       ,
         					 'height': 0                      ,
                   'margin-left': 100,
                   'margin-top': 150,
         					 'borderTopColor': 'transparent',
         					 'borderRightColor': 'transparent',
         					 'borderLeftColor':  'transparent'}, duration)
    }).end()
}(jQuery))
.border {
    margin: 50px;
    width: 50px;
    height: 50px;
    border-width: 50px;
    border-style: solid;
    border-top-color: green;
    border-right-color: yellow;
    border-bottom-color: red;
    border-left-color: blue;
    cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>


voici un autre violon:

.container:after {
    position: absolute;
    right: 0;
    content: "";
    margin-right:-50px;
    margin-bottom: -8px;
    border-width: 25px;
    border-style: solid;
    border-color: transparent transparent transparent #000;
    width: 0;
    height: 0;
    z-index: 10;
    -webkit-transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
    transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
    bottom: 21px;
}
.container {
    float: left;
    margin-top: 100px;
    position: relative;
    width: 150px;
    height: 80px;
    background-color: #000;
}

.containerRed {
    float: left;
    margin-top: 100px;
    position: relative;
    width: 100px;
    height: 80px;
    background-color: red;
}

https://jsfiddle.net/qdhvdb17/





css-shapes