Skip to content

精通 CSS - 高级 Web 标准解决方案 7. 对表单和数据表格应用样式

🏷️ 《精通 CSS - 高级 Web 标准解决方案》

本章主要讲了两个标签 <table>表格)和 <fieldset>表单)。

不过这两个元素在实际使用中已经越来越少见了。

7.1 对数据表格应用样式

7.1.1 表格特有的元素

  • summary 类似于图像的 alt 属性
  • caption 表格的标题
  • theadtbodytfoot 表格逻辑部分
  • colcolgroup 对表格列定义或分组(支持的浏览器并不多)

7.1.2 数据表格标记

html
<table class="cal" summary="A calendar style data picker">
    <caption>
        <a href="#" rel="prev">&lt;</a> May 2019 <a href="#" rel="next">&gt;</a>
    </caption>
    <colgroup>
        <col id="sun" />
        <col id="mon" />
        <col id="tue" />
        <col id="wed" />
        <col id="thur" />
        <col id="fri" />
        <col id="sat" />
    </colgroup>
    <thead>
        <tr>
            <th scope="col">Sun</th>
            <th scope="col">Mon</th>
            <th scope="col">Tue</th>
            <th scope="col">Wed</th>
            <th scope="col">Tur</th>
            <th scope="col">Fri</th>
            <th scope="col">Sat</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td class="null">28</td>
            <td class="null">29</td>
            <td class="null">30</td>
            <td><a href="#">1</a></td>
            <td><a href="#">2</a></td>
            <td><a href="#">3</a></td>
            <td><a href="#">4</a></td>
        </tr>
        <!-- ... -->
        <tr>
            <td><a href="#">26</a></td>
            <td><a href="#">27</a></td>
            <td><a class="selected">28</a></td>
            <td><a href="#">29</a></td>
            <td><a href="#">30</a></td>
            <td><a href="#">31</a></td>
            <td class="null">1</td>
        </tr>
    </tbody>
</table>

7.1.3 对表格应用样式

CSS 规范有两个表格边盒模型:单独的和叠加的。

单独模型中,在各个单元格周围有边框;
叠加模型中,单元格共享边框。

大多数浏览器默认采用单独模型。

使用 border-collapse 属性控制边盒模型。该属性 可能的值:

  • separate:默认值,叠加模型
  • collapse:单独模型
  • inherit:从父元素继承
css
table.cal {
    border-collapse: separate;
    border-spacing: 0;
    text-align: center;
    color: #333;
}

.cal th, .cal td {
    margin: 0;
    padding: 0;
}

7.1.4 添加视觉样式

css
/* 设置表格标题样式 */
.cal caption {
    font-size: 1.25em;
    padding-top: 0.692em;
    padding-bottom: 0.692em;
    background-color: #d4dde6;
}
.cal caption [rel="prev"] {
    float: left;
    margin-left: 0.2em;
}
.cal caption [rel="next"] {
    float: right;
    margin-right: 0.2em;
}
.cal caption a:link,
.cal caption a:visited {
    text-decoration: none;
    color: #333;
    padding: 0.2em;
}
.cal caption a:hover,
.cal caption a:active,
.cal caption a:focus {
    background-color: #6d8ab7;
}
/* 设置行标题样式 */
.cal thead th {
    background-color: #d4dde6;
    border-bottom: 1px solid #a9bacb;
    font-size: 0.875em;
}
/* 设置表格体样式 */
.cal tbody {
    color: #a4a4a4;
    text-shadow: 1px 1px 1px white;
    background-color: #d0d9e2;
}
/* 设置单元格样式 */
.cal tbody td {
    border-top: 1px solid #e0e0e1;
    border-right: 1px solid #9f9fa1;
    border-bottom: 1px solid #acacad;
    border-left: 1px solid #dfdfe0;
}
/* 设置链接样式 */
.cal tbody a {
    display: block;
    text-decoration: none;
    color: #333;
    background-color: #c0c8d2;
    font-weight: bold;
    padding: 0.385em 0.692em 0.308em 0.692em;
}
/* 设置鼠标悬停状态 */
.cal tbody a:hover,
.cal tbody a:focus,
.cal tbody a:active,
.cal tbody .selected a:link,
.cal tbody .selected a:visited,
.cal tbody .selected a:hover,
.cal tbody .selected a:focus,
.cal tbody .selected a:active {
    background-color: #6d8ab7;
    color: white;
    text-shadow: 1px 1px 2px #22456b;
}
.cal tbody td:hover,
.cal tbody td.selected {
    border-top: 1px solid #2a3647;
    border-right: 1px solid #465977;
    border-bottom: 1px solid #576e92;
    border-left: 1px solid #466080;
}

7.2 简单的表单布局

7.2.1 有用的表单元素

fieldset 用来对相关的信息块进行分组。
使用 legend 元素添加标题。

label 标签元素常用来关联表单控件。

隐式关联

html
<label>email <input name="email" type="text" /></label>

显示关联

html
<label for="email">email</label>
<input name="email" id="email" type="text" />

在表单输入控件和标签之间创建关联需要 id 属性;而将表单数据发送回服务器需要 name 属性。

7.2.2 基本布局

没有样式的表单:

html
<fieldset>
    <legend>Your Contact Details</legend>
    <div>
        <label for="author">Name:<em class="required">(Required)</em></label>
        <input name="author" id="author" type="text" />
    </div>
    <div>
        <label for="email">Email Address:</label>
        <input name="email" id="email" type="text" />
    </div>
    <div>
        <label for="url">Web Address:</label>
        <input name="url" id="url" type="text" />
    </div>
</fieldset>

设置表单样式:

css
fieldset {
    margin: 1em 0;
    padding: 1em;
    border: 1px solid #ccc;
    background: #f8f8f8;
}
legend {
    font-weight: bold;
}
label {
    /* 将标签设置为 block 会产生边框,并迫使输入框转到下一行 */
    display: block;
    cursor: pointer;
}
input {
    width: 20em;
}

7.2.3 其它元素

文本区域 textarea

html
<fieldset>
    <legend>Comments</legend>
    <div>
        <label for="text">Message:</label>
        <textarea name="text" id="text"></textarea>
    </div>
</fieldset>
css
textarea {
    width: 100%;
    height: 10em;
}

单选按钮 & 复选框 通常需要把标签放在元素右边。

html
<fieldset id="remember-me">
    <legend>Remember Me</legend>
    <div>
        <label for="remember-yes"><input id="remember-yes" class="radio" name="remember" typee="radio" value="yes" />Yes</label>
    </div>
    <div>
        <label for="remember-no"><input id="remember-no" class="radio" name="remember" typee="radio" value="no" />No</label>
    </div>
</fieldset>
css
input.radio, input.checkbox, input.submit {
    width: auto;
}
#remember-me .radio {
    margin-right: 1em;
}

必填域

许多表单包含必须填写的域。可以在这些必填域旁边放上有样式的文本或星号。

html
<fieldset>
    <legend>Your Contact Details</legend>
    <div>
        <label for="author">Name:<em class="required">(Required)</em></label>
        <input name="author" id="author" type="text" />
    </div>
</fieldset>
css
.required {
    font-size: 0.75em;
    color: #760000;
}

7.3 复杂的表单布局

减少使用的垂直空间,将标签和表单元素水平布置。

css
label {
    float: left;
    width: 10em;
    cursor: pointer;
}
/* 清理 div 容器,避免影响下一组标签 */
form div {
    clear: left;
}

7.3.1 可访问的数据输入元素

有时候我们不希望每个元素都显示标签,但又希望代码中有标签可供屏幕阅读器(为视觉有障碍的人设计的阅读屏幕的工具,该工具会自动忽略隐藏的元素。)访问。

html
<div>
    <label for="dateOfBirth">Date Of Birth:</label>
    <input name="dateOfBirth" id="dateOfBirth" type="text" />
    <label id="monthOfBirthLabel" for="monthOfBirht">Month of Birth:</label>
    <select name="monthOfBirht" id="monthOfBirth">
        <option value="1">January</option>
        <option value="2">February</option>
        <option value="3">March</option>
        <!-- ... -->
    </select>
    <label for="yearOfBirth">Year Of Birth:</label>
    <input name="yearOfBirth" id="yearOfBirth" type="text" />
</div>
css
#monthOfBirthLabel, #yearOfBirthLabel {
    /* 隐藏标签(之所不用 display: none 是因为这样会导致屏幕阅读器访问不到它) */
    text-indent: -1000em;
    /* 不设置为 inline-block 的话 text-indent 貌似不起作用 */
    display: inline-block;
    /* 为了防止标签影响布局,需要将标签的宽度设置为 0 */
    width: 0;
}
/* 设置每个空间的尺寸和外边距 */
input#dateOfBirth {
    width: 3em;
    margin-right: 0.5em;
}
input#monthOfBirth {
    width: 10em;
    margin-right: 0.5em;
}
input#yearOfBirth {
    width: 5em;
}

7.3.2 多列复选框

使用 fieldset 实现标签组的效果。由于 legend 元素定位定位在每个浏览器上可能不一样,所以改用 h2 元素。

html
<fieldset id="favoriteColor">
    <h2>Favorite Color:</h2>
    <div class="col">
        <div>
            <label><input class="checkbox" id="red" type="checkbox" value="red" />red</label>
            <label><input class="checkbox" id="yellow" type="checkbox" value="yellow" />yellow</label>
            <label><input class="checkbox" id="pink" type="checkbox" value="pink" />pink</label>
            <label><input class="checkbox" id="green" type="checkbox" value="green" />green</label>
        </div>
    </div>
    <div class="col">
        <div>
            <label><input class="checkbox" id="orange" type="checkbox" value="orange" />orange</label>
            <label><input class="checkbox" id="purple" type="checkbox" value="purple" />purple</label>
            <label><input class="checkbox" id="blue" type="checkbox" value="blue" />blue</label>
            <label><input class="checkbox" id="other" type="checkbox" value="other" />other</label>
        </div>
    </div>
</fieldset>
css
<!-- 覆盖 fieldset 的样式 -->
fieldset#favoriteColor {
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
}
/* 将标题用作标签,将其设置为向左浮动 */
fieldset#favoriteColor h2 {
    width: 10em;
    float: left;
    font-size: 1em;
    font-weight: normal;
}
/* 将列也设置为向左浮动,实现列的效果 */
fieldset#favoriteColor .col {
    width: 8em;
    float: left;
    clear: none;
}
/* 清除标签的浮动 */
fieldset#favoriteColor label {
    float: none;
    display: block;
}

提交按钮

最常用的是 typesubmitinput 元素。但可以使用 button 元素替代 input 元素。

可以在 button 元素中放入图片,使图片成为按钮。

html
<div>
    <button type="submit">
        <img src="/img/button.png" alt="Like It" />
    </button>
</div>

关闭 button 的默认样式。

css
button {
    border: none;
    background: none;
    cursor: pointer;
}

OS X 等系统为了操作系统样式的统一性,禁止修改 input 按钮的样式,但是,button 元素不受限制。

css
button.book {
    width: 200px;
    height: 50px;
    border: 1px solid #989898;
    /** 设置圆角 **/
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    /** 设置背景 **/
    background: url(/img/button-bg.png) #c5e063 bottom left repeat-x;
    /** 设置阴影 **/
    -moz-box-shadow: 2px 2px 2px #ccc;
    -webkit-box-shadow: 2px 2px 2px #ccc;
    box-shadow: 2px 2px 2px #ccc;
    /** 设置字体 **/
    color: #fff;
    font-size: 26px;
    font-weight: bold;
    text-shadow: 1px 1px 1px #666;
}

7.3.3 表单反馈

表单验证的错误消息等

html
<div>
    <label for="email">Email Address:<em class="feedback">Incorrect email address. Please try again.</em></label>
    <input name="email" id="email" type="text" />
</div>

将段落的 position 设置为 relative,从而建立一个新的定位上下文。然后对返回 em 进行绝对定位。

css
div {
    clear: left;
    position: relative;
}
.feedback {
    position: absolute;
    left: 30em;
    right: 0;
    top: 0.5em;
    /* 警告字体设置为红色、粗体 */
    font-weight: bold;
    color: #760000;
    /* 左边加一个警告图像 */
    padding-left: 18px;
    background: url(/img/error.png) no-repeat left top;
}

附 1. 引用

  1. 《精通 CSS - 高级 Web 标准解决方案(第 2 版)》 - Andy Budd, Simon Collison, Cameron Moll 著;陈剑瓯 译。