4

Firstly, I have searched SO for similar questions and there are many but none which have the exact requirements below.

I am trying to create the button below using pure css.

enter image description here

It has the following requirements.

  1. It has a 1px border with a horizontal gradient.
  2. It must be transparent.
  3. It must have rounded corners
  4. It will have a cut-out of the border which is also transparent.
  5. It must be variable width and height
  6. It should work in all modern browsers (not IE)

I have created a Code Sandbox which gets all of it right except the border-radius. I have used a polygon clip-path for the cut out and used border-image for the gradient which is why the border-radius doesn't work.

body {
  font-family: sans-serif;
  background-color: #232837;
}

.button {
  cursor: pointer;
  display: inline-block;
  height: 40px;
  line-height: 40px;
  padding: 0 10px;
  color: white;
  
  background-color: transparent;

  border: solid 1px;
  border-radius: 6px;
  border-image: linear-gradient(to left, #743ad5 0%, #d53a9d 100%);
  border-image-slice: 1;

  clip-path: polygon(0 0, 12px 0, 12px 1px, 24px 1px, 24px 0, 100% 0, 100% 100%, 0 100%);

}
 <div style="padding:40px;">
   <a class="button">This is a button</a>
  </div>

https://codesandbox.io/s/kw9p9k5073

I have managed to avoid using svgs so far as I don't really understand them well enough to implement a solution properly but if I have to go down that path I will.

Any advice would be very much appreciated.

Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
jonhobbs
  • 26,684
  • 35
  • 115
  • 170

2 Answers2

3

Considering the fact that you will have an horizontal gradient with 1px border we can simulate this by creating a multiple background layer. The left and right border can be considered as a solid color (since it's an horizontal gradient) and only the top/bottom need to really be gradient.

The tricky part is to find the percentage value for the top gradient in order to have the transparent gap and keep it the same as the bottom one. For this I used some math to find the correct values.

I made the border 2px to better see the result

body {
  font-family: sans-serif;
  background-color: #232837;
}

.button {
  cursor: pointer;
  display: inline-block;
  height: 40px;
  line-height: 40px;
  padding: 0 10px;
  color: white;
  border:2px solid transparent;
  border-radius:10px;
  border-right-color:#743ad5;
  border-left-color:#d53a9d;
  background:
    linear-gradient(to left,
      rgb(116, 58, 213) 0%, rgb(186, 58, 143) 70% ,
      transparent 70%,  transparent 85%, 
      rgb(201, 58, 128) 85%, rgb(213, 58, 157) 100%) top/100% 2px,
    linear-gradient(to left, #743ad5 0%, #d53a9d 100%) bottom/100% 2px;
  background-repeat:no-repeat;
}
<a class="button">This is a button</a>
<a class="button">This is a long button</a>
<a class="button" style="padding:10px">This is a very long button</a>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 1
    @Kaiido no, it also works for dynamic width and height ;) I have updated with more examples – Temani Afif Jan 18 '19 at 12:07
  • That's very clever, just one problem, the corners are a strange shape, presumably because the background gradient overlaps the corner a bit. I'm going to have a fiddle with it and see if I can get it looking perfect. If I can I'll mark it correct. – jonhobbs Jan 18 '19 at 12:39
  • @jonhobbs yes the radius won't be perfect, but I consdiered the fact that you have a small radius thus it's not a big issue – Temani Afif Jan 18 '19 at 12:43
  • 1
    I took your idea of only making the top and bottom lines gradients and used additional elements to do this without messing up the corner radius so I've marked it as correct. Many thanks. – jonhobbs Jan 18 '19 at 20:44
  • It will helpful to you https://codepen.io/abhisavadiya/pen/RwxYwLX – volvereabhi Apr 25 '22 at 11:24
  • @volvereabhi that's my answer in another question ;) https://stackoverflow.com/a/51496341/8620333 – Temani Afif Apr 25 '22 at 11:25
0

The below code uses pseudo-elements, but doesn't meet requirement (2). Perhaps you could try with mix-blend-mode to remove the background.

body {
    font-family:sans-serif;
    background-color:#232837
}

.button {
    cursor:pointer;
    display:inline-block;
    padding:13px 15px 12px;
    color:#fff;
    background:#232837;
    border-radius:6px;
    position:relative
}

.button::after {
    position:absolute;
    top:-1px;
    bottom:-1px;
    left:-1px;
    right:-1px;
    background:linear-gradient(to left,#743ad5 0%,#d53a9d 100%);
    content:'';
    z-index:-1;
    border-radius:6px;
    clip-path:polygon(0 0,12px 0,12px 4px,24px 4px,24px 0,100% 0,100% 100%,0 100%)
}

Using SVG to create a rect with a stroke set to a linearGradient is possible. However, you would need to define the viewBox size and the elements size. It would be extremely unresponsive and your button's width and height cannot be variable, thus not meeting requirement (5).

Leena Lavanya
  • 333
  • 1
  • 10