仿 Tailwind CSS 官网首页 一个 button 的变化动画

1,191 阅读2分钟

仿 Tailwind CSS 官网首页 一个 button 的变化动画

先来看一下 tailwind CSS 官网这个动画的效果. 模仿这个动画可以学到的是定义和使用 CSS 变量以及在 JavaScript 中操作修改 CSS 变量. 在之前的交互动画模仿中, 借用了 <input type="radio">, 而这次则改用 <input type="checkbox"> 请添加图片描述 下面是我模仿的结果 请添加图片描述

HTML

<div class="container flex">
   <input type="checkbox" title="this input" name="input" id="input-switch">
   <label for="input-switch">
     <div class="switch">
       <div class="button"></div>
     </div>
   </label>
 </div>

因为开关是可以开也可以关, 所以不能用 radio 因为其开了再点就不会关. 所以改用 checkbox

CSS

  1. 定义两个变量, 分别表示开关的开关和默认的背景颜色, 重置样式, 定义一个 flex 的水平垂直居中布局
    :root {
      --radius: 20px;
      --bgColor: #fff;
    }
    * {
      padding: 0;
      margin: 0;
    }
    .flex {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
  2. 设置 container 容器的样式. 这里要使用之前定义的变量 bgColor, 给背景颜色的变化加上线性过渡
    .container {
      height: 100vh;
      background-color: var(--bgColor);
      transition: background-color .2s linear;
    }
    
  3. 设置开关默认的样式
    • border-radius: 9999px; 是为了使得按钮有💊的效果, 两端是圆的.
    .switch {
      width: calc( var(--radius) * 2.2 ); 
      height: calc( var(--radius) );
      background-color: rgb(96, 211, 96);
      border-radius: 9999px;
      position: relative;
      padding: 2px;
      transition: background-color .2s linear;
    }
    
  4. 设置开关中圆点⚪的效果
    • 注意其absolute 定位, 将来要修改其 left 控制其位置变化. 默认位置是靠左靠上 2px, 就是父元素的padding大小. 📕注意: left 是相对于父元素的 border 计算的, 所以要加上 父元素的 padding
    .button {
      height: var(--radius);
      width: var(--radius);
      border-radius: 50%;
      background-color: rgba(255, 255, 255, 0.9);
      transition: all .2s ease-in-out;
      position: absolute;
      left: 2px;
      top: 2px;
    }
    
  5. 设置checkbox效果
    • 默认是不显示
    • 选中后修改按钮的背景色. 并且修改⚪的left, 为父元素的 width (📕注意 width 不包括 padding) 减去自身宽度再加上 padding
    input[type="checkbox"] {
      display: none;
    }
    input[type="checkbox"]:checked + label .switch {
      background-color: #D10;
    }
    input[type="checkbox"]:checked + label .switch .button {
      left: calc( var(--radius) * 2.2 - var(--radius) + 2px );
    }
    

JavaScript

使用 setProperty 修改颜色

document.getElementById('input-switch').addEventListener('click', (e) => {
  if (e.target.checked) {
    document.body.style.setProperty('--bgColor', 'rgb(17, 24, 39)');
  } else {
    document.body.style.setProperty('--bgColor', '#fff');
  }
})

完整代码

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Switch</title>
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="../css/font-awesome.css">
</head>
<body>
  <div class="container flex">
    <input type="checkbox" title="this input" name="input" id="input-switch">
    <label for="input-switch">
      <div class="switch">
        <div class="button"></div>
      </div>
    </label>
  </div>
  <script>
    document.getElementById('input-switch').addEventListener('click', (e) => {
      if (e.target.checked) {
        document.body.style.setProperty('--bgColor', 'rgb(17, 24, 39)');
      } else {
        document.body.style.setProperty('--bgColor', '#fff');
      }
    })
  </script>
</body>
</html>

CSS

:root {
  --radius: 20px;
  --bgColor: #fff;
}

* {
  padding: 0;
  margin: 0;
}
.container {
  height: 100vh;
  background-color: var(--bgColor);
  transition: background-color .2s linear;
}

.flex {
  display: flex;
  justify-content: center;
  align-items: center;
}
.switch {
  width: calc( var(--radius) * 2.2 ); 
  height: calc( var(--radius) );
  background-color: rgb(96, 211, 96);
  border-radius: 9999px;
  position: relative;
  padding: 2px;
  transition: background-color .2s linear;
}

.button {
  height: var(--radius);
  width: var(--radius);
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.9);
  transition: all .2s ease-in-out;
  position: absolute;
  left: 2px;
  top: 2px;
}

input[type="checkbox"] {
  display: none;
}
input[type="checkbox"]:checked + label .switch {
  background-color: #D10;
}
input[type="checkbox"]:checked + label .switch .button {
  left: calc( var(--radius) * 2.2 - var(--radius) + 2px );
}

谢谢你看到这里😀