Styling web forms

 

在前面的几篇文章中,我们介绍了创建和构建Web表单所需的所有HTML. 在本文中,我们将继续研究如何使用CSS设置表单控件的样式. 从历史上讲,这一直很困难-表单控件在CSS中自定义的难易程度相差很大-但随着旧浏览器的淘汰和现代浏览器的使用,我们变得越来越容易.

Prerequisites: 基本的计算机知识,以及对HTMLCSS的基本了解.
Objective: 了解样式表背后的问题,并学习一些对您有用的基本样式技术.

Why is styling form widgets challenging?

表单控件是在1995年的HTML 2规范中添加到HTML ; CSS直到1996年底才发布,并且在随后的几年中浏览器都没有很好地支持CSS. 浏览器依靠底层操作系统来管理和呈现表单控件.

即使使用CSS来设置HTML样式,历史上浏览器供应商仍然不愿意使表单控件可样式化,因为用户非常习惯于各自平台的外观. 但这已经改变了. 网站所有者比以往任何时候都更希望表单样式适合其总体网站设计,并且网络平台已更改,以使其更可行.

对于某些表单小部件,仍然很难重建控件以使其可样式化,但是我们现在可以使用CSS设置许多表单功能的样式,尽管我们确实需要格外小心以确保不破坏可用性.

Not all widgets are created equal when CSS is involved

当前,将CSS与表单一起使用时仍然存在一些困难. 这些问题可以分为三类:

The good

跨平台,某些元素的样式几乎没有问题. 其中包括以下元素:

  1. <form>
  2. <fieldset> and <legend>
  3. <input type="search">之外的单行文本<input> (例如,键入text,url,email ...).
  4. Multi-line <textarea>s
  5. 按钮( <input><button>两者)
  6. <label>
  7. <output>

The bad

一些元素的样式更难,需要更复杂的CSS或一些更具体的技巧:

我们将在文章高级表单样式中描述如何处理这些更具体的功能.

The ugly

某些元素无法使用CSS进行彻底样式化. 这些包括:

再次,我们将描述在Advanced form styling中如何对这些元素进行样式化 .

所有这些控件的真正问题在于它们具有非常复杂的结构,并且除了某些基本样式(例如更改控件的宽度或边距)之外,您通常无法对控件的内部组件进行样式设置(例如作为日期选择器日历,或<select>上的按钮(导致显示选项列表)组成这些小部件.

如果要彻底自定义这些小部件,则实际上必须使用HTML,CSS和JavaScript创建自己的小部件. 这超出了核心表单文章的范围,但是我们确实在高级文章" 如何构建自定义表单控件"中进行了介绍 .

注意 :有一些专有的CSS伪元素可用,它们允许您设置这些表单控件的内部组件的样式,例如::-moz-range-track ,但是它们在浏览器之间不一致,因此无法依赖. 我们也会在以后提到这些.

The good

要为易于使用CSS设置样式的表单控件设置样式,您应该面对很多困难,因为它们的行为几乎与任何其他HTML元素一样. 我们已经在您的第一个表单中查看了一些简单的表单样式,并且CSS构建块模块也包含了一些有用的表单样式要素 .

除了上面介绍的基本CSS工具外,我们还提供了多个选择器(UI伪类),这些选择器可基于UI的当前状态进行样式设置. 我们将在下一篇文章UI伪类中详细介绍这些内容.

我们将在本文结尾处的示例中向您提供有关基本表单控件样式和放置的更多想法. 但是,在进行此操作之前,我们想先谈谈一些值得了解的表单样式的特定方面.

Fonts and text

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

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应用程序的设计者做出的.

Box sizing

所有文本字段都完全支持与CSS框模型相关的每个属性,例如widthheightpaddingmarginborder . 但是,与以前一样,浏览器在显示这些小部件时依赖于系统默认样式. 由您决定如何将它们融合到您的内容中. 如果要保留小部件的本机外观,则要给它们提供一致的大小会遇到一些困难.

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

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属性提供的150px水平空间的中心. 其他浏览器可能不会使小部件居中,但它们确实遵守分配的空间.

Legend placement

<legend>元素可以样式设置,但是控制它的放置可能有些棘手. 默认情况下,它始终位于其<fieldset>父对象的顶部边框上方,位于左上角附近. 要将其放置在其他位置,例如,在字段集中的某个位置或左下角附近,您需要依靠定位.

请看以下示例:

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

fieldset {
  position: relative;
}

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

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

<legend>元素对于可访问性非常重要-辅助技术将其称为字段集中每个表单元素的标签的一部分-但可以使用上述一种技术. 图例内容仍将以相同的方式说出; 只是视觉位置发生了变化.

注意 :您可能会认为使用transform属性还可以帮助您定位<legend> . 但是,在测试过程中,我们发现当您使用例如transform: translateY();对其进行定位时transform: translateY(); ,它会移动,但在<fieldset>边框中留下一个难看的空白,无法再次填写. 坚持定位.

A specific styling example

让我们看一下如何设置HTML表单样式的具体示例. 我们将建立一个看起来精美的"明信片"联系表; 完整版本请看这里 .

如果您想按照本示例进行操作,请在本地复制我们的cardbox-start.html文件 ,然后按照以下说明进行操作.

The HTML

The HTML is only slightly more involved than the example we used in the first article of this guide; it just has a few extra IDs and a heading.

<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>

Add the above code into the body of your HTML.

Organizing your assets

这就是乐趣的开始! 在开始编码之前,我们需要三个附加资产:

  1. 明信片背景 -下载此图像并将其保存在与工作HTML文件相同的目录中.
  2. 打字机字体: fontsquirrel.com的" Secret Typewriter"字体 -将TTF文件下载到与上述相同的目录中.
  3. 一种手绘字体:fontsquirrel.com中的" Journal"字体 -将TTF文件下载到与上述相同的目录中.

开始之前,您的字体需要更多处理:

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

The CSS

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

Overall layout

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

@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/veteran_typewriter-webfont.woff2') format('woff2'),
         url('fonts/veteran_typewriter-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 GridFlexbox来布置表单. 使用此方法,我们可以轻松地定位元素,包括标题和所有表单元素:

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

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

#from, #reply {
   display: flex;
}

Labels and controls

现在我们可以开始处理表单元素本身了. 首先,让我们确保为<label>提供正确的字体:

label {
  font : .8em "typewriter", sans-serif;
}

文本字段需要一些通用规则. 简而言之,我们删除它们的bordersbackgrounds ,并重新定义其paddingmargin

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

当这些字段之一获得关注时,我们将使用浅灰色,透明的背景突出显示它们(具有焦点样式对于可用性和键盘可访问性始终很重要):

input:focus, textarea:focus {
  background   : rgba(0,0,0,.1);
  border-radius: 5px;
}

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

Tweaking the textareas

<textarea>元素默认呈现为行内块元素. 这里的两个重要事项是resizeoverflow属性. 尽管我们的设计是固定大小的设计,并且我们可以使用resize属性来防止用户调整多行文本字段的大小,但最好不要阻止用户选择调整文本区域的大小. overflow属性用于使字段在浏览器之间更一致地呈现. 有些浏览器的默认值为auto ,而有些浏览器的默认值为scroll . 在我们的情况下,最好确保每个人都将使用auto

textarea {
  display : block;

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

  border-right: 1px solid;

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

Styling the submit button

<button>元素非常便于使用CSS设置样式; 您甚至可以使用伪元素来做任何您想做的事情:

button {
  padding      : 5px;
  font         : bold .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 {
  outline     : none;
  background  : #000;
  color       : #FFF;
}

The final result

瞧! 您的表单现在应如下所示:

注意 :如果您的示例无法正常运行,并且想根据我们的版本进行检查,则可以在GitHub上找到它- 实时运行 (另请参见源代码 ).

Summary

As you can see, as long as we want to build forms with just text fields and buttons, it's easy to style them using CSS. In the next article, we will see how to handle form widgets which fall into the "bad" and "ugly" categories.

In this module

Advanced Topics