Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a div with dynamic height and an arrow facing inwards using CSS

I have created the below arrow div with CSS pseudo elements. It is working fine for the fixed height but when I set its height to auto and increase the text it becomes like this. Now is it to set the arrow in a way that it increases its height with the text.

We can do this by using jQuery but is it possible to do it in CSS only?

Div with arrow on right

.label-box-st1::after {
  border-bottom: 73px solid #800080;
  border-right: 45px solid rgba(0, 0, 0, 0);
  border-top: 73px solid #800080;
  content: "";
  position: absolute;
  right: -43px;
  top: 0;
  width: 20px;
}
like image 865
Mehar Avatar asked Jan 22 '26 04:01

Mehar


1 Answers

Using Linear Gradients:

You can do it using a couple of angled linear-gradients like in the below snippet. As you can see from the snippet, it can adapt to any height even if the content wraps around (or) if it spans multi-lines.

The shape is created as follows:

  • Couple of linear-gradients (with to [side] [side] syntax) which is colored for almost 50% and transparent for the remaining 50%. Both these gradients have 50% size in Y-axis (that is, half of the element's height) and has 20px size in X-axis (meaning it has a fixed width for the triangle).
  • These linear gradients are positioned at the right top and right bottom of the element to produce the triangle effect.
  • One more linear-gradient (which is actually a solid color) whose size in Y-axis is 100% height of the parent and size in X-axis is 20px less than 100% (using calc). This produces the colored area aside from the triangular area.

The advantages of this approach are as follows:

  • It doesn't require any extra elements (real or pseudo) and hence there is no unwanted clutter in the markup and the pseudo-elements can be used for other things.
  • As can be seen in the last div, it would adapt itself even if the width of the div changes also.
  • The triangular cut at the right side is transparent and so the background of the page can also be seen through the cut, if required.

The only two drawbacks of this approach are as follows:

  • Gradients have a lower browser support compared to pseudo-elements (works only in IE10+) and
  • At some very wide angles, the angled sides will be a bit jagged.

.shape {
  position: relative;
  width: 200px;
  color: white;
  padding: 8px;
  margin: 4px;
  background: linear-gradient(to bottom right, rgb(128, 0, 128) 49%, transparent 51%), linear-gradient(to top right, rgb(128, 0, 128) 49%, transparent 51%), linear-gradient(to right, rgb(128, 0, 128), rgb(128, 0, 128));
  background-size: 20px 50%, 20px 50%, calc(100% - 20px) 100%;
  background-position: 100% 0%, 100% 100%, 0% 0%;
  background-repeat: no-repeat;
}
.shape.wide {
  width: 300px;
}
<div class='shape'>Some div with small content</div>

<div class='shape'>Some div with large content that wraps around into multiple lines</div>

<div class='shape'>Some div with large content that wraps
  <br>around into multiple lines
  <br>even spanning multiple lines</div>

<div class='shape'>Some div with
  <br>large content that wraps
  <br>around into multiple lines
  <br>even spanning
  <br>multiple lines</div>

<div class='shape wide'>Some div with
  <br>large content that wraps
  <br>around into multiple lines
  <br>even spanning
  <br>multiple lines</div>

Using SVG: (recommended approach but added below as question asks for CSS)

The same shape can also be achieved using SVG. With SVG all that we need to do is create one path using SVG's path element and then position the path absolutely with respect to the element (along with z-index: -1 to put it behind the text). SVGs are by nature scalable and so they can adapt even if the container's width and/or height increases.

Advantages of SVG are almost similar to that of the gradient based approach. The way where SVG is better than gradient based approach is that this has better browser support (should work in IE9+) and the jagged edges are also less pronounced.

.shape {
  position: relative;
  width: 200px;
  color: white;
  padding: 8px;
  margin: 4px;
}
.shape.wide {
  width: 300px;
}
.shape svg {
  position: absolute;
  height: 100%;
  width: 100%;
  top: 0px;
  left: 0px;
  z-index: -1;
}
.shape path {
  fill: rgb(128, 0, 128);
}
<div class='shape'>
  <svg viewBox='0 0 1 1' preserveAspectRatio='none'>
    <path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
  </svg>
  Some div with small content</div>

<div class='shape'>
  <svg viewBox='0 0 1 1' preserveAspectRatio='none'>
    <path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
  </svg>  
  Some div with large content that wraps around into multiple lines</div>

<div class='shape'>
  <svg viewBox='0 0 1 1' preserveAspectRatio='none'>
    <path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
  </svg>  
  Some div with large content that wraps
  <br>around into multiple lines
  <br>even spanning multiple lines</div>

<div class='shape'>
  <svg viewBox='0 0 1 1' preserveAspectRatio='none'>
    <path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
  </svg>  
  Some div with
  <br>large content that wraps
  <br>around into multiple lines
  <br>even spanning
  <br>multiple lines</div>

<div class='shape wide'>
  <svg viewBox='0 0 1 1' preserveAspectRatio='none'>
    <path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
  </svg>  
  Some div with
  <br>large content that wraps
  <br>around into multiple lines
  <br>even spanning
  <br>multiple lines</div>

Note: You can read more about SVG's path element and its commands (like M, z, L, A etc) in this MDN Tutorial. I would personally recommend you to have a look at SVG because it helps creating a lot of complex shapes with very minimal effort :)

like image 196
Harry Avatar answered Jan 24 '26 19:01

Harry