使用 HTML 和 CSS 构建交互式登录表单
Darin Senneff 创建的 Yeti 登录表单非常棒,和他构建的大多数东西一样,一直是我的灵感源泉:
以前,我曾使用 HTML、CSS、SVG 和 JavaScript 创建过这个动画登录表单。但由于我使用了纯 CSS 来为 SVG 制作动画(而不是添加GreenSock),而且并非所有浏览器都支持 GreenSock,所以动画效果有些不流畅。
经过几周异常忙碌的工作后,昨天我终于抽出时间进行了一些有趣的开发。我决定尝试使用 HTML 和 CSS 来开发这个交互式表单的另一个版本,完全不使用任何 SVG 或 JavaScript。
如果您想要一个类似的教程,但使用 JavaScript,请不要错过“如何构建交互式表单”系列,其中我将逐步解释如何使用 HTML、CSS 和 JS 构建像这样的表单。
不使用 JavaScript 或 SVG 的限制使其更具挑战性,并看看它是否可行(剧透警告:有点可行,但有一些限制),并在构建它时学习新的东西。
结果如下:
第一步是创建一个简单的表单,其中包含我想要的元素,顺序如下:
- 人物形象(仅需简单的 CSS)
- 用户名/电子邮件文本字段(标签+输入)
- 密码文本字段(标签+输入)
- 显示密码复选框(输入+标签)
- 提交按钮
- 忘记密码链接
我拥有了没有动画或交互性的表单的主要结构...然后乐趣就开始了。
组织元素
在我之前的表单中,交互是通过 JavaScript 处理的。没有 JavaScript 意味着我必须使用字段中的信息来制作图像动画……这意味着我必须稍微重构一下代码。
CSS 图像不能再放在顶部了,因为它需要字段的值来更新其状态。即使显示在顶部,它也需要位于代码的底部。为此,我可以尝试使用FlexBox或Grid 等不同的方法。
我选择了 FlexBox - 事后看来,它可能不是最好的选择 - 并使用该order
属性对元素进行重新排序。
因此,图像移到了底部,“显示密码”按钮移到了密码顶部。order
应用了一些值,我必须调整tabindex
元素,使它们的键盘顺序与显示顺序一致(这稍后会引起一些可访问性问题)。
最终订单如下:
- 用户名/电子邮件文本字段
- 显示密码复选框
- 密码文本字段
- 提交按钮
- 忘记密码链接
- 人物形象
动画图像
现在所有元素都已到位,并且 CSS 人物已绘制完毕,我可以为其添加一些动画。
一个简单的方法是让它眨眼:它不依赖于任何其他东西,考虑到眼睛是圆形的,为了模拟眨眼,我们将眼睛的高度从原始值改为 0,然后再改回原始值。像这样(简化):
@keyframes blink {
0%, 90%, 100% {
height: 0.625rem;
}
95% {
height: 0;
}
}
.eyes {
animation: blink 5s infinite;
}
这很简单。接下来是嘴巴。角色的眼睛里总是带着一丝微笑,但为了表示所有字段都正确,它笑得更灿烂一些。
为了实现这一点,我使用 HTML 验证(见下文)并将其与选择器:valid
/结合起来:invalid
。
嘴巴是元素的底部边框。为了使其更大,我调整了该元素的宽度和高度(以及位置)。代码简化:
.mouth {
border: 0.125rem solid transparent;
border-bottom: 0.125rem solid #422;
border-radius: 50%;
transition: all 0.5s
}
/* invalid: smile... but not too much */
form:invalid .mouth {
top: 75%;
left: 50%;
width: 25%;
height: 10%;
}
/* valid: big smile by expanding size */
form:valid .mouth {
top: 60%;
left: 50%;
width: 40%;
height: 40%;
}
不幸的是,:valid
/:invalid
伪类不能很好地与 IE 和 Edge 中的表单配合使用......这限制了演示的范围。
一个额外的动画是,当勾选“显示密码”字段时,角色会闭上眼睛。我还可以添加一些更精致的动画(比如让双手上下移动),但我将留待以后改进。
隐藏密码
让文本从普通文本变为星号再变回来是最棘手的功能。我本来可以发誓用 就能实现text-transform
,但事实并非如此。
有一个非标准-webkit-text-security
属性允许开发者实现这一点。但它只适用于 WebKit 浏览器。这是一个测试,所以我尝试了一下(代码已简化):
/* show the text field as asterisks in normal mode */
input[name="password"] {
-webkit-text-security: disc;
}
/* if show password is checked, show the actual text */
input[name="show-password"]:checked ~ input[name="password"] {
-webkit-text-security: none;
}
这确实有效。但在开发表单的所有技巧中,这可能是唯一一个我肯定会用 JavaScript 替换的,因为它大大减少了表单的支持。
颜色和主题
如今,能够改变组件和站点的颜色是一项主要功能……为什么不将它添加到我的演示中呢?
我没有使用颜色、阴影或大小的固定值,而是在更高级别(表单标签)定义CSS 变量并在其中包含的元素中重复使用它们。
对于颜色,我选择了HSL 格式。在 HSL 中,你可以定义颜色的色相、饱和度和亮度,这对于创建阴影非常方便……并且与 CSS 变量和函数结合使用时功能非常强大。
hsl()
/函数hsla()
允许 CSS 变量和其他函数(尤其是calc()
)作为参数。因此,我们可以定义默认颜色,并根据不同的状态设置不同的色调。
在这个例子中,我们使用深蓝色作为按钮的背景,而对于悬停状态,我们使用相同颜色的 20% 暗色调:
form {
/* default color: dark blue in HSL */
--colorH: 210;
--colorS: 50%;
--colorL: 38%;
}
/* the button will be dark blue by default */
form button {
background: hsl(
var(--colorH),
var(--colorS),
var(--colorL)
);
}
form button:hover {
/* 20% darker using calc */
background: hsl(
var(--colorH),
var(--colorS),
calc(var(--colorL) * 0.8)
);
}
这是一个屏幕截图,您可以看到改变色调值如何改变表单中使用的调色板:
构建表单不需要玩颜色和 HSL,但这很有趣。
表单验证
对于这一点,我没有让自己复杂化:删除所有 JavaScript 验证,并使用标准 HTML5 验证将其委托给浏览器:
这只是一个演示。如果是更重要的事情,或者需要投入生产,我会在 HTML 验证的同时使用 JS。但在本例中,目标是避免使用 JavaScript,所以……
浏览器兼容性问题
使用Brave(基于Chrome的浏览器)完成开发后,我发现了一些问题:
- 显示/隐藏密码(我使用的
-webkit-text-security
)。 - IE/Edge 中表单级别的
:valid
/问题。:invalid
尽管如此,我继续在不同的浏览器上测试,发现了一个新问题。耶!Safari 似乎在动画中使用的单位有问题。通过将 替换为相应的rem
单位,问题得到了解决。rem
px
可访问性问题
说实话,考虑到我当时正在调整 Flex 的排序和样式,我本来没指望登录表单能做到无障碍访问。但经过一些测试后,结果比我最初预想的要好得多。
例如,如果页面加载时没有样式,则登录表单如下所示:
标签文本出现在其字段之后——这很奇怪,但仍然可以理解——而“显示密码”字段出现在该字段之前。这也很常见(毕竟 Senneff 的表单也把它放在了顶部。)
运行自动化可访问性测试的结果也还不错。Wave只发现了三个问题(与 相关tabIndex
),而aXe检测到了标签的对比度问题(在静止模式下有效,但在悬停或活动模式下无效)。
之后,我还尝试与键盘进行交互并使用几个屏幕阅读器(VoiceOver和ChromeVox)。
Chrome(根据最新的 WebAIM 调查,它是使用最广泛的浏览器)的结果是积极的:按顺序浏览字段,并且即使代码中的顺序与屏幕上的顺序不匹配,屏幕阅读器也能正确读取所有内容。
Safari 不太成功,并且在关注复选框时出现一些问题(这个问题似乎很常见,而且不仅仅出现在我的表单上......但这不是重点。)
我不会在实际生产环境中(完全)使用这个表单,因为有些功能(例如密码显示/隐藏、表单有效性)并非所有浏览器都支持(IE 和 Edge 是主要问题)。不过开发它还是一次不错的尝试。
在此过程中,我练习了一些 FlexBox,使用了一些有趣的选择器和伪类,了解了-webkit-text-security
(感谢Chris Coyier 在 CSS-Tricks 上的帖子)......这很好。