Как работают CSS-треугольники? - PullRequest
1756 голосов
/ 16 августа 2011

Существует множество различных форм CSS на Трюки CSS - формы CSS , и я особенно озадачен треугольником:

CSS 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>

Как и почему это работает?

Ответы [ 17 ]

17 голосов
/ 17 июня 2017

ОК, этот треугольник будет создан из-за способа, которым границы элементов работают вместе в HTML и CSS ...

Поскольку мы обычно используем границы размером 1 или 2 пикселя, мы никогда не замечаем, что границы образуют углы 45 ° друг к другу с одинаковой шириной, и, если ширина изменяется, также изменяется степень угла, запустите код CSS, который я создал ниже:

.triangle {
  width: 100px;
  height: 100px;
  border-left: 50px solid black;
  border-right: 50px solid black;
  border-bottom: 100px solid red;
}
<div class="triangle">
</div>

Тогда на следующем шаге у нас нет никакой ширины или высоты, что-то вроде этого:

.triangle {
  width: 0;
  height: 0;
  border-left: 50px solid black;
  border-right: 50px solid black;
  border-bottom: 100px solid red;
}
<div class="triangle">
</div>

И теперь мы делаем левую и правую границы невидимыми, чтобы сделать желаемый треугольник, как показано ниже:

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

Если вы не хотите запускать фрагмент, чтобы увидеть шаги, я создал последовательность изображений, чтобы просмотреть все шаги в одном изображении:

enter image description here

11 голосов
/ 09 марта 2016

CSS clip-path

Я чувствую, что этот вопрос пропущен; clip-path

clip-path в двух словах

Обрезка со свойством clip-path сродни вырезанию фигуры (например, круга или пятиугольника) из прямоугольного листа бумаги. Свойство принадлежит спецификации « CSS Masking Module Level 1 ». В спецификации говорится: «Маскировка CSS предоставляет два средства для частичного или полного скрытия частей визуальных элементов: маскирование и отсечение».


clip-path будет использовать сам элемент, а не его границы, чтобы вырезать форму, указанную в его параметрах. Он использует очень простую систему координат, основанную на процентах, что делает его редактирование очень простым и означает, что вы можете подобрать его и создать странные и прекрасные формы в считанные минуты.


Пример формы треугольника

div {
  -webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
  background: red;
  width: 100px;
  height: 100px;
}
<div></div>

Даунсайд

В настоящий момент у него есть существенный недостаток, один из которых заключается в том, что он в значительной степени не поддерживается, он действительно распространяется только на браузеры -webkit- и не имеет поддержки в IE, и лишь частично в FireFox.


Ресурсы

Вот несколько полезных ресурсов и материалов, которые помогут лучше понять clip-path, а также начать создавать свои собственные.

11 голосов
/ 31 июля 2015

Это старый вопрос, но я думаю, что стоит поделиться, как создать стрелку, используя эту технику треугольника.

Шаг 1:

Давайте создадим 2 треугольника, для второго мы будем использовать псевдокласс :after и расположим его чуть ниже другого:

2 triangles

.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>

Шаг 2

Теперь нам просто нужно установить преобладающий цвет границы второго треугольника на тот же цвет фона:

enter image description here

.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>

Скрипка со всеми стрелками:
http://jsfiddle.net/tomsarduy/r0zksgeu/

9 голосов
/ 27 мая 2015

SASS (SCSS) треугольник миксин

Я написал это для упрощения (и СУХОГО) автоматического создания треугольника 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;
}

пример использования:

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

Страница игровой площадки


Важное примечание:
если треугольник в некоторых браузерах выглядит как с пикселами , попробуйте один из способов, описанных здесь .

8 голосов
/ 06 апреля 2018

Если вы хотите применить границу к треугольнику, прочитайте это: Создать треугольник с помощью CSS?

Почти все ответы сосредоточены на треугольнике, построенном с использованием границыпоэтому я собираюсь разработать метод linear-gradient (который начался в ответе @ lima_fil ).

Использование значения степени, подобного 45°, заставит нас соблюдать определенное отношениеheight/width, чтобы получить желаемый треугольник, и это не будет отзывчивым:

.tri {
  width:100px;
  height:100px;
  background:linear-gradient(45deg, transparent 49.5%,red 50%);
  
  /*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>

Вместо этого мы должны рассмотреть предопределенные значения направления, такие как to bottom, to top и т. Д. В этом случае мы можем получить любой вид треугольникаформа, сохраняя его отзывчивостью.

1) Прямоугольный треугольник

Чтобы получить такой треугольник, нам нужен один линейный градиент и диагональное направление, например to bottom right, to top leftto bottom left и т. Д.

.tri-1,.tri-2 {
  display:inline-block;
  width:100px;
  height:100px;
  background:linear-gradient(to bottom left, transparent 49.5%,red 50%);
  border:1px solid;
  animation:change 2s linear infinite alternate;
}
.tri-2 {
  background:linear-gradient(to top right, transparent 49.5%,red 50%);
  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) равнобедренный треугольник

Для этого нам понадобится 2 линейных градиента, как указано выше, и каждый из них будетвзять половину ширины (или высоты).Как будто мы создаем зеркальное отображение первого треугольника.

.tri {
  display:inline-block;
  width:100px;
  height:100px;
  background-image:
  linear-gradient(to bottom right, transparent 49.5%,red 50%),
  linear-gradient(to bottom left,  transparent 49.5%,red 50%);
  background-size:50.3% 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) равносторонний треугольник

С этим немного сложно справиться, так как нам нужно сохранить связь междувысота и ширина градиента.У нас будет тот же треугольник, что и выше, но мы усложним вычисление, чтобы преобразовать равнобедренный треугольник в равносторонний.

Чтобы упростить его, мы будем считать, что ширина нашего div известнаи высота достаточно велика, чтобы можно было нарисовать наш треугольник внутри (height >= width).

CSS triangle with gradient

У нас есть два градиента g1 иg2, синяя линия - это ширина div w, и каждый градиент будет иметь 50% (w/2), и каждая сторона треугольника должна быть равна w.Зеленая линия - это высота обоих градиентов hg, и мы можем легко получить следующую формулу:

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

Мы можем положиться на calc(), чтобы сделать наш расчет и получить нужный результат:

.tri {
  --w:100px;
  width:var(--w);
  height:100px;
  display:inline-block;
  background-image:
  linear-gradient(to bottom right, transparent 49.5%,red 50%),
  linear-gradient(to bottom left,  transparent 49.5%,red 50%);
  background-size:calc(var(--w)/2 + 0.5px)  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>

Другим способом является управление высотой div и упрощение синтаксиса градиента:

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

4) Случайный треугольник

Чтобы получить случайный треугольник, это просто, так как нам просто нужно удалить условие50% каждого, НО мы должны соблюдать два условия (оба должны иметь одинаковую высоту, а сумма обоих значений ширины должна составлять 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>

Но что, если мы хотим определить значение для каждой стороны?Нам просто нужно снова выполнить расчет!

CSS triangle with gradient

Давайте определим hg1 и hg2 как высоту нашего градиента (оба равныкрасная линия) затем wg1 и wg2 как ширина нашего градиента (wg1 + wg2 = a).Я не буду вдаваться в подробности расчета, но в конце мы получим:

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

Теперь мы достигли предела CSS, так как даже с calc() мы не сможем реализовать это, поэтому нам просто нужно собрать конечный результат вручную и использовать его как фиксированный размер:

.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 49.5%,red 50%),
  linear-gradient(to bottom left,  transparent 49.5%,red 50%);

  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>

Бонус

Мы не должны забывать, что мы также можем применять вращение и / или наклон, и у нас есть больше возможностей, чтобы получить больше треугольника:

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

  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>

И, конечно, мы должны помнить о SVG-решении , которое может быть более подходящим в некоторых ситуациях:

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>
4 голосов
/ 14 декабря 2015

Другие уже объяснили это хорошо.Позвольте мне дать вам анимацию , которая объяснит это быстро: http://codepen.io/chriscoyier/pen/lotjh

Вот код, с которым вы можете поиграть и изучить понятия.

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;
}

Поиграйте с этим и посмотрите, что получится.Установите высоту и ширину на ноль.Затем удалите верхнюю границу и сделайте левый и правый прозрачным, или просто посмотрите на код ниже, чтобы сделать треугольник CSS:

#border-demo {
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 100px solid blue;
}
4 голосов
/ 06 марта 2015

вот еще одна скрипка:

.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/

...