2

I am trying to make a polygon border shape like the image below but with a transparent background. polygon border with transparent background

The code I have tried is below. In the code, there are a total of 28 points. First from a point in left in the clockwise direction, then from the same point in the anti-clockwise direction.

@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');

.p-button{
  text-decoration: none;
  background: transparent;
  color: white;
  padding: 14px 50px;
  text-transform: uppercase;
  font-family: "Poppins";
  border: solid 1px black;
  border-radius: 30px;
  font-size:12px;
  --b: 1px; /* border width */
  --h:25px; /* this is half the height, adjust it based on your code */
  clip-path:polygon(
    
    /* 1st to 14th point in anticlockwise direction */
    0 50%,
    calc(0.134*var(--h))  25%,   /* 0.134 = 1 - cos(30)   */
    calc(  0.5*var(--h))  6.7%,  /* 6.7% = 0.134/2 * 100% */
    var(--h) 0,
    calc(100% - var(--h)) 0,
    calc(100% - 0.5*var(--h))   6.7%,
    calc(100% - 0.134*var(--h)) 25%,
    100% 50%,
    calc(100% - 0.134*var(--h)) 75%,
    calc(100% - 0.5*var(--h))   93.3%, /* 93.3% = 100% - 6.7% */
    calc(100% - var(--h)) 100%,
    var(--h) 100%,
    calc(  0.5*var(--h))  93.3%,
    calc(0.134*var(--h))  75%,
    
    
    /* 15th to 28th point in anticlockwise direction */
    calc((0.134*var(--h)) + var(--b))  75%,
    calc((0.5*var(--h)) + var(--b))  93.3%,
    var(--h) calc(100% - var(--b)),
    calc(100% - var(--h)) calc(100% - var(--b)),
    calc(100% - (0.5*var(--h) + var(--b)))   93.3%, /* 93.3% = 100% - 6.7% */
    calc(100% - (0.134*var(--h) + var(--b))) 75%,
    calc(100% - var(--b)) 50%,
    calc(100% - (0.134*var(--h) + var(--b))) 25%,
    calc(100% - (0.5*var(--h) + var(--b)))   6.7%,
    calc(100% - var(--h)) var(--b),
    var(--h) calc(0px + var(--b)),
    calc(  (0.5*var(--h)) + var(--b))  6.7%,  /* 6.7% = 0.134/2 * 100% */
    calc((0.134*var(--h)) + var(--b))  25%,   /* 0.134 = 1 - cos(30)   */
    var(--b) 50%) ;
}

body{
  display: flex;
  height: 100vh;
  align-items: center;
  justify-content: center;
  
}
<a class="p-button" href="">Demo it</a>

The code I took reference for the button with background color (not transparent) is from this link.

@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');

.p-button{
  text-decoration: none;
  background: #000;
  color: white;
  padding: 15px 50px;
  text-transform: uppercase;
  font-family: "Poppins";
  font-size:40px;
  --h:45px; /* this is half the height, adjust it based on your code */
  clip-path:polygon(
    0 50%,
    calc(0.134*var(--h))  25%,   /* 0.134 = 1 - cos(30)   */
    calc(  0.5*var(--h))  6.7%,  /* 6.7% = 0.134/2 * 100% */
    var(--h) 0,
    calc(100% - var(--h)) 0,
    calc(100% - 0.5*var(--h))   6.7%,
    calc(100% - 0.134*var(--h)) 25%,
    100% 50%,
    calc(100% - 0.134*var(--h)) 75%,
    calc(100% - 0.5*var(--h))   93.3%, /* 93.3% = 100% - 6.7% */
    calc(100% - var(--h)) 100%,
    var(--h) 100%,
    calc(  0.5*var(--h))  93.3%,
    calc(0.134*var(--h))  75%);
}

body{
  display: flex;
  height: 100vh;
  align-items: center;
  justify-content: center;
  
}
<a class="p-button" href="">Demo it</a>

3
  • Is there a reason for not drawing using an SVG? (And if you want to clip the shape as well, doing that slightly outside?) Commented Jul 26, 2021 at 8:13
  • I tried but, SVG is not responsive like the button. In SVG, it is hard to control padding-left, right, top, and bottom individually. Commented Jul 26, 2021 at 8:20
  • I was thinking of usin the svg as background, or drawn behind the button, not that it would also contain the text and padding. Commented Jul 26, 2021 at 8:25

3 Answers 3

2

Your idea is good but you will need to fix the math which is the complex part here.

You will notice that this will also affect the content so I add it as pseudo element to avoid this:

.p-button {
  position:relative;
  padding: 14px 50px;
  font-size:45px;
  text-decoration:none;
}

.p-button:before{
  content:"";
  position:absolute;
  inset:0;
  background:black;
  --b: 4px; /* border width */
  --h:34px; /* this is half the height, adjust it based on your code */
  --b1: calc(0.866*var(--b));
  --b2: calc(0.5*var(--b)); 
  clip-path:polygon(
    
    0 50%,
    calc(0.134*var(--h))  25%,   /* 0.134 = 1 - cos(30)   */
    calc(  0.5*var(--h))  6.7%,  /* 6.7% = 0.134/2 * 100% */
    var(--h) 0,
    calc(100% - var(--h)) 0,
    calc(100% - 0.5*var(--h))   6.7%,
    calc(100% - 0.134*var(--h)) 25%,
    100% 50%,
    calc(100% - 0.134*var(--h)) 75%,
    calc(100% - 0.5*var(--h))   93.3%, /* 93.3% = 100% - 6.7% */
    calc(100% - var(--h)) 100%,
    var(--h) 100%,
    calc(  0.5*var(--h))  93.3%,
    calc(0.134*var(--h))  75%,
    0 50%,
    
    var(--b) 50%,
    calc(0.134*var(--h) + var(--b1))  calc(75% - var(--b2)),
    calc(  0.5*var(--h) + var(--b2))  calc(93.3% - var(--b1)),
    var(--h) calc(100% - var(--b)),
    calc(100% - var(--h)) calc(100% - var(--b)),
    calc(100% - 0.5*var(--h)  - var(--b2))  calc(93.3% - var(--b1)),
    calc(100% - 0.134*var(--h) - var(--b1)) calc(75% - var(--b2)),
    calc(100% - var(--b)) 50%,
    calc(100% - 0.134*var(--h) - var(--b1)) calc(25% + var(--b2)),
    calc(100% - 0.5*var(--h)  - var(--b2))  calc(6.7% + var(--b1)),
    calc(100% - var(--h)) var(--b),
    var(--h) var(--b),
    calc(  0.5*var(--h) + var(--b2))  calc(6.7% + var(--b1)),  
    calc(0.134*var(--h) + var(--b1))  calc(25% + var(--b2)),   
    var(--b) 50%) ;
}

body{
  display: flex;
  height: 100vh;
  align-items: center;
  justify-content: center;
  background:linear-gradient(45deg,red,lightblue);
}
<a class="p-button" href="">Demo it</a>

Sign up to request clarification or add additional context in comments.

4 Comments

This is amazing, I didn't think that way. Is there an easier way to achieve this kind of border, maybe via other CSS property I am unknown of?
@FossBytes not really, this is probably the most suitable CSS solution. Any other CSS solution will have the same (or more) complexity.
Also, how have you come up with the formula for clip paths in both buttons? any idea? . I would like to understand more about it.
@FossBytes a pen, a paper and some math background. you have 8 points drawn in a circle so with some trigonometry we can get the values (some sin() and cos()). I will try to edit the post later if I get a chance but I cannot promise (it would take time to draw figures and explain)
1

Here u need is Clipping tool When when using clipping , the border also get clipped so , so inorder to get border we need to add one more div in background with needed border-color and clip that also.. But u cant achieve transparent border along with this method

@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');

.p-button{
  text-decoration: none;
  background: white;
  color: black;
  padding: 15px 50px;
  text-transform: uppercase;
  font-family: "Poppins";
  font-size:40px;
  width:260px;
height:94px;
  
 

-webkit-clip-path: polygon(20% 0, 10% 7%, 3% 23%, 0 50%, 3% 75%, 10% 90%, 20% 100%, 80% 100%, 90% 94%, 97% 78%, 100% 50%, 97% 20%, 90% 6%, 80% 0); clip-path: polygon(20% 0, 10% 7%, 3% 23%, 0 50%, 3% 75%, 10% 90%, 20% 100%, 80% 100%, 90% 94%, 97% 78%, 100% 50%, 97% 20%, 90% 6%, 80% 0);

}
.border{
width:264px;
height:98px;
background-color:black;
 display: flex;
 
  align-items: center;
  justify-content: center;

-webkit-clip-path: polygon(20% 0, 10% 7%, 3% 23%, 0 50%, 3% 75%, 10% 90%, 20% 100%, 80% 100%, 90% 94%, 97% 78%, 100% 50%, 97% 20%, 90% 6%, 80% 0); clip-path: polygon(20% 0, 10% 7%, 3% 23%, 0 50%, 3% 75%, 10% 90%, 20% 100%, 80% 100%, 90% 94%, 97% 78%, 100% 50%, 97% 20%, 90% 6%, 80% 0);
}
*{box-sizing: border-box;}
body{
  display: flex;
  height: 100vh;
  align-items: center;
  justify-content: center;
  
}
<div class="border"><a class="p-button" href="">Demo it</a></div>

Comments

-2

You cannot get the functionality you want directly from clipping tools. Because they are made for another purpose.

This will NOT generate the same output. It's just a demonstration of a different approach:

.polygon {
  display: inline-block;
  position: relative;
  width: 150px;
  height: 150px;
  background: red;
  box-sizing: border-box;
  -webkit-clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
  clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
}
.polygon img {
  position: absolute;
  top: 2px; /* equal to border thickness */
  left: 2px; /* equal to border thickness */
  width: 146px; /* container height - (border thickness * 2) */
  height: 146px; /* container height - (border thickness * 2) */
  -webkit-clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
  clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
}
<div class="polygon">
  <img src="https://placehold.co/600x400?text=non-txt">
</div>
<!-- This will NOT generate a button with the text "DEMO"! -->

Or perhaps having two clipping polygons on top of each other to mimic transparency. For further details refer to this post.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.