《HTML并不简单:Web前端开发精进秘籍》张鑫旭 笔记
label
语义为“标签”,但往往标签内容并没有实用label元素。一般来说,label元素需要和其他元素产生关联才能体现价值。
与:
- 传统表单控件元素:button、input、textarea、select等
- 之后博客会讲到的progress和meter
- 非典型表单元素output
假如有登陆表单如下,不使用label也可以:
<form action="">
<div>
<span>邮箱</span>
<input type="email" />
</div>
<div>
<span>密码</span>
<input type="password" />
</div>
</form>
但使用label会更好:
- 语义更精确
- 扩大了输入框的响应区域
<form action="">
<div>
<label for="email">邮箱</label>
<input type="email" id="email" />
</div>
<div>
<label for="password">密码</label>
<input type="password" id="password" />
</div>
</form>
当label元素和表单控件元素产生关联时,点击label元素,表单会自动处于激活状态。输入框表现为焦距,单选按钮和复选框表现为选中态切换。
span就做不到。
<input type="checkbox" id="agree">
<label for="agree">我同意</label>
上面代码,点击文字相当于点击checkbox
。
产生关联的方式
上面提到,label元素能与特定元素产生关联:
- 传统表单控件元素:button、input、textarea、select等
- 之后博客会讲到的progress和meter
- 非典型表单元素output
产生关联的方式有两种:
- 通过特定的HTML属性,如上述for和id
- 通过HTML结构关系
HTML属性
label的for属性与相关联表单控件的id属性相同。
HTML结构
将表单控件放在label元素中:
<label>
邮箱
<input type="email" />
</label>
这里如果有for=''
,相当于没绑定(覆盖了默认绑定的for='email'
),不会扩大输入框的响应区域。
for属性
for在js中是关键字,因此想使用js获取html中的for属性,要使用htmlFor
:
document.querySelector('label').htmlFor
output元素也支持for属性,且支持多个值。
output- HTML(超文本标记语言) | MDN (mozilla.org)
<input type="number" id="price" />
<input type="number" id="amount" />
<output for="price amount"></output>
用来标识输出结果关联的表单元素。
HTMLOutputElement.htmlFor
返回的就是一个DOMTokenList
对象。
https://www.htmlapi.cn/3/3-1.html
案例
可以使用label实现以下效果,无需js就能实现交互。
将label元素作为点选的主体元素,内部放置隐藏的单选按钮元素:
<label>
<input type="radio" name="money" value="150" checked hidden>
<span>¥150</span>
</label>
<label>
<input type="radio" name="money" value="100" checked hidden>
<span>¥100</span>
</label>
使用合适的CSS选择器匹配单选按钮的状态变化,可以使用has伪类:
label:has(:checked) {
}
如果想实现想switch开关那样的效果,里面的控件换成它即可:
<input epub:type='checkbox'>
作者示例:
https://www.htmlapi.cn/3/3-2.html
fieldset和legend
这样写表单的代码不好:
<form>
<p>你有xxx吗</p>
<input type="radio" id="yes" />
<label for="yes">有</label>
<input type="radio" id="no" />
<label for="no">无</label>
</form>
因为最开始的问题和下面的两个单选选项是有关联的,或者说带有“组”的关系,而上述HTML代码并未建立起对应的联系。此时,当用户触摸(移动端交互方式)两个单选按钮的时候,听到的仅仅是
<label>
元素中的“有”和“没有”两个词,至于对应的问题是什么,不得而知,或者是触摸到了问题,但是并不知道对应的选项是什么,这时用户体验就不好。
改成这样好:
<form>
<fieldset>
<legend>你有xxx吗</legend>
<input type="radio" id="yes" />
<label for="yes">有</label>
<input type="radio" id="no" />
<label for="no">无</label>
</fieldset>
</form>
<fieldset>
元素表示组的意思,专门用在表单元素中,表示一组内容;<legend>
元素表示这个组的标题,在这个例子中,就是问题内容。
使用Tab键导航(桌面端交互方式)表单(单选按钮聚焦,屏幕阅读识别),就会清晰读出“你有xxx吗?”。这样,用户就能清楚地知道,下面的“有”和“没有”对应的到底是什么。
表单内容若有 分组 概念,最好就使用fieldset和legend。
唯一的边框样式
如果想实现以下样式,fieldset和legend是最好的实现方法:
<fieldset>
<legend>标题</legend>
</fieldset>
fieldset {
border: 1px solid #ccc;
}
若想让标题在上面居中:
legend {
margin-inline: auto;
}
可以用它实现分割线,不过不推荐,语义不符:
fieldset {
border: 0;
border-top: 1px dashed #ccc;
}
<legend>
元素的语义是“标题”,而不是“分隔线”。更建议大家使用<hr>
元素模拟分隔线。
批量禁用表单元素
<fieldset disabled>
<legend>标题</legend>
<input type="text">
<input type="text">
<input type="text">
</fieldset>
disabled
属性可以批量禁用fieldset
内的表单元素,同时可以匹配CSS:disabled伪类。只有fieldset
有这种功能。
不要使用CSS
pointer-events:none
声明禁用表单了,也不要再使用HTMLinert
属性去禁用表单了,这些方法只是表面上的禁用。
示例:https://www.htmlapi.cn/3/4-2.html
progress
在上传图片或者下载资源的时候,往往都会用百分比进度条来表示当前任务的效果。此时,千万不要花费大量的时间和代码去模拟,浏览器提供了原生的HTML元素,样式自定义方便,兼容性良好,且语义一级棒。
<progress value="50" max="100"></progress>
progress:进度指示元素 - HTML(超文本标记语言) | MDN (mozilla.org)
如果我们没有设置value属性,则进度条进入不确定态,样式表现为循环等待状态。操作系统不同,浏览器不同,等待效果的样式也会有所不同。此状态会匹配CSS:indeterminate
伪类。
作者示例:https://www.htmlapi.cn/3/5-1.html
meter
<meter
min="0"
max="100"
low="30"
high="60"
optimum="80"
value="20"
></meter>
<meter
min="0"
max="100"
low="30"
high="60"
optimum="80"
value="50"
></meter>
<meter
min="0"
max="100"
low="30"
high="60"
optimum="80"
value="70"
></meter>
meter:HTML 标量元素 - HTML(超文本标记语言) | MDN (mozilla.org)
如果optimum属性值在low和high之间,则说明low和high都是警戒值,只有在这个区间范围内的值才是正常的,因此,最终的色值状态只有两个,即橙色警戒和绿色正常。
如果optimum属性值比low小,则说明low不是警戒值,而是推荐值,也就是值越小安全性反而越高,此时,low-high之间的范围就属于警戒范围,而超过high的值就属于危险范围了。
如果optimum属性值比high大,也会出现3段色值状态,此时,大于high的值会被认为是正常的,因此表现为绿色,这个效果可以类比为密码强度。
一些伪元素:
- meter元素自身的选择器。
::-webkit-meter-inner-element{}
.::-webkit-meter-bar{}
灰色背景条。::-webkit-meter-even-less-good-value{}
红色。::-webkit-meter-optimum-value{}
橙色。::-webkit-meter-suboptimum-value{}
绿色。