Solution 1 :

Is this what you are looking for?

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

    body, html {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      background: #5CA4EA;
      overflow: hidden;
      font-family: 'Lato', sans-serif;
    }
    
    .container {
      width: 400px;
      height: 400px;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .center {
      width: 180px;
      height: 60px;
      position: absolute;
    }
    
    .btn {
      width: 180px;
      height: 60px;
      cursor: pointer;
      background: transparent;
      border: 1px solid #91C9FF;
      outline: none;
      transition: 1s ease-in-out;
    }
    
    svg {
      position: absolute;
      left: 0;
      top: 0;
      fill: none;
      stroke: #fff;
      stroke-dasharray: 150 480;
      stroke-dashoffset: 150;
      transition: 1s ease-in-out;
    }
    
    .btn:hover {
      transition: 1s ease-in-out;
      background: #4F95DA;
    }
    
    .btn:hover svg {
      stroke-dashoffset: -480;
    }
    
    .btn span {
      color: white;
      font-size: 18px;
      font-weight: 100;
    }
    
    button:active {
        border: 3px outset #ddd;
        color: #fff;
        background: linear-gradient(160deg, #666, #444);
        text-shadow: 0px 0px 4px #ccc;
        box-shadow: 0 0 10px #fff, 0 0 40px #fff, 0 0 80px #fff;
        transition-delay: 1s;
    }
      <div class="container">
        <div class="center">
          <button class="btn">
            <svg width="180px" height="60px" viewBox="0 0 180 60" class="border">
              <polyline points="179,1 179,59 1,59 1,1 179,1" class="bg-line" />
              <polyline points="179,1 179,59 1,59 1,1 179,1" class="hl-line" />
            </svg>
            <span>HOVER ME</span>
          </button>
        </div>
      </div>

Solution 2 :

This “Correction” of mine was based on the post this post to make svg responsible.

Sorry for the english of google translator.

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

body, html {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: #5CA4EA;
  overflow: hidden;
  font-family: 'Lato', sans-serif;
}

.container {
  width: 400px;
  height: 400px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
}

.btn {
  cursor: pointer;
  background: transparent;
  border: 1px solid #91C9FF;
  outline: none;
  transition: 1s ease-in-out;
    padding:3%;
  padding-top:2%;
  padding-bottom:2%;
    position: relative;
    display: flex;
}

svg {
    width: calc(100% + 2px);
  height: calc(100% + 2px);
  position: absolute;
  left: -1px;
  top: -1px;
  fill: none;
  stroke: #fff;
  stroke-dasharray: 150 480;
  stroke-dashoffset: 150;
  transition: 1s ease-in-out;
}

.btn:hover {
  transition: 1s ease-in-out;
  background: #4F95DA;
}

.btn:hover svg {
  stroke-dashoffset: -480;
}

.bg-line{
  width:100px;
  height:100px;
}

.btn span {
  color: white;
  font-size: 18px;
  font-weight: 100;
}
<div class="container">
        
    
      <button class="btn">
            
<!-- edit -->
        <svg viewBox="0 0 180 60" class="border" preserveAspectRatio="none" class="border">
      
       <polyline points="179,1 179,59 1,59 1,1 179,1" class="bg-line" />
      <polyline points="179,1 179,59 1,59 1,1 179,1" class="hl-line" />
    
    </svg>
                    
        <span>Junior is AWESOME</span>
      </button>
    
        
  </div>
  • OR

I really wanted to find a more correct way to do this without using SVG, I researched it all day, this is what I got:

I used the Animation, Before and Linear-gradient properties. The animation is not fluid because I’m not really good at it, and above all I recommend using a file just for keyframes.

(The “back” animation can be included later: D)
English from google translator

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

body, html {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: #5CA4EA;
  overflow: hidden;
  font-family: 'Lato', sans-serif;
}

.container {
  width: 400px;
  height: 400px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
}

.btn {
  cursor: pointer;
  background: rgb(99, 169, 235);
  border: 1px solid #91C9FF;
  outline: none;
  transition: 1s ease-in-out;
    padding:3%;
  padding-top:2%;
  padding-bottom:2%;
    position: relative;
    display: flex;
}

.btn::before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: -1;
    margin: -3px; /* !importanté */
    border-radius: inherit; /* !importanté */
    background: linear-gradient(0deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0) 99%, rgba(255,255,255,0) 100%);
  }

  .btn:hover::before{

-webkit-animation: all 1s; /* Chrome, Safari, Opera */ 
    animation: all 1s;
    transition:animation 1s ease-in-out;

  }

  @keyframes all {
    2%   {
      background: linear-gradient(-45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.3) 99%, rgba(255,255,255,0) 100%);
   }
   5%   {
      background: linear-gradient(-45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.5) 99%, rgba(255,255,255,0) 100%);
   }

    7%   {
      background: linear-gradient(-45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   14%   {
      background: linear-gradient(-23deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   22%   {
      background: linear-gradient(0deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   28%   {
      background: linear-gradient(23deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   35%   {
      background: linear-gradient(45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   43%   {
      background: linear-gradient(90deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   50%   {
      background: linear-gradient(120deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   57%   {
      background: linear-gradient(145deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   64%   {
      background: linear-gradient(180deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   71%   {
      background: linear-gradient(200deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   78%   {
      background: linear-gradient(220deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   85%   {
      background: linear-gradient(300deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   92%   {
      background: linear-gradient(320deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   94%   {
      background: linear-gradient(345deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.9) 99%, rgba(255,255,255,0) 100%);
   }

   97%   {
      background: linear-gradient(345deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.5) 99%, rgba(255,255,255,0) 100%);
   }

   100%   {
      background: linear-gradient(345deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.3) 99%, rgba(255,255,255,0) 100%);
   }

}

/* Chrome, Safari, Opera */
@-webkit-keyframes all {
      2%   {
      background: linear-gradient(-45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.3) 99%, rgba(255,255,255,0) 100%);
   }
   5%   {
      background: linear-gradient(-45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.5) 99%, rgba(255,255,255,0) 100%);
   }

    7%   {
      background: linear-gradient(-45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   14%   {
      background: linear-gradient(-23deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   22%   {
      background: linear-gradient(0deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   28%   {
      background: linear-gradient(23deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   35%   {
      background: linear-gradient(45deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   43%   {
      background: linear-gradient(90deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   50%   {
      background: linear-gradient(120deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   57%   {
      background: linear-gradient(145deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   64%   {
      background: linear-gradient(180deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   71%   {
      background: linear-gradient(200deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   78%   {
      background: linear-gradient(220deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   85%   {
      background: linear-gradient(300deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   92%   {
      background: linear-gradient(320deg, rgba(255,255,255,0) 72%, rgba(255,255,255,1) 99%, rgba(255,255,255,0) 100%);
   }

   94%   {
      background: linear-gradient(345deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.9) 99%, rgba(255,255,255,0) 100%);
   }

   97%   {
      background: linear-gradient(345deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.5) 99%, rgba(255,255,255,0) 100%);
   }

   100%   {
      background: linear-gradient(345deg, rgba(255,255,255,0) 72%, rgba(255,255,255,0.3) 99%, rgba(255,255,255,0) 100%);
   }
}

.btn:hover {
  transition: 1s ease-in-out;
  background: #4F95DA;
}

.btn:hover svg {
  stroke-dashoffset: -480;
}

.bg-line{
  width:100px;
  height:100px;
}

.btn span {
  color: white;
  font-size: 18px;
  font-weight: 100;
}
<div class="container">
        
    
      <button class="btn">
            
<!-- edit -->
                    
        <span>Junior is AWESOME</span>
      </button>
    
        
  </div>

Problem :

I’m trying to combine the look of one button, with the responsiveness of another button:

Button A: https://codepen.io/vitor-siqueira/pen/xNBExN

Button B: https://codepen.io/AnthonyBmm/pen/poooJmO

I would like to make Button C, which looks and feels exactly like Button A, but it automagically resizes to fit the button text (no wrap, like Button B). At the moment I create 3-4 virtually identical Button A’s and adjust the width values of the SVG and the CSS, which… is terrible practice.

I found Button B which has a similar animation but without an SVG and thought that it may be a good start to try and replicate the Button A effect, but I haven’t been able to succeed.

Can someone help please?


The attached code from the 2 pens can be found below:

Button A HTML:

  <div class="container">
    <div class="center">
      <button class="btn">
        <svg width="180px" height="60px" viewBox="0 0 180 60" class="border">
          <polyline points="179,1 179,59 1,59 1,1 179,1" class="bg-line" />
          <polyline points="179,1 179,59 1,59 1,1 179,1" class="hl-line" />
        </svg>
        <span>HOVER ME</span>
      </button>
    </div>
  </div>

Button A CSS:

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

body, html {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: #5CA4EA;
  overflow: hidden;
  font-family: 'Lato', sans-serif;
}

.container {
  width: 400px;
  height: 400px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
}

.center {
  width: 180px;
  height: 60px;
  position: absolute;
}

.btn {
  width: 180px;
  height: 60px;
  cursor: pointer;
  background: transparent;
  border: 1px solid #91C9FF;
  outline: none;
  transition: 1s ease-in-out;
}

svg {
  position: absolute;
  left: 0;
  top: 0;
  fill: none;
  stroke: #fff;
  stroke-dasharray: 150 480;
  stroke-dashoffset: 150;
  transition: 1s ease-in-out;
}

.btn:hover {
  transition: 1s ease-in-out;
  background: #4F95DA;
}

.btn:hover svg {
  stroke-dashoffset: -480;
}

.btn span {
  color: white;
  font-size: 18px;
  font-weight: 100;
}

Button B HTML:

<body>
    <a href="#">push this and that
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </a>
</body>

Button B CSS:

* {
    box-sizing: border-box;
}
body {
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background: #999;
}

a {
    /*border-radius: 12px;*/
    border: 3px outset #888;
    position: relative;
    display: inline-block;
    padding: 15px 30px;
    color: #eee;
    text-transform: uppercase;
    letter-spacing: 4px;
    overflow: hidden;
    
    box-shadow: 0 0 10px rgb(0, 0, 0, 1);
    font-family: verdana;
    font-size: 28px;
    font-weight: bolder;
    text-decoration: none;
    background:linear-gradient(160deg, #666, #444);
    text-shadow: 0px 0px 2px rgba(0, 0, 0, .5);

    transition: 0.2s;

}
a:active {
    border: 3px outset #ddd;
    color: #fff;
    background: linear-gradient(160deg, #666, #444);
    text-shadow: 0px 0px 4px #ccc;
    box-shadow: 0 0 10px #fff, 0 0 40px #fff, 0 0 80px #fff;
    transition-delay: 1s;
}

a span {
    position: absolute;
    display: block;
}

a span:nth-child(1) {
    top: 0;
    left: -100%;
    width: 100%;
    height: 2px;
    background: linear-gradient(90deg, transparent, #eee);
}
a:active span:nth-child(1) {
    left: 100%;
    transition: 1s;
}
a span:nth-child(2) {
    top: -100%;
    right: 0;
    width: 2px;
    height: 100%;
    background: linear-gradient(180deg, transparent, #eee);
}
a:active span:nth-child(2) {
    top: 100%;
    transition: 1s;
    transition-delay: 0.25s;
}
a span:nth-child(3) {
    bottom: 0;
    right: -100%;
    width: 100%;
    height: 2px;
    background: linear-gradient(270deg, transparent, #eee);
}
a:active span:nth-child(3) {
    right: 100%;
    transition: 1s;
    transition-delay: 0.5s;
}

a span:nth-child(4) {
    bottom: -100%;
    left: 0;
    width: 2px;
    height: 100%;
    background: linear-gradient(360deg, transparent, #eee);
}
a:active span:nth-child(4) {
    bottom: 100%;
    transition: 1s;
    transition-delay: 0.75s;
}

Comments

Comment posted by 17thelement

Thank you for your help Mech! I think I may be doing something wrong because I can’t notice any difference compared to the original? For instance, changing the font size to 28 or adding more text will keep the button border the same size, but the text would spill down. Can you reproduce this also?

Comment posted by 17thelement

Thank you very much @juniorGY, this is very helpful. I noticed that the hover animation does not follow the border entirely – you can see it better if you change font size to 28. I tried to adjust the left/top offsets but that didn’t work. Any suggestions, please?

Comment posted by Mauricio-MN

It is a fact that SVG is a vector and cannot have its resolution quality spoiled, but vectors also suffer from the stretching effect, in this case, the horizontal borders end up being thickened by the stretching of the button caused by the text size, and in this case not I know how to proceed, but the size of the SVG border has decreased due to the button having decreased, you can increase the padding of the button or the thickness of the SVG.

Comment posted by Mauricio-MN

The readjustment of position that I did in SVG to fill the border, is because the border of the button does not count as real size, so 100% size for the SVG does not fill it, and as the button has two vertical borders of 1px and two verticals of 1px, we have 2px more on the X and Y axis, which is exactly what we added to the SVG, and we reallocated it to -1px up and to the left. One solution would be an internal border for the button.

Comment posted by 17thelement

Ahh I understand, thank you for the in-depth explanation! That explains why even when I played around with the width and the X and Y axis alignment the lines were following their own paths instead of the border. So in this case there’s no way to achieve what I’m trying to achieve with the SVG. The only way is to adopt the Button B css method and try to hack it so that it animates like Button A. Is that correct?

Comment posted by Mauricio-MN

The way in which button B was done seems to solve the problem well, it is worth remembering that it is possible to correct the SVG using javascript, or create animations by CSS, the “before” and “after” properties would also be something to explore. I updated my post with a possible idea, but I’m not very good with animations in css …

By