Responsive CSS triangle with percents width

2019-01-03 09:48发布

The code below will create an arrow right below an <a> element:

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>

The problem is that we have to indicate the link width to get an arrow of a proper size because we cannot indicate the border width in pixels.

How to make a responsive triangle percent based?

6条回答
2楼-- · 2019-01-03 10:26

You could use a skewed and rotated pseudo element to create a responsive triangle under the link :

DEMO (resize the result window to see how it reacts)

The triangle maintains it's aspect ratio with the padding-bottom property.

If you want the shape to adapt it's size according to it's content, you can remove the width on the .btn class

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

For more info on responsive triangles and how to make them, you can have a look at Triangles with transform rotate (simple and fancy responsive triangles)

查看更多
虎瘦雄心在
3楼-- · 2019-01-03 10:26

I found solution that works with any width/height. You can use two pseudo-elements with linear-gradient background, like this, (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%)
}
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-01-03 10:35

A modified version of the below code can help you to achieve this

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

For further reading on responsive triangles: Responsive CSS Triangles

查看更多
Ridiculous、
5楼-- · 2019-01-03 10:36

I took @Probocop's answer and come up with the following:

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

This works in Chrome and I've added a fix for Firefox. It doesn't work in Edge, however if you decrease the height of the down arrow then it doesn't look so bad.

Please note that if you are using bootstrap you will need to either change the name or override some of the styles it applies. If you decide to rename it then you also need to add the following to the .btn style:

box-sizing: content-box;
查看更多
我想做一个坏孩纸
6楼-- · 2019-01-03 10:39

I tried the other answers and found them to be either too complex and/or unwieldy to manipulate the shape of the triangle. I decided instead to create a simple triangle shape as an svg.

The triangle height can be set to an absolute value, or as a percentage of the rectangle so it can be responsive in both directions if necessary.

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>

Tested FF, Chrome, IE, Edge, mob Safari and mob Chrome

查看更多
我想做一个坏孩纸
7楼-- · 2019-01-03 10:41

Another solution to this would be to use a CSS clip-path to clip a triangle out of a coloured block. No IE support however, but could be used for internal tools etc.

DEMO

Written with SCSS for ease.

.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%);
  }

}
查看更多
登录 后发表回答