【问题标题】:Responsive button animation CSS响应式按钮动画 CSS
【发布时间】:2020-06-24 17:19:59
【问题描述】:

我正在尝试将一个按钮的外观与另一个按钮的响应性结合起来:

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

按钮 B:https://codepen.io/AnthonyBmm/pen/poooJmO

我想制作按钮 C,它的外观和感觉与按钮 A 完全相同,但它会自动调整大小以适应按钮文本(没有换行,如按钮 B)。目前,我创建了 3-4 个几乎相同的按钮 A,并调整了 SVG 和 CSS 的宽度值,这是一种糟糕的做法。

我发现按钮 B 具有类似的动画但没有 SVG,并认为尝试复制按钮 A 效果可能是一个好的开始,但我未能成功。

有人可以帮忙吗?


2 支笔的附加代码如下:

按钮 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>

按钮 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;
}

按钮 B HTML:

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

按钮 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;
}

【问题讨论】:

    标签: html css svg button hover


    【解决方案1】:

    这是你要找的吗?

    @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>

    【讨论】:

    • 感谢您的帮助机甲!我想我可能做错了什么,因为我没有注意到与原版相比有什么不同?例如,将字体大小更改为 28 或添加更多文本将使按钮边框保持相同大小,但文本会向下溢出。你也能重现这个吗?
    【解决方案2】:

    我的这个“更正”是基于帖子this post 让 svg 负责。

    对不起谷歌翻译的英文。

    @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>

    我真的很想找到一种更正确的方法来做到这一点,而不使用 SVG,我研究了一天,这就是我得到的:

    我使用了 Animation、Before 和 Linear-gradient 属性。动画不是很流畅,因为我不是很擅长,最重要的是我建议只为关键帧使用文件。

    (后面可以包含“后退”动画:D) 来自谷歌翻译的英语

    @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>

    【讨论】:

    • 非常感谢@juniorGY,这很有帮助。我注意到悬停动画并没有完全跟随边框 - 如果将字体大小更改为 28,您可以更好地看到它。我尝试调整左/上偏移,但没有奏效。有什么建议吗?
    • SVG是一个矢量,不能破坏它的分辨率,这是一个事实,但是矢量也会受到拉伸效果的影响,在这种情况下,水平边框最终会被拉伸而变粗。按钮由文本大小引起,在这种情况下我不知道如何进行,但是由于按钮减小,SVG边框的大小减小了,您可以增加按钮的填充或SVG的厚度。
    • 我在 SVG 中为填充边框所做的位置重新调整,是因为按钮的边框不计为实际大小,因此 SVG 的 100% 大小不会填充它,并且作为该按钮有两个 1px 的垂直边框和两个 1px 的垂直边框,我们在 X 和 Y 轴上多了 2px,这正是我们添加到 SVG 的内容,我们将其重新分配到 -1px 向上和向左。一种解决方案是按钮的内部边框。
    • 啊我明白了,谢谢你的深入解释!这就解释了为什么即使我使用宽度和 X 轴和 Y 轴对齐,线条也遵循它们自己的路径而不是边界。所以在这种情况下,没有办法实现我想要通过 SVG 实现的目标。唯一的方法是采用 Button B 的 css 方法并尝试对其进行 hack,使其像 Button A 一样具有动画效果。对吗?
    • 按钮 B 的制作方式似乎很好地解决了问题,值得记住的是,可以使用 javascript 更正 SVG,或者通过 CSS、“之前”和“创建动画” after" 属性也是值得探索的东西。我用一个可能的想法更新了我的帖子,但我对 css 中的动画不是很好......
    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    相关资源
    最近更新 更多