网页表单样式

在之前的几篇文章中,我们展示了如何在 HTML 中创建网页表单。现在,我们将展示如何在 CSS 中为它们设置样式。

先决条件 HTMLCSS 的基本理解。
目标 了解表单样式背后的问题,并学习一些对您有用的基本样式技术。

表单小部件样式方面的挑战

历史

1995 年,HTML 2 规范 引入了表单控件(也称为“表单小部件”或“表单元素”)。但 CSS 直到 1996 年末才发布,而且直到几年后才被大多数浏览器支持;因此,在此期间,浏览器依赖于底层操作系统来渲染表单小部件。

即使有了 CSS,浏览器供应商最初也不愿使表单元素可样式化,因为用户已经习惯了各自浏览器的外观。但情况已经发生了变化,现在表单小部件大多是可样式化的,但也有一些例外。

小部件类型

易于样式化

  1. <form>
  2. <fieldset><legend>
  3. 单行文本 <input>(例如类型文本、url、电子邮件),除了 <input type="search">
  4. 多行 <textarea>
  5. 按钮(<input><button> 两种)
  6. <label>
  7. <output>

难以样式化

文章 高级表单样式 展示了如何对这些进行样式化。

具有内部组件的元素无法仅用 CSS 进行样式化

例如,日期选择器日历和 <select> 上的按钮(单击时显示选项列表)无法仅使用 CSS 进行样式化。

文章 高级表单样式如何构建自定义表单控件 描述了如何对这些进行样式化。

注意: 一些专有的 CSS 伪元素,例如 ::-moz-range-track,能够对这些内部组件进行样式化,但这些在浏览器之间不一致,因此不太可靠。我们稍后会提到这些。

简单表单小部件的样式

上一节中的“易于样式化”小部件可以使用文章 您的第一个表单CSS 构建块 中的技术进行样式化。还有一些特殊的选择器——UI 伪类——可以根据 UI 的当前状态启用样式化。

我们将在本文末尾逐步介绍一个示例——但首先,这里有一些值得了解的关于表单样式的特殊方面。

字体和文本

CSS 字体和文本功能可以轻松地与任何小部件一起使用(是的,您可以在表单小部件中使用 @font-face)。但是,浏览器的行为通常不一致。默认情况下,一些小部件不会从其父元素继承 font-familyfont-size。许多浏览器使用系统的默认外观。为了使表单的外观与您内容的其余部分保持一致,您可以将以下规则添加到您的样式表中

css
button,
input,
select,
textarea {
  font-family: inherit;
  font-size: 100%;
}

inherit 属性值会导致属性值与父元素属性的计算值匹配;继承父元素的值。

下面的屏幕截图显示了差异。左侧是 <input type="text"><input type="date"><select><textarea><input type="submit"><button> 在 macOS 上的 Chrome 中的默认渲染,使用平台的默认字体样式。右侧是相同的元素,应用了我们上面的样式规则。

Form controls with default and inherited font families. By default, some types are serif and others are sans serif. Inheriting should change the fonts of all to the parent's font family - in this case a paragraph. Oddly, input of type submit does not inherit from the parent paragraph.

默认值在许多方面有所不同。继承应该将它们的字体更改为父元素的字体系列——在本例中,是父容器的默认衬线字体。它们都这样做了,但有一个奇怪的例外——<input type="submit"> 在 Chrome 中没有从父段落继承。相反,它使用 font-family: system-ui。这是使用 <button> 元素而不是等效输入类型的另一个原因!

关于表单是否应该使用系统默认样式或自定义样式(旨在与您的内容匹配)存在很多争论。这个决定由您作为网站或 Web 应用程序的设计者来决定。

盒子大小

所有文本字段都完全支持与 CSS 盒模型相关的每个属性,例如 widthheightpaddingmarginborder。但是,如前所述,浏览器在显示这些小部件时依赖于系统默认样式。您需要决定如何将它们与您的内容融合在一起。如果您想保留小部件的原生外观和感觉,那么如果您想赋予它们一致的大小,您将面临一些困难。

这是因为每个小部件都有自己的边框、填充和边距规则。 要使几个不同的窗口小部件具有相同的大小,可以使用 box-sizing 属性以及其他属性的一些一致值

css
input,
textarea,
select,
button {
  width: 150px;
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

在下面的屏幕截图中,左列显示了 <input type="radio"><input type="checkbox"><input type="range"><input type="text"><input type="date"><select><textarea><input type="submit"><button> 的默认渲染。另一方面,右列显示了应用了我们上面的规则的相同元素。注意,这使我们能够确保所有元素都占据相同的空间,尽管平台为每种类型的窗口小部件设置了默认规则。

box model properties effect most input types.

屏幕截图可能无法显示的是,单选按钮和复选框控件仍然看起来一样,但它们在 width 属性提供的 150 像素的水平空间中居中。其他浏览器可能不会将小部件居中,但它们确实会遵守分配的空间。

图例放置

<legend> 元素可以进行样式化,但控制其放置可能有点棘手。默认情况下,它始终位于其 <fieldset> 父元素的顶部边框上方,靠近左上角。要将其放置在其他位置,例如在 fieldset 中的某个位置或靠近左下角,您需要依赖于定位。

以以下示例为例

要以这种方式定位图例,我们使用了以下 CSS(出于简洁起见,删除了其他声明)

css
fieldset {
  position: relative;
}

legend {
  position: absolute;
  bottom: 0;
  right: 0;
}

<fieldset> 也需要定位,以便 <legend> 相对于它定位(否则 <legend> 将相对于 <body> 定位)。

<legend> 元素对于可访问性非常重要——它将被辅助技术作为 fieldset 内每个表单元素的标签的一部分进行朗读——但使用像上面这样的技术是可以的。图例内容仍然会以相同的方式朗读;只是视觉位置发生了变化。

注意: 您也可以使用 transform 属性来帮助您定位 <legend>。但是,当您使用例如 transform: translateY(); 定位它时,它会移动,但在 <fieldset> 边框中留下了难看的间隙,这很难消除。

一个具体的样式示例

让我们看看如何对 HTML 表单进行样式化的具体示例。我们将构建一个外观奇特的“明信片”联系表单;此处查看完成版本.

如果您想按照此示例操作,请制作 postcard-start.html 文件 的本地副本,并按照以下说明操作。

HTML

HTML 只是比我们在 本指南的第一篇文章 中使用的示例稍微复杂一些;它只有一些额外的 ID 和标题。

html
<form>
  <h1>to: Mozilla</h1>

  <div id="from">
    <label for="name">from:</label>
    <input type="text" id="name" name="user_name" />
  </div>

  <div id="reply">
    <label for="mail">reply:</label>
    <input type="email" id="mail" name="user_email" />
  </div>

  <div id="message">
    <label for="msg">Your message:</label>
    <textarea id="msg" name="user_message"></textarea>
  </div>

  <div class="button">
    <button type="submit">Send your message</button>
  </div>
</form>

将以上代码添加到 HTML 的 body 中。

组织您的资产

这就是乐趣开始的地方!在开始编码之前,我们需要三个额外的资产

  1. 明信片背景——下载此图像并将其保存到与您的工作 HTML 文件相同的目录中。
  2. 打字机字体:dafont.com 上的“Mom's Typewriter”字体——将 TTF 文件下载到与上面相同的目录中。
  3. 手绘字体:dafont.com 上的“Journal”字体——将 TTF 文件下载到与上面相同的目录中。

您的字体需要在开始之前进行更多处理

  1. 转到 fontsquirrel.com 的 Webfont Generator
  2. 使用表单上传您的两个字体文件并生成一个 Web 字体工具包。将工具包下载到您的计算机。
  3. 解压缩提供的 zip 文件。
  4. 在解压缩的内容中,您会找到一些字体文件(在撰写本文时,两个 .woff 文件和两个 .woff2 文件;它们将来可能会有所不同。)将这些文件复制到名为 fonts 的目录中,与之前相同的目录中。我们使用每个字体的两个不同文件来最大限度地提高浏览器兼容性;有关更多信息,请参阅我们的 Web 字体 文章。

CSS

现在我们可以深入研究示例的 CSS。将下面显示的所有代码块依次添加到 <style> 元素中。

整体布局

首先,我们通过定义 @font-face 规则以及对 <body><form> 元素设置的所有基本样式来进行准备。如果 fontsquirrel 的输出与我们上面描述的不同,您可以在下载的 Web 字体工具包中的 stylesheet.css 文件中找到正确的 @font-face 块(您需要用它们替换下面的 @font-face 块,并更新到字体文件的路径)

css
@font-face {
  font-family: "handwriting";
  src:
    url("fonts/journal-webfont.woff2") format("woff2"),
    url("fonts/journal-webfont.woff") format("woff");
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: "typewriter";
  src:
    url("fonts/momot___-webfont.woff2") format("woff2"),
    url("fonts/momot___-webfont.woff") format("woff");
  font-weight: normal;
  font-style: normal;
}

body {
  font: 1.3rem sans-serif;
  padding: 0.5em;
  margin: 0;
  background: #222;
}

form {
  position: relative;
  width: 740px;
  height: 498px;
  margin: 0 auto;
  padding: 1em;
  box-sizing: border-box;
  background: #fff url(background.jpg);

  /* we create our grid */
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: 10em 1em 1em 1em;
}

注意,我们使用了一些 CSS 网格Flexbox 来布局表单。使用它,我们可以轻松地定位我们的元素,包括标题和所有表单元素

css
h1 {
  font:
    1em "typewriter",
    monospace;
  align-self: end;
}

#message {
  grid-row: 1 / 5;
}

#from,
#reply {
  display: flex;
}

标签和控件

现在我们可以开始处理表单元素本身。首先,让我们确保 <label> 使用正确的字体。

css
label {
  font:
    0.8em "typewriter",
    sans-serif;
}

文本字段需要一些通用的规则。换句话说,我们删除它们的 bordersbackgrounds,并重新定义它们的 paddingmargin

css
input,
textarea {
  font:
    1.4em/1.5em "handwriting",
    cursive,
    sans-serif;
  border: none;
  padding: 0 10px;
  margin: 0;
  width: 80%;
  background: none;
}

当这些字段中的一个获得焦点时,我们使用浅灰色透明背景突出显示它们(对于可用性和键盘可访问性,始终拥有焦点样式非常重要)

css
input:focus,
textarea:focus {
  background: rgb(0 0 0 / 10%);
  border-radius: 5px;
}

现在我们的文本字段已经完成,我们需要调整单行和多行文本字段的显示以匹配,因为它们使用默认值通常看起来不一样。

调整文本区域

<textarea> 元素默认渲染为内联块元素。这里有两个重要的属性:resizeoverflow。虽然我们的设计是固定大小的,我们可以使用 resize 属性来阻止用户调整多行文本字段的大小,但最好不要阻止用户调整 textarea 的大小,如果他们愿意的话。使用 overflow 属性可以使字段在不同浏览器中的渲染更加一致。一些浏览器默认值为 auto,而另一些则默认值为 scroll。在我们的例子中,最好确保每个人都使用 auto

css
textarea {
  display: block;

  padding: 10px;
  margin: 10px 0 0 -10px;
  width: 100%;
  height: 90%;

  border-right: 1px solid;

  /* resize  : none; */
  overflow: auto;
}

设置提交按钮样式

<button> 元素用 CSS 设置样式非常方便,您可以随意操作,甚至可以使用 伪元素

css
button {
  padding: 5px;
  font: bold 0.6em sans-serif;
  border: 2px solid #333;
  border-radius: 5px;
  background: none;
  cursor: pointer;
  transform: rotate(-1.5deg);
}

button:after {
  content: " >>>";
}

button:hover,
button:focus {
  background: #000;
  color: #fff;
}

最终结果

瞧!您的表单现在应该看起来像这样

The final look and layout of the form after applying all styling and tweaking to it as described above

注意:如果您的示例没有按照您的预期工作,并且您想将其与我们的版本进行比较,您可以在 GitHub 上找到它 - 查看它 运行中(也可以查看 源代码)。

测试您的技能

您已阅读完本文,但您能记住最重要的信息吗?在您继续之前,您可以进行一些进一步的测试,以验证您是否保留了这些信息 - 请查看 测试您的技能:样式基础

总结

如您所见,只要我们想使用文本字段和按钮构建表单,就可以轻松地使用 CSS 对其进行样式设置。在 下一篇文章 中,我们将看到如何处理属于“糟糕”和“丑陋”类别的表单小部件。

高级主题