Are diagonal border lines possible in HTML / CSS?

2019-05-06 13:30发布

问题:

Just realized I have yet to see this.

But can not believe it isn't possible.

I'm looking to draw a triangle in pure CSS/HTML. An equilateral if possible.

Clarification:

I don't wish to use an image to achieve this.

You would need to be able to put content inside the div.

回答1:

One Solution

Diagonals are not easy. One solution is to overlay pseudo-elements to create the border, assuming you are dealing with solid background colors. Then you have to position the content to make it look nice. You could even do some text wrapping.

Here is a basic example using this code:

CSS & HTML Respectively

.triangleBorder {
        position: relative;
        width: 200px;
        height: 173.2px; /* for equalateral = Width * (sq.root 3) / 2 */
    }
    
    .triangleBorder:before {
        content: '';
        width: 0;
        height: 0;
        position: absolute;
        z-index: -2;
        border: 100px solid transparent;
        border-top-width: 0;
        border-bottom: 173.2px solid black;
    }
    
    .triangleBorder:after {
        content: '';
        width: 0;
        height: 0;
        position: absolute;
        left: 1px;
        top: 1px;
        z-index: -1;
        border: 99px solid transparent;
        border-top-width: 0;
        border-bottom: 171.5px solid white;
    }
    
    .triangleBorder span {
       position: absolute;
       width: 100%;
       text-align: center;
       top: 50%;
    }
<div class="triangleBorder">
    <span>Content<span>
</div>



回答2:

Here are a few different approaches for creating the equilateral triangle shape using CSS. Creation of diagonals is still not any easier but now the shape can at-least have a transparent background even when the body has a gradient (or) an image as its background.

Option 1: Using Pseudo-elements and Skew Transforms

In this method we use a couple of pseudo-elements and skew them in opposite directions (inward) to create the diagonal lines whereas the line at the bottom is produced using a border-bottom on the parent. We can also produce trapezoids using this approach.

Cons: This approach would not work if the body background and shape background are different and the body background is not a solid color.

.triangle {
  position: relative;
  width: 200px;
  border-bottom: 2px solid white;
  color: white;
  margin: 20px auto;
  overflow: hidden;
}
.shape1 {
  height: 174px;
}
.shape2 {
  height: 101px;
}
.triangle:before,
.triangle:after {
  position: absolute;
  content: '';
  height: 100%;
  width: 0%;
  bottom: 0px;
  transform-origin: left bottom;
}
.triangle:before {
  left: 0px;
  border-right: 2px solid white;
}
.triangle.shape1:before {
  transform: skew(-30deg);
}
.triangle.shape2:before {
  transform: skew(-45deg);
}
.triangle:after {
  right: 0px;
  border-left: 2px solid white;
}
.triangle.shape1:after {
  transform: skew(30deg);
}
.triangle.shape2:after {
  transform: skew(45deg);
}
.triangle span {
  position: absolute;
  width: 100%;
  text-align: center;
  top: 50%;
}

/* Just for demo */

*{
  box-sizing: border-box;
}

body {
  background: radial-gradient(ellipse at center, #400, #100);
}
.trapezoid {
  position: relative;
  border-bottom: 2px solid white;
  color: white;
  margin: 20px auto;
  width: 200px;
  height: 50px;
}
.trapezoid:before,
.trapezoid:after {
  position: absolute;
  content: '';
  height: 100%;
  width: 40%;
  bottom: -1px;
  border-top: 2px solid white;
  transform-origin: left bottom;
}
.trapezoid:before {
  left: 0px;
  border-left: 2px solid white;
  transform: skew(-45deg);
}
.trapezoid:after {
  right: 0px;
  border-right: 2px solid white;
  transform: skew(45deg);
}
.trapezoid span {
  position: absolute;
  width: 100%;
  text-align: center;
  top: 30%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<div class='triangle shape1'>
  <span>content</span>
</div>
<div class='triangle shape2'>
  <span>content</span>
</div>

<br/>


<!-- Just something extra to illustrate -->

<div class='trapezoid'>
  <span>content</span>
</div>

<br/>


Here is a variation of Option 1 which would work when the background of the body and that of the shape are different and the body background is a solid color.

.triangle{
  position: relative;
  width: 200px;  
  border-bottom: 2px solid black;
  color: red;
  background: beige;
  margin: 20px auto;
  overflow: hidden;
}
.shape1{
  height: 174px;
}
.shape2{
  height: 101px;
}
.triangle:before, .triangle:after{
  position: absolute;
  content: '';
  height: 101%;
  width: 100%;
  bottom: 0px;
  background: red;
  transform-origin: left bottom;
}
.triangle:before{
  left: -200px;
  border-right: 2px solid black;
}
.triangle.shape1:before{
  transform: skew(-30deg);  
}
.triangle.shape2:before{
  transform: skew(-45deg);  
}
.triangle:after{
  right: -200px;  
  border-left: 2px solid black;
}
.triangle.shape1:after{
  transform: skew(30deg);
}
.triangle.shape2:after{
  transform: skew(45deg);
}

.triangle span{
  position: absolute;
  width: 100%;
  text-align: center;
  top: 50%;
}

/* Just for demo */

*{
  box-sizing: border-box;
}
body{
  background: red;  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle shape1'>
  <span>content</span>
</div>
<div class='triangle shape2'>
  <span>content</span>
</div>

Here is another variation of Option 1 which supports gradient background for both inside and outside the triangle shape.

.triangle {
  position: relative;
  width: 200px;
  border-bottom: 2px solid white;
  color: white;
  margin: 20px auto;
  overflow: hidden;
}
.shape1 {
  height: 174px;
}
.shape2 {
  height: 101px;
}
.triangle:before,
.triangle:after {
  position: absolute;
  content: '';
  height: 99%;
  width: 50%;
  z-index: -1;
  transform-origin: left bottom;
}
.triangle:before {
  left: 0px;
  top: 100%;
  border-top: 3px solid white;
  background: linear-gradient(90deg, #003333, #773333);
}
.triangle.shape1:before {
  border-top: 4px solid white;
  transform: skewY(-60deg);
}
.triangle.shape2:before {
  transform: skewY(-45deg);
}
.triangle:after {
  right: 0px;
  top: 0%;
  border-top: 3px solid white;
  background: linear-gradient(90deg, #773333, #FF3333);
}
.triangle.shape1:after {
  border-top: 4px solid white;
  transform: skewY(60deg);
}
.triangle.shape2:after {
  transform: skewY(45deg);
}
.triangle span {
  position: absolute;
  width: 100%;
  text-align: center;
  top: 50%;
}


/* Just for demo */

*{
  box-sizing: border-box;
}
body {
  background: radial-gradient(ellipse at center, #400, #100);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle shape1'>
  <span>content</span>
</div>
<div class='triangle shape2'>
  <span>content</span>
</div>

Screenshot:

Triangles with different angles can be easily created by modifying the skew angle and the height of the parent div. But, as we are using skew the borders tend to become thinner as the skew angle approaches 90deg (or -90deg) but that shouldn't be too big a problem because with such high angles you can barely have fit any text inside.


Option 2: Using Linear Gradients

In this method, we use a couple of angled linear-gradient backgrounds (each of which are 50% width of the container) and slant them in opposite directions to produce the diagonal lines.

.triangle {
  position: relative;
  border-bottom: 2px solid white;
  color: white;
  margin: 20px auto;
  height: 174px;
  width: 200px;
  background: linear-gradient(to top left, transparent 49.5%, white 49.5%, white 50.5%, transparent 50.5%), linear-gradient(to top right, transparent 49.5%, white 49.5%, white 50.5%, transparent 50.5%);
  background-size: 50% 100%;
  background-position: 1px 0px, 99px 0px;
  background-repeat: no-repeat;
}
.triangle span {
  position: absolute;
  width: 100%;
  text-align: center;
  top: 50%;
}
/* Just for demo*/

body {
  background: radial-gradient(ellipse at center, #400, #100);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle'>
  <span>content</span>
</div>

Cons: Angled gradients are known for producing jagged lines.

Note: Irrespective of which approach is chosen, you would still have to do text wrapping to make the text stay inside the shape.