在网页中我们经常要让用户输入一些内容,或者说是收集用户的一些数据,比如说搜索功能,就需要用户在一个搜索框中输入搜索的关键词,比如注册登录功能,就要用户在文本框中输入账号和密码。这种都可以视作用户输入的行为。表单元素其实就是专门用于收集用户数据的一系列元素。这些用户信息通常是要传输到后端服务器的,所以表单也可以看做是一种前后端交互的桥梁。

上图这种登录界面,其实就是一系列表单元素组成的,像上面的文本框,选择框,甚至登录按钮,这些其实都是表单元素,包括上图中没有的下拉列表等等,这种用户可以在网页上修改或者输入的元素,都是表单元素。
表单元素
input 元素
首先介绍第一个元素,即 input 元素,这个元素用于获取用户的输入,它可以用于收集很多种用户输入,比如可以用来收集一串文本,一串密码,一个多选,一个单选。至于这个 input 元素具体用来收集什么种类的用户输入,根据其 type 类型来指定。
html
<input type="text">这里这个 input 的 type 属性为 text,表示收集的输入类型为文本类型。

此时就可以在这个文本框内输入内容。
当然,前面说了,根据 type 属性的不同,input 可以用于收集各种各样的数据,这里只会介绍常用的 type 属性,不常用的 type 属性可能还伴随着兼容性问题,而且本身也并不复杂,所以不一一介绍,type 属性的所有取值可以参考 <input>:输入(表单输入)元素 - HTML(超文本标记语言) | MDN
上面那个 input 元素的 type 属性为 text,表示要收集一串文本,此时这个 input 就是一个普通文本输入框。
除了 type 属性以外,input 元素还有一个 value 属性,表示的就是输入的值,比如上面的文本框中我输入了一串字符串是吧,当我输入进去之后,这个 input 元素的 value 属性就会变成我输入的数据,至于如何在页面中实时获取到这个 value 属性值,这其实是 JavaScript 中需要学习的内容,这里我们可以使用 value 属性来设置一个初始值即可。
html
<input type="text" value="default value">给 input 元素添加上 value 属性的时候,当我们进入页面的时候,就可以直接在输入框中看到这个默认值。

其实我们可以认为,每一个 input 都是一个用于获取用户输入的元素,input 根据 type 属性的不同有很多种类型,但不论如何改变,本质上都是获取用户输入,既然是获取用户输入,就一定需要一个东西来保存用户输入的数据,这个保存用户输入的东西其实就是这个 input 上的 value 属性,input 元素上的值和这个元素的 value 属性一一对应,例如当我在文本框上输入数据的时候,这个文本框,也就是这个 input 元素的 value 属性会实时修改,反过来也一样,当我修改这个 input 元素的 value 属性的时候,这个文本框的内容也会修改。
读者可能经常见到一个场景,就是在一个文本框中不输入内容的时候显示一个浅色的提示文字,当鼠标聚焦在文本框中输入文字的时候,浅色的提示文字消失了,例如 b 站的下图效果:

当我输入文字的时候,这个提示文字就会消失,这样一个效果在以前只能用 JavaScript 来实现,但由于这个功能过于普遍,所以现在可以使用 placeholder 属性来实现。
html
<input type="text" placeholder="default value">
可以看到,我们现在这个效果和 b 站那个效果就几乎一样了,都是文本框为空的时候默认显示浅色的提示文字,当输入内容的时候提示文字消失。
以上介绍了 input 的基本概念和 type 属性,以及 type 属性为 text 的时候,即普通文本框状态下的一些细节。
下面继续介绍,有时候我们会看到另一个场景,就是在输入密码的时候,我们会看到下面的效果

输入的文字隐藏起来了,这个东西也是 input 的一种类型,就是 password 类型。
html
<input type="password" placeholder="default value">当我们将 input 的 type 属性改成 password,此时表示 input 接受的输入是一个密码,所以会显示一个密码框,密码框里文字默认就是被隐藏的,或者说的对用户不可见的。

可以看到,对于密码框而言,placeholder 属性依然生效
password 和 text 两种类型的 input 元素,其实本质上是一模一样的,唯一的区别就是 password 输入的内容对用户不可见,这主要是为了防止录屏和偷窥操作,实际上我们可以很轻松地使用 JavaScript 通过该 input 元素的 value 属性拿到密码。
值得注意的是,如果是一个搜索框,或者这个文本框是提供搜索功能,用于搜索关键词的,那么建议不要使用 text 类型的 input 元素,而使用 search 类型的 input 元素,这是专门用于收集用户搜索关键词的 input 元素。
这二者区别主要体现在移动端上,在移动端,如果是 search 类型的 input 元素,那么在键盘右下角可以直接提供一个跳转按钮,而如果是 text 的 input 元素,键盘左下角一般是换行的回车按钮。
除了以上类型以外,我们在注册的时候是不是还要经常输入一个出生日期,input 元素还提供了日期输入的功能,设置 type 属性为 date 的时候,就可以输入一个日期。
html
<input type="date">
从这里读者也应该认识到,input 元素其实就是用来收集用户输入的,它到底长什么样取决于它要收集何种类型的数据,或者说是 type 属性,比如当我要让用户输入一个文本,就用 text,输入一个日期,就用 date。
注意,这其实是调用浏览器提供的样式来完成日期的选择,这个日期选择界面的具体样式我们是无法控制的,如果我们真的希望要更改这些样式,建议自己去写一个日期选择器。同样的话,对于后面的单选、多选也适用,这些东西都不是我们可以修改的,如果要弄好看点,都是需要自己用 HTML+CSS 自己写一个多选、单选出来。
考虑一个情况,如果我需要用户输入一个数字,比如说年龄,我可以用一个 text 来实现,但是这样实现是有问题的,用户会不会输入一个负数?会不会输入一个几百岁的非法年龄?这些其实都是问题对吧,要屏蔽掉这种数据就需要以后的 JS 知识,但是这里我们也可以实现让用户输入指定数字,实现方案就是 range 类型的 input 元素。
html
<input type="range" min="18" max="120" value="18">使用 range 类型的 input 元素之后,此时可以设置 min 和 max 属性,分别表示最小值和最大值,此时 value 属性可以设置默认值,效果如下所示

此时我们看不到数值,因为要像获取到数值其实是 JavaScript 应该做的事。
可能这并不是读者想达到的效果,如果我们想要用户只输入一个数字,其实有更好的解决方案,就是 number 类型的 input 元素。
html
<input type="number" min="0" max="100">
可以看到,此时将这个 input 元素的类型设置为了 number,这个输入框就只能接受数字类型的数据,并且可以通过 min 和 max 来设置最小值和最大值,可以看到,如果输入了一个超出范围的数字,实际上一点击向下或者向上就会回归原样,并且后期使用 JS 也是获取不到这些非法数据的。
对于 number 类型的 input 元素,会自带一个向上向下的按键,默认情况下,点一下向上就是加一,如果我希望它点一下上箭头是加 10,那么就设置 step 元素的数值,这个元素用于设置步长。
我们还可以让用户输入一个颜色,将 input 元素的 type 属性设置为 color 就是一个颜色选择器。
html
<input type="color">
除此之外,我们还经常会让用户去做选择,比如让用户选择爱好,让用户选择性别等等,这些其实无非就涉及到多选和单选。
首先看多选,如果我们要让用户选择一些兴趣爱好,就应该用多选框,input 的 type 属性为 checkbox 的时候,表示这是一个多选框。
html
<input type="checkbox">
我们页面中可能会有很多组的多选框,比如这几个多选框是让用户选择爱好,下一组多选框是让用户反馈问题,我们以后获取多选框数据的时候,肯定要明确目前这个多选框隶属于哪一组,所以我们在使用多选框的时候,对于同一组的多选框,应该设置一个相同的 name 属性。
html
爱好:
<input name="hoby" type="checkbox">音乐
<input name="hoby" type="checkbox">电影
<input name="hoby" type="checkbox">游戏
这就实现了一个简单的多选输入。
除此之外,我们有时候还要让用户多选一吧,比如性别,起码从一个正常人的朴素认知来看,生理上的性别不可能即是男又是女吧,一般都是二选一,对于这种二选一,包括多选一的效果,有两种实现方案,分别是单选框和下拉菜单。
首先是单选框,单选框的 type 属性为 radio
html
性别:
<input type="radio">男
<input type="radio">女
我们这里发现了一个很严重的 bug,这两个居然可以同时选择,这个原因其实和前面提到的 checkbox 一样,我们页面中可能会存在很多组单选框,比如这里让你选择性别,下面就会让你选择省份对吧,我们在获取数据的时候,必须知道这是属于哪一组的单选框,对于同一组的单选框,我们只能选择一个,我们也是使用 name 属性将其进行分组。
html
性别:
<input name="sex" type="radio">男
<input name="sex" type="radio">女
此时将这两个单选框分成了一组,这个时候就只能二选一,当选择女的时候,男就会自动取消选择,就实现了单选效果。
其实每一个 input 元素都需要有一个 name 属性,包括文本框也需要有 name 属性,至于原因,因为表单是把用户数据传到后端的,而这个传输方式其实是键值对,这个 name 就是键,而前面提到的 value 属性其实就是值。一个键对应一个值,并且键必须保证唯一,这样一一对应,才能保证数据无歧义地向后端传输。
有时候我们还要上传一个附件,也就是上传一个文件,可以使用 file 类型的 input 元素,这样就可以让用户选择一个文件,后期可以配合 JS 和服务器进行上传操作。
input 可以通过修改 type 属性称成为一个按钮,但这是一种过时的写法,目前推荐使用 button 元素来制作按钮,这里后面会介绍到。type 属性为 reset 的时候,此时 input 元素为重置按钮。type 属性为 submit 的时候,此时 input 元素为提交按钮。type 属性为 button 的时候,此时 input 元素为一个普通按钮。当 input 为按钮时,其 value 属性就是按钮的文字。
以上介绍了 input 元素的常见类型,具体其实可以参考 MDN 文档:<input>:输入(表单输入)元素 - HTML(超文本标记语言) | MDN。
select 元素
读者如果阅读细心,可能会发现我似乎漏了一个东西,前面介绍到,要实现多选一的效果,可以使用 radio 类型的 input 元素,也就是单选框,我还提到了可以使用下拉菜单来实现多选一。如果我们要实现下拉菜单,则需要使用 select 元素和 option 元素,而不是 input 元素。
html
选择省份:
<select>
<option>四川</option>
<option>河北</option>
<option>北京</option>
<option>天津</option>
<option>上海</option>
</select>
这个元素其实看一眼就知道大概怎么用,select 元素其实就是一个下拉菜单,其的子元素只能是 option 元素,每一个 option 元素都表示一个下拉项。
option 元素里有一个属性为 value,select 元素里有一个属性为 name。实际上我前面说过,表单数据的传输其实都是键值对,这里也不例外,select 里面的 name 就是键,因为页面中可能有多个 select 元素,必须确定目前传输的是哪一个 select 元素的数据,就通过这个 name 属性进行区分,至于取值可以是 option 里面的任意一个,那我总不能把 option 里面的文字作为取值吧,我可以让第一个 option 的 value 为 1,第二个 option 的 value 为 2,这个时候传入到后端后,就可以根据这个 value 值判断用户选择的是哪一个 option。实际上和单选框是很类似的,读者继续往后学,学到前后端交互的部分,就会有更深刻的理解。
以上介绍了很多关于选择的表单元素,分别是单选框,多选框两个类型的 input 元素,以及 select 元素。读者可能会见过很多默认选中的效果,对于 radio 和 checkbox 类型的 input 元素,如果要让它默认选中,则需要添加 checked 属性。而对于 select 元素,要默认选中其中的某一个 option,则只需要在指定 option 内添加上 selected 属性即可。不管是 selected 还是 checked 属性,均为布尔属性。
实际上,前面说到,select 元素的子元素只有 option,这是不太准确的,其实我们还可以通过 optgroup 元素对 option 进行分组。
html
选择游戏:
<select name="game">
<optgroup label="单机">
<option>植物大战僵尸</option>
<option>魔兽争霸3</option>
</optgroup>
<optgroup label="热门游戏">
<option>CF</option>
<option>英雄联盟</option>
</optgroup>
</select>
效果如图所示,多个 option 元素可以被分在一组,使用 optgroup 元素之后,其 label 属性的值就是分组的名,会显示在页面上。
下拉列表除了可以单选以外,还可以进行多选,其实我们发现我们在一个网页上要多选,绝大多数时候都是多选框,很少会出现下拉列表进行多选的,所以其实用的很少,但是还是有必要进行介绍。
我们只需要在 select 元素里面加一个 multiple 属性(改属性为布尔属性),此时这个下拉菜单就可以实现多选。

此时只需要按住键盘上的 ctrl,即可实现多选功能。
textarea 元素
对于 text 类型的 input 元素,主要用来收集用户输入的文本,但读者可能会发现,这玩意儿好像只有一行,如果我需要用户输入一大段文本,这个东西就有不太好了,如果要让用户输入一个多行文本,就需要使用 textarea 元素。
html
<textarea cols="30" rows="10">
</textarea>使用这个元素,就可以生成一个多行文本,其中 cols 和 rows 用于控制初始大小有多少行和多少列,注意,一般来说,我们并不使用 cols 和 rows 来控制 textarea 的大小,一般我们更建议使用 css 去控制。

观察这个多行文本框的左下角,其实我们会发现这玩意儿是允许用户进行缩放的,如下所示。

实际上这并不好,因为缩放一个元素会影响其他元素的布局,从而影响整个网页。这其实是我们可以通过 CSS 控制的,当其 CSS 中的 resize 属性设置为了 none,就不允许用户缩放了。
textarea 也是文本框,所以其实也可以使用 placeholder 来设置内容为空时的提示文字。这一点和前面 text 类型的 input 一样。
回顾:textarea 中,如果要实现首行缩进,使用 text-indent 属性。
button 元素
接下来介绍 button 元素,实际上以前,要做一个按钮,只能使用 input 元素,input 元素提供了 submit ,reset 和 button 三种类型来实现按钮,HTML 4 之后提出了 button 元素,目前也都推荐使用 button 元素来替代以上三种 input 元素。相较于三种类型的 input 元素,button 元素有非常多的优势,例如语义化更加明确,可以实现更加精准的 CSS 控制,可以嵌套其他元素等等。
button 元素里也有一个 type 属性,表示按钮的类型,主要也是 reset,submit 和 button 三个属性。就替代了上面三种 input 元素。
botton 元素的 type 属性,如果不设置,默认值是 submit,也就是提交按钮。
html
<button>这是一个按钮</button>
可以看到,button 元素作为一个成双成对的元素,是可以嵌套其他元素的,其内容也是直接写在中间,而不用像 input 元素那样写在 value 里,甚至我们都可以在 button 元素里面加一个图片。
实际上,input 类型的按钮,也可以添加图片,此时就应该使用 image 类型的 input 元素,但由于这里的 button 可以完全替代这个功能,并且强大非常多,所以并不介绍。
表单元素的状态
任何一个表单元素都有一些状态,这些状态可以通过布尔属性进行设置,对于文本框的元素,可以设置只读文本框,即添加上 readonly 这一个布尔属性,就可以实现只读的文本框,即你只能看,不能改。而对于所有表单元素而言,它都可以被禁用,只需要添加上 disabled 这一布尔属性即可禁用该表单元素,一般来说,被禁用的表单元素,浏览器多多少少都会改变它的显示样式。
配合表单元素使用的元素
以上其实就介绍完了所有表单元素,但实际上,还有很多元素是可以配合表单元素使用的元素,注意,只是配合使用,其本身并不是表单元素,并不用于收集用户数据。
label 元素
这个元素通常是用于配合单选和多选框的。首先看一下前面写过的正常单选框。
html
请选择性别:
<input type="radio" name="sex">男
<input type="radio" name="sex">女
这就完成了一个单选功能,但实际上,我们在页面上经常看到这样一个不起眼的功能。

看到问题了吗,这里我根本没有点那个多选按钮,但是依然完成了选择,要实现这个功能就需要用到 label 元素。
可以认为 label 元素就是一个标签,比如上面的例子中,第一个多选按钮的标签文本为 男,第二个多选按钮的标签文本为 女。此时再使用 label 元素的 for 属性,设置为某一个 input 元素的 id 属性,就可以将这个 label 元素和 input 元素进行绑定。绑定之后,就可以通过点击 label 元素来完成单选和多选。
html
请选择性别:
<input type="radio" name="sex" id="nan">
<label for="nan">男</label>
<input type="radio" id="nv" name="sex">
<label for="nv">女</label>
这样其实就实现了点击文字选择按钮的操作,同样,对于多选框,这也同样适用。
这种方式我们可以称为显式关联,即通过 label 元素的 for 属性和某一个 input 元素的 id 属性,将一个 label 元素和 input 元素强制绑定起来。
html
请选择性别:
<input type="radio" name="sex" id="nan">
<input type="radio" id="nv" name="sex">
<label for="nv">女</label>
<label for="nan">男</label>
这种方式哪怕是不写在一起,也是可以关联起来的。
还有另一种方式,我更为喜欢,就是隐式关联,但前提是文字和选择框必须写在一起,隐式关联的写法就是将 input 元素和它的文字写在一个 label 元素里。
html
请选择性别:
<label>
<input type="radio" name="sex">男
</label>
<label>
<input type="radio" name="sex">女
</label>
这样也可以实现一样的效果,但显然,这种方式的前提是 input 元素和其文本必须写在一起,这种方法可以不用谢 label 元素的 for 属性和 input 元素的 id 属性,所以我本人更喜欢这种写法。
这里只使用了单选框作为演示,读者可以自行实验多选框
datalist 元素
在网页中,我们可能经常见到一些搜索功能的下拉菜单。

当我们输入文字的时候,会出现下拉菜单显示提示信息,当然,这个东西其实都是自己写的一个样式,但实际上,我们可以通过 datalist 元素模拟出这样一个效果。datalist 通常配合文本框来使用,可以很方便实现这样一个下拉菜单带提示的效果。
html
请输入你喜欢的浏览器:<input list="browser" type="text">
<datalist id="browser">
<option value="chrome">谷歌</option>
<option value="firefox">火狐</option>
<option value="safari">苹果</option>
<option value="opera">欧朋</option>
</datalist>
可以看到,这样就实现了一个下拉菜单的提示效果,通过 datalist 的 id 属性和 input 元素的 list 属性绑定起来,此时 datalist 内的 option 元素,就会变成这个 input 的下拉提示列表。注意,option 里面的内容为提示信息,option 的 value 值才是需要填入的信息。
这玩意儿用的很少,因为存在兼容性问题,同时,样式不好调,我们更多的时候是自己去写一个下拉菜单。只做了解。
form 元素
form 元素非常重要,它涉及到前后端交互,目前我们接触到的都是前端的开发,还涉及不到后端,我们这里简单介绍一下,比如一个登录页面,用户输入账号密码点击登录之后,我们就要把数据丢给后端,然后后端去验证这个数据是不是正确的,如果账号密码正确,我们的网页就会收到登录成功,然后就跳转到登录成功的页面,而如果登录失败,我们就提示一个登录失败,这就是一个简单的前后端交互。
我们的表单元素其实都一整组的,比如一个注册页面,账号,密码,验证码,这些就是一组表单元素,就要写在同一个 form 元素内。而像反馈的一些表单,比如反馈问题的时候我们一般会留下联系方式,留下意见等等,这些又是另一组表单元素,又要写在另一个 form 元素内。
form 元素对于静态页面没有任何意义,读者只需要知道一组表单元素需要放在同一个 form 表单中。
form 元素里面有两个属性,分别是 action 和 method。action 表示我们要提交的地址是哪里,method 表示提交方式,一般提交方式有 GET 和 POST。
html
<form action="https://baidu.com" method="get">
账号:<input type="text" name="user" id="">
<br>
密码:<input type="password" name="psw" id="">
<br>
<button>登录</button>
</form>以上代码效果如下

这个 form 表单的 action 是 https://baidu.com,也就是说当我们点击提交之后,我们写在这个 form 元素之内所有表单元素的数据就会被提交到百度。这里我们使用 get 方法来提交。我们看一下提交的效果。

使用 GET 方法提交的参数其实是被放在地址栏的,可以看到,当我们提交之后,地址栏上就会多出一些东西,即 ?user=test&psw=test,首先第一个问号不用解释,就是一个分隔符,问号前面的是链接地址,问号后面的就是提交的参数,每一对参数由 & 隔开,每一对参数都是一个键值对,即第一个参数的键为 user,值为 test,第二个参数的键为 psw,值为 test。这样我们的数据就提交到了百度。但是百度不知道我这个数据是干嘛的,所以可以认为它直接把我这个数据被百度服务器给丢弃了。
从这里读者也大概能理解表单元素中的 name 属性是用来干嘛的了,表单元素中 name 属性其实就是提交到后台的键,而表单元素的 value 就是提交到后台的值。
当然并不是所有的数据服务器都会丢弃,我们这里可以这样写
html
<form action="https://www.baidu.com/s" method="get">
<input type="text" name="wd" id="">
<button>搜索</button>
</form>
这个时候,当我们点击搜索的时候,我们就会想百度服务器传递一个名为 wd 是数据,数据值为 test,这个数据百度就会做一个搜索处理,并返回给我们一个搜索结果。这里读者应该可以理解,服务器只会对特定的数据名进行处理,比如我们前面名为 user 的数据和名为 psw 的数据,百度都不会做处理,但是这个名为 wd 的数据百度就做了处理。至于后端如何处理,我相信这并不是现阶段需要了解的事。
同样,下拉列表这些也可以进行传递
html
<form action="https://www.baidu.com/s" method="get">
<select name="city">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">深圳</option>
</select>
<button>提交</button>
</form>
我们可以看到,点击提交之后,提交到百度的数据是 city=3,实际上这个 city 就是下拉列表的 name ,这个 3 其实表示的是我们提交的数据值是 3,可以看到在我们下拉列表中,深圳对应 option 的 value 值正好是 3,所以后端就可以根据这个 3,判断出我们选择的是深圳。但是显然,百度并没有对这个名为 city 的数据做任何处理,所以我们并不能看到什么效果。
读者现在可能已经可以理解这个提交按钮是用来干嘛的了,没错,提交按钮就是把当前 form 表单的内容提交到服务器,具体提交到哪个服务器,以及用何种方式提交,就是由 form 元素的属性配置的。而其他两个按钮,重置按钮,其实就是可以把该 form 元素里的所有数据全部清空。而另一个普通按钮,就是什么也不干,这个需要配合 JS 来使用。
fieldset 元素
前面提到 form 元素,其实是划分表单的,比如我这个网页,上面部分是一个登录的,下面部分是一个用户反馈的,我们发现这两组表单元素是用于实现两个不同操作的,这种我们就可以认为这是完全独立的两个表单,所以其实 form 元素划分的所谓的分组,是按照功能划分的,相同功能的表单元素应该放在同一个 form 元素中,我们可以认为一个 form 元素就是一张表单,而我们前面提到的一个一个元素,则是表单元素。
但有时候,同一个表单,比如研究生报名的时候,会让你填写非常多的东西,但他们的功能就是报名填写信息,但是实在太多了,就可以在进行表单内部的二次分组。二次分组所用到的元素就是 fieldset 元素,同一组的元素放在同一个 fieldset 元素中,每一个 fieldset 元素内部还可以有一个 legend 的子元素,用于给这一组元素取一个名。
html
<form action="https://www.baidu.com" method="get">
<fieldset>
<legend>账号信息</legend>
<p>
账号:<input type="text" name="" id="">
</p>
<p>
密码:<input type="password" name="" id="">
</p>
</fieldset>
<fieldset>
<legend>基本信息</legend>
<p>
姓名:<input type="text" name="" id="">
</p>
<p>
性别:<input type="radio" name="" id="">男
<input type="radio" name="" id="">女
</p>
</fieldset>
<fieldset>
<legend>联系方式</legend>
<p>
电话:<input type="text" name="" id="">
</p>
<p>
邮箱:<input type="text" name="" id="">
</p>
</fieldset>
<button>注册</button>
</form>
效果如图所示,这里对一张大表单进行分组,其实更多的是基于语义化的考虑,哪怕不使用这个 fieldset 元素和 legend 元素,我们完全可以实现这样的样式。
和表单元素有关的 CSS
首先,先看这么一个东西

当我鼠标点一下电话右边的文本框,然后就可以给这个文本框输入内容,这个时候,实际上我们称这个被点击的文本框处于聚焦状态,或者说焦点在这个文本框里面。
这个样式是不是不太好看,我们其实可以修改,使用 :focuse 伪类就可以选择处于聚焦状态的元素,这个聚焦状态主要就是针对文本框的。可以看到,这个文本框处于聚焦状态的时候,元素默认是有一个类似边框加粗的效果,其实这个并不是边框,而是轮廓,即 outline 属性,浏览器一般会默认给处于聚焦状态的元素添加上一个默认的轮廓,这个 outline 属性和 border 属性并不一样,border 属性是盒模型的一部分,会占据页面空间,而 outline 属性则不是盒模型的一部分,只有显示效果,并不占据空间。
css
input:focus {
outline: 1px solid green;
}
可以看到,我这里将聚焦的轮廓修改成了绿色,此时处于聚焦状态的文本框的轮廓就变成了绿色。
其实除了文本框可以聚焦,其他的元素也是可以聚焦的,我们通过 tab 按键可以切换聚焦。

可以看到,当我点击 tab 按键的时候,焦点就会切换,可以看到,button 元素其实也是可以聚焦的,只不过我这里的选择器是 input:focus,即聚焦状态的 input 元素,而 button 并不是 input 元素,所以并没有改变 button 聚焦的默认样式。
说实话这个功能非常常见,我们其实会发现这个浏览器默认的 outline 非常丑,所以其实绝大多数的时候,我们可以在重置样式表里覆盖掉浏览器的默认样式。
说到 outline,这里提一下 outline-offset 属性

这里当我把 outline-offset 属性设置为 10 像素之后,我们可以看到,这里轮廓的位置发生了变化,可见这个属性用于设置轮廓的位置,有一些浏览器默认设置了这个属性,可能会导致一些样式上的问题,所以这里需要了解一下。
除了这个伪类以外,还有一个伪类是 :checked,表示单选或多选框被选中的样式。实际上不管是单选还是多选,可以设置的样式都非常有限,我们一般使用选择器来设置其兄弟元素的样式。
css
input:checked+span {
color: red;
}