Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a specific div shape (like a polygon with a tail)

I am trying without success to create text container like this:

enter image description here

Can you please suggest me any solution for this ?

I was able to create something similar via clip-path but I wonder how can I make this shape element? Also please notice color differences. Is there any other way to make that?

CodePen Demo

CSS

div {
    width: 350px;
    height: 350px;
    background: #1e90ff;
    -webkit-clip-path: polygon(50% 0%, 91% 22%, 100% 45%, 91% 81%, 33% 88%, 0% 60%, 6% 23%);
    clip-path: polygon(50% 0%, 91% 22%, 100% 45%, 91% 81%, 33% 88%, 0% 60%, 6% 23%);
}
like image 522
Ganga Avatar asked Dec 25 '22 12:12

Ganga


2 Answers

Since there are two different gradient backgrounds with two different angles involved, doing this with a single element would become very complex. It can be done with one single element but would require setting multiple gradient backgrounds to the element, positioning them and adjusting the clip-path.

Instead of going to so much complexities, it would be a better idea to use a couple of elements where one is for the polygon on the top and the other is for the tail like part at the bottom.

Following is a full description of what was done to achieve the shape:

  • Add two pseudo-elements to the main container div. The :before pseudo-element would form the polygon on top and the :after would form the tail at the bottom.
  • Two pseudo elements are required because if we clip the parent element itself into polygon shape then the tail part would also become invisible due to clipping of the parent.
  • Position the :after pseudo-element such that its bottom and left match with the coordinates of lowest point on the polygon.
  • Add background in the form of linear-gradient to both the polygon pseudo-element and the tail like pseudo-element.
  • The :after pseudo-element is rotated by -20 degrees to give it an angled appearance. This can also be done without using transform (by just modifying the coordinates of the clip-path ) but I feel that using transform makes them a bit more intuitive.

Note: Browser support for clip-path is very low at present and you'd probably want to have a look at using SVG because the clip paths won't work in Firefox without using inline SVG and in IE they won't work at all.

div {
  position: relative;
  width: 250px;
  height: 250px;
}
div:before {
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  background: linear-gradient(to bottom left, rgb(251, 228, 168), rgb(246, 197, 51));
  -webkit-clip-path: polygon(35% 0%, 91% 12%, 100% 35%, 91% 67%, 33% 78%, 0% 50%, 6% 23%);
  clip-path: polygon(35% 0%, 91% 12%, 100% 35%, 91% 67%, 33% 78%, 0% 50%, 6% 23%);
}
div:after {
  position: absolute;
  content: '';
  height: 15%;
  width: 22%;
  left: 33%;
  bottom: 7%;
  background: linear-gradient(to bottom left, rgb(250, 225, 150), rgb(248, 210, 91) 45%, rgb(240, 168, 43) 50%, rgb(242, 181, 44) 55%, rgb(245, 192, 44));
  transform-origin: left top;
  transform: rotate(-20deg);
  -webkit-clip-path: polygon(0% 0%, 90% 35%, 100% 100%, 0% 100%, 35% 40%);
  clip-path: polygon(0% 0%, 90% 35%, 100% 100%, 0% 100%, 35% 40%);  
}
<div></div>

The below snippet which uses url() syntax for clip-path along with inline SVG will work in Firefox also (but not in IE).

div {
  position: relative;
  width: 250px;
  height: 250px;
}
div:before {
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  background: linear-gradient(to bottom left, rgb(251, 228, 168), rgb(246, 197, 51));
  -webkit-clip-path: url(#polygon-clip);
  clip-path: url(#polygon-clip);
}
div:after {
  position: absolute;
  content: '';
  height: 15%;
  width: 22%;
  left: 33%;
  bottom: 7%;
  background: linear-gradient(to bottom left, rgb(250, 225, 150), rgb(248, 210, 91) 45%, rgb(240, 168, 43) 50%, rgb(242, 181, 44) 55%, rgb(245, 192, 44));
  transform-origin: left top;
  transform: rotate(-20deg);
  -webkit-clip-path: url(#tail-clip);
  clip-path: url(#tail-clip);
}
<svg width="0" height="0">
  <defs>
    <clipPath id='polygon-clip' clipPathUnits='objectBoundingBox'>
      <polygon points='.35 0, .91 .12, 1 .35, .91 .67, .33 .78, 0 .5, .06 .23' />
    </clipPath>
    <clipPath id='tail-clip' clipPathUnits='objectBoundingBox'>
      <polygon points='0 0, .9 .35, 1 1, 0 1, .35 .4' />
    </clipPath>
  </defs>
</svg>
<div></div>
like image 70
Harry Avatar answered Dec 27 '22 02:12

Harry


SVG

I would consider using only svg for this complex image with gradients.

The advantages of doing this with svg only is:
Each path gets one gradient so its easy to keep track.
You only need tree elements to draw the main shape.
And its supported by all major browsers.

I tested this image in:
Firefox 42.0
IE 11
chrome 46

.text {
  font-size: 10px;
}
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" viewBox="0 0 125 125" width="50%">
  <title>Orange speech buble</title>
  <desc>Created for answering a question on stack overflow</desc>
  <defs id="defs3338">
    <linearGradient id="linearGradient4154">
      <stop id="stop4156" offset="0" style="stop-color:#e1b800;stop-opacity:1" />
      <stop id="stop4158" offset="1" style="stop-color:#ffffff;stop-opacity:1" />
    </linearGradient>
    <linearGradient gradientTransform="translate(1.5152288,-5.0507627)" gradientUnits="userSpaceOnUse" y2="951.2207" x2="41.163715" y1="1011.5774" x1="57.831238" id="linearGradient4160" xlink:href="#linearGradient4154" />
    <linearGradient gradientTransform="translate(-1.5152288,-4.2931483)" gradientUnits="userSpaceOnUse" y2="1009.6832" x2="51.26524" y1="1022.0576" x1="57.073616" id="linearGradient4170" xlink:href="#linearGradient4154" />
    <linearGradient gradientTransform="translate(1.5152288,-5.0507627)" gradientUnits="userSpaceOnUse" y2="1029.1357" x2="62.160976" y1="1029.1357" x1="43.221054" id="linearGradient4180" xlink:href="#linearGradient4154" />
  </defs>
  <g transform="translate(0,-927.36222)" id="layer1">
    <path d="m 48.992399,1015.4916 13.637059,6.8185 -17.172593,10.1016 z" style="fill:url(#linearGradient4180);" />
    <path d="m 37.628182,1015.2391 25.001276,7.071 -9.848988,-13.8896 z" style="fill:url(#linearGradient4170);" />
    <path d="m 55.305852,953.36727 -21.213203,8.33376 -12.374369,27.52666 15.909903,25.50631 55.55839,-7.3236 7.576147,-14.39464 -0.75762,-18.43528 -9.596447,-13.38453 z" style="fill:url(#linearGradient4160);" />
    <text y="985" x="34" class="text" xml:space="preserve">Your text here</text>
  </g>
</svg>
like image 24
Persijn Avatar answered Dec 27 '22 00:12

Persijn