1

I'm looking to create a div in the shape of a shopping tag, and have gotten pretty far, but I want to make it pixel perfect by rounding the triangle pointer both at it's peak and just before blending into the tag.

enter image description here

Larger detail:

enter image description here

Wanted, the types of rounded edges here:

enter image description here

Bonus points if I can get the little white dot somewhere (I tried content: "·" with little luck).

I've looked up stackoverflow items on rounded triangles, so this seems doable, but they're all standalone triangles, not added to the end of a div. And I'm trying to do it w/o making a standalone triangle next to my rectangular div.

Thank you for any ideas!

.tag {
  background-color: red;
  border-radius: 0 3px 3px 0;
  color: #fff;
  display: inline-block;
  font-family: verdana;
  font-size: 12px;
  height: auto;
  line-height: 12px;
  margin-left: 9px;
  padding: 3px 6px 3px 3px;
  position: relative;
}

.tag:before {
  content: "";
  line-height: 6px;
  position: absolute;
  width: 0;
  height: 0;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  border-right: 9px solid #f00;
  top: 0;
  left: -9px;
}
<div class="tag">hello</div>

--- EDIT AFTER SUGGESTIONS ---

.tag {
    background-color: red;
    border-radius: 0 3px 3px 0;
    clip-path: polygon(10px 0, 100% 0, 100% 100%, 10px 100%, 0 50%);
    color: #fff;
    display: inline-block;
    font-family: verdana;
    font-size: 12px;
    filter: url('#goo');
    height: auto;
    line-height: 12px;
    margin-left: 15px;
    padding: 3px 12px 3px 15px;
    position: relative;
}
<div class="tag">Hello</div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <defs>
        <filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
    </defs>
</svg>

This looks pretty much there, and the point is a bit rounded. But the edges leading onto the rectangle are still sharp, and it's now rounded the right side of the tag a great deal. I'm guessing the blur values need to be adjusted so I'm looking in that direction now, though it's a new topic for me.

Jeremy L.
  • 853
  • 8
  • 15

2 Answers2

1

you can use clip-path for the shape, an SVG filter for the rounded corner (adjust the stdDeviation to control the radius) and a gradient coloration for the dot:

.box {
  display: inline-block;
  filter: url('#goo');
}

.box div {
  margin: 10px;
  padding: 20px 40px 20px 20px;
  font-size: 35px;
  font-weight: bold;
  font-family: sans-serif;
  color:#fff;
  transform-origin: right center;
  transform:rotate(-45deg);
  background: 
    radial-gradient(8px at calc(100% - 20px) 50%,#fff 99%,transparent),/* the dot */
    linear-gradient(60deg,red,orange); /* gradient coloration */
  clip-path: polygon(0 0, calc(100% - 30px) 0, 100% 50%, calc(100% - 30px) 100%, 0 100%);
}
<div class="box">
  <div>SALE</div>
</div>

<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <defs>
        <filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur" />    
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
    </defs>
</svg>

With mask to have transparency within the dot:

.box {
  display: inline-block;
  filter: url('#goo');
}

.box div {
  margin: 10px;
  padding: 20px 40px 20px 20px;
  font-size: 35px;
  font-weight: bold;
  font-family: sans-serif;
  color:#fff;
  transform-origin: right center;
  transform:rotate(-45deg);
  -webkit-mask: radial-gradient(9px at calc(100% - 20px) 50%,transparent 99%,#fff);
  background:linear-gradient(60deg,red,orange); /* gradient coloration */
  clip-path: polygon(0 0, calc(100% - 30px) 0, 100% 50%, calc(100% - 30px) 100%, 0 100%);
}

body {
  background:linear-gradient(to right,#888,#fff);
}
<div class="box">
  <div>SALE</div>
</div>

<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <defs>
        <filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur" />    
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
    </defs>
</svg>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Wow terrific work @Temani! Any modern cross-browser problems I should be aware of? – Jeremy L. Oct 15 '20 at 02:17
  • @daprezjer only IE will fail as usual, for the others there are no problem – Temani Afif Oct 15 '20 at 02:23
  • Thanks, I'll try it out and give credit. I didn't really need the rotation and the gradient of the screen cap - just the rounded triangle edges - but I'm guessing I can figure that out. – Jeremy L. Oct 15 '20 at 03:50
  • Edited my comment above. Getting into the blur matrix is getting crazy, but seems really cool! I'm surprised there's not a less heady way of doing this however, given it the triangle can be made on its own: https://stackoverflow.com/questions/14446677/how-to-make-3-corner-rounded-triangle-in-css But perhaps this is the only way with only one div. – Jeremy L. Oct 15 '20 at 04:36
0

Based on Temani's answer above, it got me thinking about the background and rotation of the :before, and the ability to clip the :before element. So, I simply put a box before it, gave it some border radius, rotated it to a diamond, and positioned it correctly over my tag. Whah lah!

I could also have used clip path to remove the right side of the diamond, but in my case I have no need.

.tag {
    background-color: red;
    border-radius: 0 3px 3px 0;
    color: #fff;
    display: inline-block;
    font-family: verdana;
    font-size: 12px;
    font-weight: 300;
    height: auto;
    line-height: 12px;
    margin-left: 15px;
    padding: 5px 6px 3px 12px;
    position: relative;
}

.tag:before {
    background: red radial-gradient(2px at 8px 50%, #fff 99%, transparent);
    content: "";
    height: 16px;
    width: 16px;
    position: absolute;
    border-radius: 4px 3px;
    top: 2px;
    transform: rotate(45deg);
    left: -7px;
}
<div class="tag">Hello</div>
Jeremy L.
  • 853
  • 8
  • 15