创建交互式 HTML5 输入

2025-05-25

创建交互式 HTML5 输入

让网站对终端用户更具吸引力的方法之一是增加额外的互动性和响应能力。这不仅赏心悦目,还能提升用户的参与度。

从这个意义上讲,达林·森内夫 (Darin Senneff) 和其他 许多 在创建交互式表单和复杂组件/模板方面所做的工作非常令人着迷——到目前为止,我最喜欢的是森内夫 (Senneff) 的登录表单

但这些动画和交互功能并非复杂组件的专属。你几乎可以在任何地方添加微交互——适度即可,否则可能会过于繁琐——而表单控件非常适合这种情况。

此外,您无需使用大型框架或库来实现这一点。库可以让您的工作更轻松,动画更流畅——GSAPSVG 动画方面表现出色——而且许多浏览器已经支持 SVG 动画,无需额外代码。

这就是为什么在这篇文章中,我们将了解如何使用纯 HTML、CSS 和 JavaScript 来创建可适应用户输入值的交互式输入字段。

无需复杂的组件,无需庞大的框架,无需外部库。只需利用标准 HTML、CSS 和原生 JavaScript。效果可能不那么炫酷,但学习起来却毫无难度。

现在,让我们开始吧...

我们要建造什么?

我们将创建一个使用默认 HTML5 时间输入的时间选择器,并且为了识别字段,它已扩展了一个交互式图标(更改时间并查看图标对新值的响应):

如上所述,我们不会使用任何库或框架,因此开发所需的只是一个文本编辑器来编写代码,以及一个浏览器来查看结果。

让我们从有趣的部分开始吧。

代码

这听起来可能有点奇怪,但整个功能只需要 15 行 HTML、CSS 和 JavaScript 代码。没错,你可能需要多写一点代码才能按照你想要的方式设置输入样式,但基本功能只需要 1 行 HTML、7 行 CSS 和 8 行纯 JavaScript 代码。真的。

HTML

不久前,HTMLinput标签类型非常有限:我们只有文本输入框、密码文本、单选按钮、复选框和常规按钮。但作为 HTML5 的一部分,添加了许多输入类型:

<input type="email" />             <!-- Email -->
<input type="url" />               <!-- URL -->
<input type="search" />            <!-- Search string -->
<input type="number" />            <!-- Number -->
<input type="date" />              <!-- Date -->
<input type="week" />              <!-- Week -->
<input type="month" />             <!-- Month -->
<input type="datetime" />          <!-- Datetime (obsolete, use the one below) -->
<input type="datetime-local" />    <!-- Datetime -->
<input type="tel" />               <!-- Telephone -->
Enter fullscreen mode Exit fullscreen mode

浏览器也意识到了这一点:如果开发者指定输入框是 类型date,为什么只显示为一个无聊的文本输入框呢?他们可以显示一个格式化的输入框,并弹出一个日历窗口供用户选择。例如,这是 Chrome 浏览器的日历窗口:

Chrome 上的默认日期选择器

使用它们有一些好处:这些输入格式正确,开箱即用。无需担心用户输入的日期是否正确,浏览器会帮你输入,这对用户来说自然而透明。

其中一个不便之处是一些老版本的浏览器不支持这些新的文本输入。但这并不是什么大问题,因为如果输入类型无法被识别,它就会被简单地显示为常规的文本输入。

另一个不便之处在于弹出窗口/显示格式无法设置样式。至少,无法以所有浏览器通用的方式设置。不过,本文不会讨论这个问题。

回到代码。我们的输入将是“时间”类型,因此所需的所有 HTML 代码如下:

<input type="time" />
Enter fullscreen mode Exit fullscreen mode

只需这样做,支持该类型的浏览器就会显示如下内容:

Chrome 上的空白时间选择器

就这样。让我们继续下一步。

CSS

在深入研究 CSS 之前,我们先来了解一下 SVG。SVG(可缩放矢量图形的缩写)格式允许我们使用类似于 HTML 的 XML 符号来创建矢量图像。

使用 SVG,我们可以绘制圆形、矩形、线条(直线或使用路径绘制的曲线),并且它可以自适应不同的尺寸而不会损失质量。在本例中,我创建了一个带有两个简单手柄的时钟小图像:

<svg xmlns='http://www.w3.org/2000/svg' width='40px' height='40px' viewBox="0 0 40 40">
  <circle cx='20' cy='20' r='18.5' fill='none' stroke='#222' stroke-width='3' />
  <path d='M20,4 20,8 M4,20 8,20 M36,20 32,20 M20,36 20,32' stroke='#bbb' stroke-width='1' />
  <g fill='#222' stroke='#222' stroke-width='2'>
    <circle cx='20' cy='20' r='2' />
    <path d='M20,24 20,5' style='transform:rotate(120deg); transform-origin: 50% 50%;' />
    <path d='M20,24 20,8' style='transform:rotate(20deg); transform-origin: 50% 50%;' />
  </g>
</svg>
Enter fullscreen mode Exit fullscreen mode

这将生成如下时钟:

基本 SVG 时钟

另外,SVG 的一个优点是它可以在 CSS 中内联使用。因此,我们可以通过以下方式将其设置为元素的背景图像:

background-image: url("data:image/svg+xml;utf8,<svg>...</svg>");
Enter fullscreen mode Exit fullscreen mode

现在我们有了图像,并且知道如何在 CSS 中使用它,我们需要考虑还需要什么:

  • 设置背景图像(如上所述background-image)。
  • 将图像放在输入的左侧(带有background-position)。
  • 表示图像不应重复(使用background-repeat)。
  • 使其与文本一样大(使用background-size)。
  • 通过在输入内推入文本(使用padding-left)来为图像留出一些空间。

我们知道如何在 CSS 中实现上述所有功能。其实并没有那么复杂!代码如下:

input[type="time"] {
  padding-left: 1.5em;
  background-repeat: no-repeat;
  background-position: 0.25em center;
  background-size: 1em;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><circle cx='20' cy='20' r='18.5' fill='none' stroke='%23222' stroke-width='3' /><path d='M20,4 20,8 M4,20 8,20 M36,20 32,20 M20,36 20,32' stroke='%23bbb' stroke-width='1' /><g fill='%23222' stroke='%23222' stroke-width='2'><circle cx='20' cy='20' r='2' /><path d='M20,24 20,5' style='transform:rotate(120deg); transform-origin: 50% 50%;' /><path d='M20,24 20,8' style='transform:rotate(20deg); transform-origin: 50% 50%;' /></g></svg>");
}
Enter fullscreen mode Exit fullscreen mode

注意我们如何使用em作为单位。这将帮助图标自动调整其位置和大小,而不受输入文本字体大小单位的影响。

通过这 7 行代码,时间输入现在如下所示:

Chrome 上的空白时间选择器,左侧带有时钟图标

由于某些奇怪的原因,当我们添加背景图片时,Chrome 会添加不同类型的边框。不过我们不用太担心,因为我们可以稍后再调整边框的样式,让它看起来更美观。

让我们通过在 JavaScript 中添加交互来完成我们的时钟。

JavaScript

为了实现交互性,我们将使用原生 JavaScript。我们的目标是,每次

// every time that the time picker changes value
document.querySelector("input[type='time']").addEventListener("input", function() {
  // regular expression that verifies the format HH:MM
  const reTime = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/;
  // if the value matches the regular expression
  if (reTime.exec(this.value)) {
    // read the values of minutes and hours and update them
    const minute = Number(this.value.substring(3,5));
    const hour = Number(this.value.substring(0,2)) % 12 + (minute / 60);
    // set the same background image but with different hour/minute angles
    this.style.backgroundImage = `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><circle cx='20' cy='20' r='18.5' fill='none' stroke='%23222' stroke-width='3' /><path d='M20,4 20,8 M4,20 8,20 M36,20 32,20 M20,36 20,32' stroke='%23bbb' stroke-width='1' /><g fill='%23222' stroke='%23222' stroke-width='2'><circle cx='20' cy='20' r='2' /><path d='M20,24 20,5' style='transform:rotate(${360 * minute / 60}deg); transform-origin: 50% 50%;' /><path d='M20,24 20,8' style='transform:rotate(${360 * hour / 12}deg); transform-origin: 50% 50%;' /></g></svg>")`;
  }
});
Enter fullscreen mode Exit fullscreen mode

我不仅将小时值调整为小时,还将其调整为该小时内经过的分钟数,从而使小时值更加真实。

这 8 行 JavaScript 代码(不含注释)将使时钟句柄更新,以表示输入框中选择的时间。最终结果如下(略作修改,使其看起来更美观):

一个闪烁问题

我在 Mac 和 Windows 上的不同浏览器中对此进行了测试,结果如下:

  • 在基于 Chromium 的浏览器(Chrome、Opera、Brave、新 Edge 等)和 Firefox 上,输入type="time"和动画均可正常工作。
  • 在 Safari 上,输入type="time"不起作用,但如果用户输入有效的时间(格式HH:MM),动画就会起作用。
  • 在 Windows 的 Edge 上,输入type="time"确实有效,但动画无效(整个时钟未显示)。

不过,在 Firefox 上存在一个问题。当使用 JavaScript 更新手柄角度时,整个时钟图标会闪烁。这是由 Firefox 处理背景重新渲染的方式造成的。

最小化闪烁影响的一种方法是将 SVG 拆分成更小的部分:一部分用于时钟框架,另外两部分分别用于每个手柄。CSS 允许堆叠多个背景图像,并用逗号分隔:

background-image: url(image1), url(image2), ...url(imageN);
Enter fullscreen mode Exit fullscreen mode

这样,当我们更新时间时,唯一会闪烁的就是手柄,而且它们无论如何都会移动,所以闪烁消失了(或部分消失了)。

结论

通过对 HTML5 及其输入类型的扩展支持,我们可以创建不需要繁重的库或复杂编码的交互式元素。

虽然支持可能尚未完全实现,但展望未来,我们应该指望获得越来越多的支持,因为失败的浏览器最终会消失(IE)、适应(Edge 切换到 Chromium)或增加支持(Safari……希望如此)。

未来还有很长的路要走,因为不同浏览器的弹出窗口样式(例如日历、周、月等等)仍然有很大差异。但一切都会好起来的。

此外,这种交互性并不局限于时间类型。您可以将类似的效果应用于任何输入类型,并创建自己的效果。唯一的限制在于您的想象力。其他示例:


希望你喜欢这篇文章,它又比我预想的要长。如果你读到这里……谢谢你的阅读!

文章来源:https://dev.to/alvaromontoro/creating-interactive-html-inputs-2ldi
PREV
如何使用 HTML 和 CSS 创建进度条(视频)
NEXT
100天CSS插图