Отзывчивый треугольник CSS с шириной в процентах

Код ниже создаст стрелку прямо под элементом <a>:

JSFiddle

.btn {
    position: relative;
    display: inline-block;
    width: 100px;
    height: 50px;
    text-align: center;
    color: white;
    background: gray;
    line-height: 50px;
    text-decoration: none;
}
.btn:after {
    content: "";
    position: absolute;
    bottom: -10px;
    left: 0;
    width: 0;
    height: 0;
    border-width: 10px 50px 0 50px;
    border-style: solid;
    border-color: gray transparent transparent transparent;   
}
<a href="#" class="btn">Hello!</a>

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

Как сделать адаптивный треугольник на процентной основе?


person sdvnksv    schedule 18.08.2014    source источник
comment
Связанный вопрос: Как я могу использовать проценты в свойствах border-*?   -  person Zach Saucier    schedule 19.08.2014


Ответы (7)


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

DEMO (измените размер окна результатов, чтобы увидеть, как оно реагирует)

Треугольник поддерживает соотношение сторон с помощью свойства padding-bottom.

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

.btn {
  position: relative;
  display: inline-block;
  height: 50px; width: 50%;
  text-align: center;
  color: white;
  background: gray;
  line-height: 50px;
  text-decoration: none;
  padding-bottom: 15%;
  background-clip: content-box;
  overflow: hidden;
}
.btn:after {
  content: "";
  position: absolute;
  top:50px;  left: 0;
  background-color: inherit;
  padding-bottom: 50%;
  width: 57.7%;
  z-index: -1;
  transform-origin: 0 0;
  transform: rotate(-30deg) skewX(30deg);
}
/** FOR THE DEMO **/

body {
  background: url('http://i.imgur.com/qi5FGET.jpg');
  background-size: cover;
}
<a href="#" class="btn">Hello!</a>

Дополнительную информацию об адаптивных треугольниках и о том, как их создавать, см. в разделе Треугольники с поворотом преобразования< /strong> (простые и причудливые отзывчивые треугольники)

person web-tiki    schedule 18.08.2014
comment
Хотя это решение работает в этом случае, я просто хочу указать другим, что оно будет работать только на белом (или сплошном цвете) фоне из-за вашего border-top:300px solid #fff; используется, чтобы скрыть остальную часть повернутого квадрата :after. - person GreatBlakes; 23.03.2015
comment
@GreatBlakes спасибо за указание на это, я решил проблему и отредактировал ответ. Верхняя граница больше не нужна, остальная часть псевдоэлемента :after скрыта с помощью overflow:hidden;. - person web-tiki; 24.03.2015

Другим решением этой проблемы может быть использование CSS clip-path для вырезания треугольника из цветного блока. Однако нет поддержки IE, но его можно использовать для внутренних инструментов и т. д.

ДЕМО

Написано с помощью SCSS для простоты.

.outer {
  background: orange;
  width: 25%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 1em;

  p {
    margin: 0;
    text-align: center;
    color: #fff;
  }

  &:after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0; 
    right: 0;
    padding-bottom: 10%;
    background: orange;
    -webkit-clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
    clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
  }

}
person Probocop    schedule 18.09.2015
comment
Это намного чище, чем выбранный ответ. Примите голосование и сердечное рукопожатие. - person dmbaughman; 14.03.2019
comment
Действительно, это идеальный ответ. - person Shashank Bhatt; 30.04.2019
comment
это решение идеально, так прямолинейно и просто - person Vincent Tang; 28.01.2020
comment
Это здорово, но не работает в Safari/Mac :( - person tsi; 07.04.2020

Я нашел решение, которое работает с любой шириной/высотой. Вы можете использовать два псевдоэлемента с фоном linear-gradient, например, (fiddle):

.btn {
    position: relative;
    display: inline-block;
    width: 100px;
    height: 50px;
    text-align: center;
    color: white;
    background: gray;
    line-height: 50px;
    text-decoration: none;
}
.btn:before {
    content: "";
    position: absolute;
    top: 100%;
    right: 0;
    width: 50%;
    height: 10px;
    background: linear-gradient(to right bottom, gray 50%, transparent 50%)
}

.btn:after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    width: 50%;
    height: 10px;
    background: linear-gradient(to left bottom, gray 50%, transparent 50%)
}
person Alexandr Subbotin    schedule 10.08.2015
comment
это хорошая идея, но края действительно "рваны" - person Will Jenkins; 17.05.2018

Модифицированная версия приведенного ниже кода может помочь вам достичь этого.

HTML

<div class="triangle-down"></div>

CSS

.triangle-down {
    width: 10%;
    height: 0;
    padding-left:10%;
    padding-top: 10%;
    overflow: hidden;
}
.triangle-down:after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    margin-left:-500px;
    margin-top:-500px;
    
    border-left: 500px solid transparent;
    border-right: 500px solid transparent;
    border-top: 500px solid #4679BD;
}

Дополнительные сведения об адаптивных треугольниках: треугольники CSS. сделал адаптивным (ссылка в архиве)

person lessismore    schedule 19.08.2014
comment
Это не отвечает. - person Zach Saucier; 19.08.2014
comment
это отзывчиво. Вы можете посмотреть здесь. - person lessismore; 20.08.2014
comment
@lessismore Это довольно волшебно, но как насчет настройки формата стрелки? Возможно ли это или соотношение 1x1 единственный способ? - person mmm; 16.08.2016

Я попробовал другие ответы и обнаружил, что они слишком сложны и / или громоздки, чтобы манипулировать формой треугольника. Вместо этого я решил создать простую треугольную форму в виде svg.

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

html, body{
  height:100%;
  width:100%;
}
.outer{
  width:20%;
  height:25%;
  background:red;
  position:relative;
  
}
.inner{
  height:100%;
  width:100%;
  background-color:red;
}
.triangle-down{
  height:25%;
  width:100%;
  position:relative;
}
.triangle-down svg{
  height:100%;
  width:100%;
  position:absolute;
  top:0;
}
svg .triangle-path{
  fill:red;
}
<div class="outer">
<div class="inner"></div>
  <div class="triangle-down">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 2 1">
 <g>
  <path class="triangle-path" d="M0,0 l2,0 l-1,1 z" />
 </g>
</svg>
</div>

Протестировано FF, Chrome, IE, Edge, моб Safari и моб хром

person Will Jenkins    schedule 17.05.2018

Другой вариант — использовать градиенты фоновой подложки и гибкое позиционирование, чтобы убедиться, что треугольник всегда масштабируется до своего родительского контейнера. Независимо от того, насколько широким или узким вы сделаете этот контейнер, треугольник всегда масштабируется вместе с ним. Вот скрипка:

https://jsfiddle.net/29k4ngzr/

<div class="triangle-wrapper-100">
<div class="triangle-left"></div>
<div class="triangle-right"></div>
</div>

.triangle-wrapper-100 {
      width: 100%;
    height: 100px;
    display:flex;
    flex-direction: column;
    flex-wrap: wrap;
}
.triangle-right {
    right: 0px;
    background: linear-gradient(to right bottom, #6940B5 50%, transparent 50%);
    width: 50%;
    height: 100px;
}
.triangle-left {
    left: 0px;
    background: linear-gradient(to right bottom, #6940B5 50%, transparent 50%);
    width: 50%;
    height: 100px;
    transform: scaleX(-1);
}
person brett m    schedule 07.05.2020

Я взял ответ @Probocop и придумал следующее:

<style>
    .btn {
        background-color: orange;
        color: white;
        margin-bottom: 50px;
        padding: 15px;
        position: relative;
        text-align: center;
        text-decoration: none;
    }

    .btn:after {
        background-color: inherit;
        clip-path: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg"%3E%3Cdefs%3E%3CclipPath id="p" clipPathUnits="objectBoundingBox"%3E%3Cpolygon points="0 0, 1 0, 0.5 1" /%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E#p'); /* fix for firefox (tested in version 52) */
        clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
        content: '';
        height: 50px;
        left: 0;
        position: absolute;
        right: 0;
        top: 100%;
    }
</style>

<a href="#" class="btn">Hello!</a>

Это работает в Chrome, и я добавил исправление для Firefox. Это не работает в Edge, однако, если вы уменьшите высоту стрелки вниз, это будет выглядеть не так уж плохо.

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

box-sizing: content-box;
person nfplee    schedule 30.03.2017