【午休时刻-CSS】三分钟整个3D Button

238 阅读1分钟

先放张效果图,或者戳这里体验一下;或者直接去看作者英文文档找作者

效果图

起步

首先来搭个按钮的基本的架子

 <style>
  .wrapper {
    background: #A30036;
    border-radius: 12px;
    border: none;
    padding: 0;
    cursor: pointer;
    outline-offset: 4px;
  }
  
  .front {
    display: block;
    padding: 12px 42px;
    border-radius: 12px;
    font-size: 1.25rem;
    background: red;
    color: white;
    transform: translateY(-4px);
  }

</style>
<body>
  <button class="wrapper">
      <span class="front">
      戳一下
    </span>
  </button>
</body>
效果图

接下来在点击的时候使用transform: translate滑动前景图层,让它动起来,产生3d的效果, 这是实现这种效果的最佳方法,因为转换可以通过硬件加速。

.wrapper:active .front {
    transform: translateY(-2px);
 }
效果图

现在基本的动作有了,但感觉还是很生硬,来在原来基础上加点动画,这里使用了will-change以便这个动画可以被硬件加速

 .front{
    will-change: transform;
    transition: transform 600ms cubic-bezier(0.3, 0.7, 0.4, 1);/*控制按压回弹*/
}

.wrapper:hover .front {
            transform: translateY(-6px);
            transition: transform 250ms cubic-bezier(.3, .7, .4, 1);//
        }

.wrapper:active .front {
  transform: translateY(-2px);
  transition: transform 34ms;
}

这里需要注意,不要把hoveractive顺序搞反了,否则按钮就点击不了了

关于cubic-bezier请移步贝塞尔曲线

效果图

添加阴影

底部阴影

为了让效果更像3D,可以使用box-shadow达到阴影效果,但为了能达到更好的效果,这里采用之前的方法,新增了一层shadow,用来展示阴影效果

<style>
.wrapper:hover .shadow {
            transform: translateY(4px);
            transition: transform 250ms cubic-bezier(.3, .7, .4, 1.5);
        }
.wrapper:active .shadow {
  transform: translateY(1px);
  transition: transform 34ms;
}
</style>

<body>
<button class="wrapper">
    <span class="shadow"></span>
    <span class="front">
    戳一下
  </span>
</button>
</body>

效果图

底部阴影渐变

新增一层edge,使其产生阴影渐变的效果

<style>
.edge {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 12px;
            background: linear-gradient(
                    to left,
                    hsl(340deg 100% 16%) 0%,
                    hsl(340deg 100% 32%) 8%,
                    hsl(340deg 100% 32%) 92%,
                    hsl(340deg 100% 16%) 100%
            );
        }
</style>
<body>      
    <button class="wrapper">
        <span class="shadow"></span>
        <span class="edge"></span>
        <span class="front">
        戳一下
      </span>
    </button>
</body>
效果图

移动端优化

  1. 在移动端,点击按钮会发现出现一个点击反馈的框框
效果图

可以使用以下属性去除

  .wrapper {
    -webkit-tap-highlight-color: transparent;
  }
  1. ios中无法点击按钮,添加ontouchstart,或者docuemnt上绑定touchstart事件
<button class="wrapper" ontouchstart="">
...
  </span>
</button>
document.addEventListener("touchstart", function() {
   // .....
},false);

完整案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
    <style>
        body{
           text-align: center;
            padding-top: 20px;
        }
        .wrapper {
            position: relative;
            background:  transparent;
            border-radius: 12px;
            border: none;
            padding: 0;
            cursor: pointer;
            outline-offset: 4px;
            user-select: none;
            -webkit-tap-highlight-color: transparent;
        }
        .wrapper:hover {
            filter: brightness(110%);
        }
        .front {
            user-select: none;
            display: block;
            padding: 12px 42px;
            border-radius: 12px;
            font-size: 1.25rem;
            background: red;
            color: white;
            transform: translateY(-4px);
            will-change: transform;
            /*控制按压回弹*/
            transition: transform 600ms cubic-bezier(0.3, 0.7, 0.4, 1);
        }

        .shadow {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 12px;
            background: hsl(0deg 0% 0% / 0.25);
            will-change: transform;
            transform: translateY(2px);
            transition:
                    transform
                    600ms
                    cubic-bezier(.3, .7, .4, 1);
        }

        .wrapper:hover .front {
            transform: translateY(-6px);
            transition:
                    transform
                    250ms
                    cubic-bezier(.3, .7, .4, 1);
        }

        .wrapper:active .front {
            transform: translateY(-2px);
            transition: transform 34ms;
        }

        .wrapper:hover .shadow {
            transform: translateY(4px);
            transition:
                    transform
                    250ms
                    cubic-bezier(.3, .7, .4, 1.5);
        }
        .wrapper:active .shadow {
            transform: translateY(1px);
            transition: transform 34ms;
        }

        .edge {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 12px;
            background: linear-gradient(
                    to left,
                    hsl(340deg 100% 16%) 0%,
                    hsl(340deg 100% 32%) 8%,
                    hsl(340deg 100% 32%) 92%,
                    hsl(340deg 100% 16%) 100%
            );
        }


    </style>
</head>
<body>
<button class="wrapper" ontouchstart="">
    <span class="shadow"></span>
    <span class="edge"></span>
    <span class="front">
    戳一下
  </span>
</button>
</body>
</html>

原文地址

www.joshwcomeau.com/animation/3…