表格输入和文本区的自定义CSS样式(附代码示例)

232 阅读10分钟

我们将创建自定义的表单输入和文本区域样式,这些样式在各种顶级浏览器中具有近乎相同的外观。我们将特别为textdatefile 的输入类型设置样式,并为readonlydisabled 的状态设置样式。

继续阅读,学习如何:

  • 重置输入样式
  • 使用hsl ,对输入状态进行主题设计
  • 确保所有状态符合对比度要求
  • 为Windows高对比度模式保留一个可感知的:focus 状态

本地输入样式的常见问题

与我们看到的单选、复选和选择相比,文本输入样式之间有更多的相同点,但还是有不一致的地方。

下面是我们今天要解决的无样式输入的截图,从左到右分别是Chrome、Safari和Firefox。

native input fields including text, date, file, and readonly and disabled states in the aforementioned browsers

我们将寻求统一各浏览器和常见字段类型的初始外观。

date 字段是独特的,因为Chrome和Firefox提供了格式化和一个弹出的日历可供选择,而Safari没有提供类似的功能。我们也不能在CSS中创建这个,所以我们在这里的目标是尽可能地创建一个类似的初始外观。请看日期/时间输入的caniuse

基础HTML

我们涵盖了很多字段类型,所以请查看CodePen的完整列表。但这里是一个文本输入和一个文本区域的基本HTML。

<label for="text-input">Text Input</label>
<input class="input" id="text-input" type="text" />

<label for="textarea">Textarea</label>
<textarea class="input" id="textarea"></textarea>

为了简化我们的样式并准备与级联工作,我们只添加了一个CSS类--input ,它直接放在文本输入和文本区域上。

标签不是我们样式练习的一部分,但它是作为一般要求包括在内的,值得注意的是,for 属性的值是输入端上的id

为主题创建CSS变量

在本教程中,我们将通过使用hsl 值来尝试一种有点不同的主题化技术。

我们将为边框设置一个灰色,然后将一个要在我们的:focus 状态下使用的蓝色分解成它的hsl值,包括:h 的 "色调",s 的 "饱和度",以及l 的 "亮度":

:root {
  --input-border: #8b8a8b;
  --input-focus-h: 245;
  --input-focus-s: 100%;
  --input-focus-l: 42%;
}

我们的每个表单字段的教程都融入了一点不同的主题化方法,这些方法都可以被提取出来,并不仅仅用于表单!

可访问的对比度#

正如所有的用户界面元素一样,输入框需要与周围环境有至少3:1的对比。

而且,:focus ,如果涉及到改变边框的颜色根据WCAG 2.2草案,厚度大于或等于2px ,则需要与非聚焦状态有3:1的对比。

WCAG 2.2的草案:focus 的要求做了一些轻微的调整,我鼓励你去审查这些要求。

重置样式

正如我所有的教程中所包含的现代最佳实践一样,我们首先添加以下重置:

*,
*::before,
*::after {
  box-sizing: border-box;
}

从各浏览器的字段初始状态中可以看出,一些突出的差异是在边框类型、背景颜色和字体属性方面。

有趣的是,font-sizefont-family 并不像排版元素那样从文档中继承,所以我们需要明确地设置它们作为我们重置的一部分。

同样值得注意的是,一个输入的font-size 应该至少计算为16px,以避免在移动Safari浏览器中的交互时被触发缩放。我们通常可以假设1rem 等于16px ,但我们会明确地将其设置为回退,然后使用更新的CSS函数 max来设置16px 作为最小值,以防它比1em 小(这个想法要感谢Dan Burzo)。

.input {
  font-size: 16px;
  font-size: max(16px, 1em);
  font-family: inherit;
  padding: 0.25em 0.5em;
  background-color: #fff;
  border: 2px solid var(--input-border);
  border-radius: 4px;
}

我们将我们的border ,以使用主题变量,还创建了一个略微圆滑的角落。

经过这次更新,我们已经看起来很不错了:

updated input styles in Chrome, Safari, and Firefox which all show the inputs with unified grey borders and white backgrounds

在那张截图中可能很难注意到,但另一个区别是每个字段的高度。这里有一个文本输入和文件输入的比较,可以更好地看到这种差异。

text input field across browsers compared to file input

让我们用下面的方法来解决这个问题,只要不放在textarea ,我们就把它应用到我们的.input 类上:

.input:not(textarea) {
  line-height: 1;
  height: 2.25rem;
}

我们把line-height: 1 ,因为当它不是textarea ,输入就不可能是多行的。由于考虑到特别是文件输入类型,我们还在rem 中设置了我们的高度。如果你知道你不会使用文件输入类型,你可以在这里使用em 来代替,以便灵活地创建各种尺寸的输入。

但是,关键的是,我们已经失去了可编辑和disabled 输入类型之间的区别。我们还想在定义readonly 时更多地暗示它也是不可编辑的,但仍然是互动的。而且,我们还有一些工作要做,以使文件输入类型更加平滑。而且,我们想创建我们的主题:focus 状态。

文件输入 CSS

让我们再看看只是我们在Chrome、Safari和Firefox上的文件输入。

current state of the file input styling across browsers

我们不能对浏览器创建的按钮进行样式设计,也不能改变提示文字,但到目前为止,我们提供的复位确实做了一点工作,使我们的自定义字体得以使用。

我们再做一个调整,把字体缩小一点,因为当与其他字段类型一起查看时,继承的按钮看起来相当大,font-size ,这是我们剩下的唯一解决方法。通过这样做,我们需要调整顶部的padding,因为我们设置的padding是基于em

input[type="file"] {
  font-size: 0.9em;
  padding-top: 0.35rem;
}

如果你希望有一个更高级的解决方案,有很多人已经介绍了这些。我在这里的目的是为你提供一个基线,你可以在此基础上建立。

readonly CSS样式

虽然不经常使用,但readonly 属性可以防止用户的额外输入,尽管可以选择值,而且它仍然可以被辅助技术发现。

让我们添加一些样式,以使更多的人知道这个字段基本上是一个先前输入值的占位符。

要做到这一点,我们将针对任何.input ,也有[readonly] 的属性。属性选择器是一种非常方便的方法,应用广泛,绝对值得在你的CSS工具箱中添加(或更新你的认识)。

.input[readonly] {
  border-style: dotted;
  cursor: not-allowed;
  color: #777;
}

除了换成dotted 边框外,我们还为它指定了not-allowed 光标,并强制使用了中灰色的文本颜色。

从下面的GIF中可以看出,除了高亮/复制数值外,用户不能与该字段互动。

the user mouses over the readonly field and is show the not-allowed cursor, and then double-clicks to highlight the value

禁用的输入和文本区域样式

readonly ,我们将使用一个属性选择器来更新禁用字段的样式。我们把它附在.input 类上,所以它也适用于文本区域和其他输入类型。

我们将利用我们的CSS变量来更新边框的颜色为柔和的灰色,字段背景为非常浅的灰色。我们还将再次应用not-allowed 光标,作为一个额外的提示,表明该字段不是交互式的。

.input[disabled] {
  --input-border: #ccc;

  background-color: #eee;
  cursor: not-allowed;
}

下面是文本输入和文本区域的结果:

Alt Text

文本区样式

我们的textarea ,但有一个属性我想提一下,因为它是文本区固有行为的独特之处。

该属性是 resize,它允许你指定textarea 可以调整的方向,或者它是否可以。

虽然你肯定应该允许textarea ,在一般情况下保留调整大小的功能,但你可以限制它只在垂直方向上调整大小,以防止用户拖动它非常宽的布局破坏,比如说。

我们将通过对我们的.input 类进行范围定位来应用这个属性,当它被应用在textarea

textarea.input {
  resize: vertical;
}

在最后的CodePen演示中试试吧!

:focus 状态样式

好了,我们已经完成了输入和文本区的初始样式,但我们需要处理一个非常重要的状态::focus

我们将采用一个组合效果,将边框的颜色改为符合3:1对比度的值,以对抗非聚焦状态,同时也添加一个box-shadow ,以获得额外的突出效果。

这就是为什么我们在hsl中定义了焦点状态的主题色:这意味着我们可以通过更新亮度值来创造一个边框颜色的变体。

首先,我们通过从各个CSS变量值中构建完整的hsl值来定义边框颜色。

.input:focus {
  border-color: hsl(var(--input-focus-h), var(--input-focus-s), var(--input-focus-l));
}

然后,我们加入box-shadow ,它将只使用模糊来创造本质上的双边框效果。calc() 可以接受在hsla 内使用,所以我们用它将原始值减淡40%,同时也允许有一点alpha透明度。

.input:focus {
  /* ...existing styles */
  box-shadow: 0 0 0 3px hsla(var(--input-focus-h), var(--input-focus-s), calc(var(--input-focus-l) +
          40%), 0.8);
}

请注意,我们现在为我们的对比增加了一个新的背景,即:focus 边框与:focus box-shadow ,所以如果使用这种方法,请确保你选择的颜色的计算差异至少为3:1。

可以选择跳回到.input 规则,并添加一个transition ,以使box-shadow

.input {
  /* ...existing styles */
  transition: 180ms box-shadow ease-in-out;
}

最后,我们不想忘记Windows高对比度模式,它不会看到box-shadow ,也无法检测到边界颜色的变化。因此,我们为这些用户加入一个透明的轮廓:

.input:focus {
  outline: 3px solid transparent;
}

我们在涉及按钮样式的那一集里也使用了这种技术。

这里有一个聚焦于文本输入的GIF演示。

keyboard focusing into and out of the text input

这里是readonly 字段的外观,因为它有一个不同的border-style

the readonly field when focused

在CodePen的HTML中,有一个使用内联样式定义更新视觉的例子,如错误状态。同样,请记住,我们是提供的--input-focus-l减弱了40%,而且聚焦的边框颜色必须与非聚焦的颜色形成至少3:1的对比,所以当你改变CSS变量值时要考虑这一点。

输入模式和自动完成

除了使用正确的输入类型(例如:电子邮件)之外,还有两个额外的属性可以帮助改善用户体验,尤其是在移动端。

第一个是定义inputmode ,它提供了一个改变的键盘或小键盘,更好地匹配预期数据。在MDN上阅读关于可用的inputmode 值 >

其次是autocomplete ,它比onoff 有更多的选择。例如,我一直很欣赏在iPhone上,当谷歌通过文本向我发送确认码时,键盘 "就知道 "这个值是什么。结果发现,这要归功于autocomplete="one-time-code"!

查看autocomplete 的完整列表,它允许你提示预期的值,并真正提高你的表单的用户体验,让用户使用自动填写的值。

演示

首先,这是我们的解决方案在Chrome、Safari和Firefox上的最终外观(从左至右)。当并排观看时,文件输入仍然有点突出,但在单个浏览器上的表单流程中,这绝对是可以接受的。

final input and textarea styles across the aforementioned browsers