「原生练手」打造一个波浪动画登录表单
本篇文章我们会实现一个酷炫的登录表单,主要体现在表单字段的标签的波浪特效上,就像下图中这样:
思路分析
整个表单的核心就在这个波浪特效的设计,这里我们需要用到transition-delay
这个属性,表单字段标签中的每个字符我们都用一个span
去包裹,然后通过transition-delay
设置一个延迟,比如第一个字符延迟0ms
后开始过渡动画,第二个字符延迟50ms
后开始过渡动画,以此类推
然后在输入框focus
的时候使用transform
去改变每个字符的位置即可实现该效果
HTML
首先看看整体页面的结构
<div class="login-form">
<h1>Login</h1>
<form action="#">
<div class="form-item">
<input id="email" type="text" />
<label for="email">
<span style="transition-delay: 0;">E</span>
<span style="transition-delay: 50ms;">m</span>
<span style="transition-delay: 100ms;">a</span>
<span style="transition-delay: 150ms;">i</span>
<span style="transition-delay: 200ms;">l</span>
</label>
</div>
<div class="form-item">
<input id="password" type="password" />
<label for="password">Password</label>
</div>
<button type="submit">Login</button>
<p>Don't have an account? <a href="#">Register</a></p>
</form>
</div>
根据前面的思路分析,这里我给email
表单字段的标签设置成五个span
标签,分别存放每个字符,然后通过内联样式添加上transition-delay
过渡动画延迟,这样一来其实就可以纯css
去实现波浪效果
但是感觉这样的话,html
的可读性变低了,所以我会考虑采用第二种方案 -- 用js
动态生成span
标签
比如这里的password
字段的label
中就是一个Password
字符串,那么可以通过js
遍历这些字符,将每个字符包裹到一个span
标签里面,动态插入到html
中,这样一来,html
的代码就会变得简洁不少,提高可读性
JavaScript
根据上面的分析,我们先来实现js
的部分,js
部分很简单,就是遍历label
中的每个字符,用span
去包裹后再放回label
标签中
((doc) => {
/** @type { HTMLLabelElement[] } */
const oLabels = doc.querySelectorAll(".login-form .form-item label");
const init = () => {
oLabels.forEach((oLabel) => {
oLabel.innerHTML = oLabel.innerText
.split("")
.map(
(letter, idx) =>
`<span style="transition-delay: ${idx * 50}ms;">${letter}</span>`
)
.join("");
});
};
init();
})(document);
CSS
最后我们再来看看css
的实现:
@import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Fira+Mono:wght@400;500;700&display=swap");
:root {
--primay-color: #4c3575;
--form-bg-color: #371b58;
--form-text-color: #ca82ff;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
body {
display: grid;
place-items: center;
background-color: var(--primay-color);
font-family: "Fira Mono", monospace;
}
.login-form {
display: flex;
flex-direction: column;
align-items: center;
color: var(--form-text-color);
padding: 30px;
background-color: var(--form-bg-color);
border-radius: 12px;
}
.login-form form {
display: flex;
flex-direction: column;
width: 100%;
}
.login-form .form-item {
position: relative;
margin-bottom: 30px;
}
.login-form .form-item input {
display: block;
width: 100%;
color: white;
background-color: transparent;
border: none;
border-bottom: 2px solid white;
padding: 15px 0;
font-size: 24px;
}
.login-form .form-item input:focus {
outline: none;
}
.login-form .form-item label {
position: absolute;
top: 20px;
left: 0;
}
.login-form .form-item label span {
display: inline-block;
transition: all 0.3s ease;
}
.login-form .form-item input:focus + label span {
color: var(--form-text-color);
transform: translateY(-30px);
}
.login-form button {
width: 100%;
cursor: pointer;
padding: 15px;
border: none;
border-radius: 12px;
background-color: var(--form-text-color);
transition: transform 0.5s ease;
}
.login-form button:active {
transform: scale(0.95);
}
.login-form a {
text-decoration: none;
color: #a760ff;
}
整体都很常规,主要核心就在于当input
出于focus
状态的时候,要给label
中的span
进行一个Y
轴方向上的偏移,再结合上内联样式中的transition-delay
样式实现依次位移的效果,也就是波浪动画
配色的选择
整个表单看起来要顺眼的话,配色很重要,这里我的配色原则是,背景色要浅色,表单主体要深色,并且要是同一个色系的,最后文字的颜色要比背景色更浅更亮,这样整个表单看起来就会很自然顺眼不少
关于配色网站,这里推荐一个我平时经常用的,里面很多好看配色