Triangular border in DIV

Viewed 61

I've got a div( well it's actually a <th> but I don't think that's relevant) with some dynamically-sized content in it.

I'd like to put a border triangle in the parent div, that fills it (base same width as div, height same height as div).

With a fixed parent div size I can do it as below. Is it possible to do this without a fixed parent div size? I'm using VueJs if that's any use

.crossedleft {
    background: 
       linear-gradient(to top left,
           rgba(0,0,0,0) 0%,
           rgba(0,0,0,0) calc(50% - 0.8px),
           rgba(0,0,0,1) 50%,
           rgba(0,0,0,0) calc(50% + 0.8px),
           rgba(0,0,0,0) 100%)
}

.crossedright {
    background: 
       linear-gradient(to top right,
           rgba(0,0,0,0) 0%,
           rgba(0,0,0,0) calc(50% - 0.8px),
           rgba(0,0,0,1) 50%,
           rgba(0,0,0,0) calc(50% + 0.8px),
           rgba(0,0,0,0) 100%)
}
<div style="height:50px;width:100px">
<div class="crossedleft" style="position:absolute; height:50px;width:50px">
<div class="crossedright" style="position:absolute; height:50px;width:50px;left:50px">
</div>
<pre>

    content

</pre>
</div>

2 Answers

Apply both backgrounds to the div instead:

.tri {
    background: 
       linear-gradient(to top left,
           rgba(0,0,0,0) 0%,
           rgba(0,0,0,0) calc(50% - 0.8px),
           rgba(0,0,0,1) 50%,
           rgba(0,0,0,0) calc(50% + 0.8px),
           rgba(0,0,0,0) 100%) left,  /* one on the left */
       linear-gradient(to top right,
           rgba(0,0,0,0) 0%,
           rgba(0,0,0,0) calc(50% - 0.8px),
           rgba(0,0,0,1) 50%,
           rgba(0,0,0,0) calc(50% + 0.8px),
           rgba(0,0,0,0) 100%) right; /* the other the right */
    background-size:50% 100%; /* both width:50% and height:100% */
    background-repeat:no-repeat;
}
<div style="width:100px" class="tri">
<pre>

    content

</pre>
</div>

You can simplify the code a little like below:

.tri {
    --g:rgba(0,0,0,0) calc(50% - 0.8px),
        rgba(0,0,0,1) 50%,
        rgba(0,0,0,0) calc(50% + 0.8px);
    background: 
       linear-gradient(to top left,  var(--g)),
       linear-gradient(to top right, var(--g)) 100%; 
    background-size:50% 100%;
    background-repeat:no-repeat;
}
<div style="width:100px" class="tri">
<pre>

    content

</pre>
</div>

First of all, you can use your own approach totally responsively by working with percentages. You can even eliminate all extra elements by using pseudo elements ::before and ::after like this:

.triangle {
  position: relative;
  display: inline-block;
  padding: 1em;
  border-bottom: 1px black solid;
}

.triangle::before,
.triangle::after {
  content: "";
  display: block;
  width: 50%;
  height: 100%;
  position: absolute;
  top: 0;
}

.triangle::before {
  left: 0;
  background: linear-gradient(to top left, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) calc(50% - 0.8px), rgba(0, 0, 0, 1) 50%, rgba(0, 0, 0, 0) calc(50% + 0.8px), rgba(0, 0, 0, 0) 100%)
}

.triangle::after {
  right: 0;
  background: linear-gradient(to top right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) calc(50% - 0.8px), rgba(0, 0, 0, 1) 50%, rgba(0, 0, 0, 0) calc(50% + 0.8px), rgba(0, 0, 0, 0) 100%)
}
<div class="triangle">Short</div>
<div class="triangle">This is a very long sentence</div>

However, in this case you might be better off with an SVG background as it can contain any shape you like. With a simple shape like a triangle you can even embed it into your CSS:

.triangle {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.0' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpolygon points='50,1 98,98 1,98' fill='none' stroke='black' stroke-width='1px' vector-effect='non-scaling-stroke' /%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  display: inline-block;
  padding: 1em;
}
<div class="triangle">Short</div>
<div class="triangle">This is a very long sentence</div>

The SVG in this example is

<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 100 100" preserveAspectRatio="none">
  <polygon points="50,1 99,99 1,99" fill="none" stroke="black"  stroke-width="1px" vector-effect="non-scaling-stroke" />
</svg>
Related