仿 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
- 定义两个变量, 分别表示开关的开关和默认的背景颜色, 重置样式, 定义一个
flex 的水平垂直居中布局:root {
--radius: 20px;
--bgColor: #fff;
}
* {
padding: 0;
margin: 0;
}
.flex {
display: flex;
justify-content: center;
align-items: center;
}
- 设置
container 容器的样式. 这里要使用之前定义的变量 bgColor , 给背景颜色的变化加上线性过渡.container {
height: 100vh;
background-color: var(--bgColor);
transition: background-color .2s linear;
}
- 设置开关默认的样式
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;
}
- 设置开关中圆点?的效果
- 注意其
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;
}
- 设置
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');
}
})
完整代码
<!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>
: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 );
}
谢谢你看到这里😀
|