查漏补缺之 HTML 篇 part3

前言

迷茫的时候,卷就是最好的选择;毕竟,与人斗其乐无穷。

本节主要对 HTML 标签使用进行介绍;掰头一下应用场景及最佳实践的思考;以及一些标签使用的问题总结。

另外,这里对元素和标签做一个释义,它们之间的区别在于元素一般是我们单独提及,如 p 元素;而标签则是在使用时通过闭合语法,如 <p></p> 就是指 p 标签。一般情况下,两者可以互通,即说标签也可以说元素也没问题。

文档声明

文档声明,告知浏览器以何种规范解析 HTML 和 CSS ;如果不指定或指定错误则默认以怪异模式解析;如果指定了标准,则根据指定的标准模式进行解析

html5 之后,应该始终使用最新的 DOCTYPE 值;注意:DOCTYPE 声明是大小写敏感的

html 复制代码
<!DOCTYPE html>

早期也出现过的一些声明文档类型的值,用来告知浏览器 HTML 或 XHTML 的版本;也将会以标准模式解析

html 复制代码
<!-- HTML 4.01 Strict -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<!-- XHTML 1.0 Strict -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

quirks 模式

根据浏览器自己的规范解析 HTML 和 CSS;好嘛,那就八仙过海,各显神通吧~同一套代码在不同浏览器上的解析效果必然是五花八门的

核心特性:盒子模型的宽度和高度通常包括边框和内边距;这种形式被称为怪异盒模型,是 IE8 以下的怪异模式下的解析形式

当然,除了早期的 IE8 浏览器行为特别怪异外;现代浏览器基本都开始遵循 HTML 和 CSS 规范,因为即使不设置 DOCTYPE,你会发现,差异也并不大;

standards 模式

浏览器会尽可能地遵守HTML和CSS规范,以确保页面的外观和行为符合预期;

盒模型

什么是盒模型?用来描述元素如何在网页上渲染的矩形盒子,包括 content、border、margin、padding

css 可以通过 box-sizing 来控制盒模型的方式,默认值为 content-box,即标准盒模型;设置 box-sizing: border-box; 则为怪异盒模型

content-box 与 border-box 的区别

content-box:设置内容的宽高即为渲染的宽高,padding、border 则会将元素撑开

border-box: padding、border 会占据内容的宽高

关于 border-box 思考

border-box 有时反而非常有用,由于 content-box 会受到 padding、border 的影响而撑开元素,很容易导致在弹性布局中导致宽度不够导致换行问题。如以下弹性布局中,使用 li 实现,对 li 设置 box-sizing: border-box; width: 50%; 即可实现弹性自适应

适用场景:

  • 固定布局:让元素在固定大小的区域内保持一定的尺寸
  • 弹性布局:让元素能够随着窗口尺寸的变化而改变尺寸;百分比布局也是如此,不需要考虑 padding、border 的影响
  • 滚动条问题:避免滚动条影响元素的尺寸

figure 和 figcaption

figure 和 figcaption 并不是语义化标签 ,它们只是用来添加对外部资源或独立内容的描述,从而让搜索引擎更好的理解这一块内容,帮助 SEO ;同时 figure 标签具有默认的 margin,可以更好的帮助排版,无样式渲染等

html 复制代码
<figure>
  <img src="xxx.png" alt="logo"/>
  <figcapition>fg1. learn site logo</figcaption>
</figure>

最佳实践:

figure 标签适合用来对图片、音视频、表格、代码块、诗句、文章等独立内容添加描述或标题(添加标题时 figcapition 在上);但它并不是语义化标签,不能用来替代 p、h、ul 这样的语义化标签;

即语义化标签优先,figure 后考虑;比如你的页面上只有一个表格,那么这个表格的标题,最好的选择是使用 h 标签;而某个局部独立区域的表格,才是使用 figure 标签的适用场景。

一个非常适用的场景就是如上图所示的一组图片 + 描述形式

代码呈现元素

figure 可以用来为代码添加描述或标题,那 HTML 中用来表示代码的元素你又了解多少?

  • code,用来表示计算机代码,忽略格式
  • pre,用来表示计算机代码,保留原始输入的所有空格和换行
  • kbd,用来表示键盘输入内容,如快捷键
  • samp,用来表示命令行命令的输出结果
  • var,用来表示公式、变量中的字母;默认具有斜体字
html 复制代码
  <p>运行 npm run dev, 终端将输出:<samp>http://192.168.10.56:8899/</samp></p>
  <p>表达式: <var>x</var> = <var>y</var> + 2 </p>
  <pre>
    function test() {

    }
  </pre>
  <code>
    function test() {

    }
  </code>
  <p>快捷复制:<kbd>CTRL + C</kbd></p>

最佳实践:

  • 代码呈现元素并不是语义化标签,只是用来强调文本;只是这些强调都和代码相关,更方便理解
  • 键盘输入内容使用 kbd、公式变量使用 var、计算机代码一般需要保留格式使用 pre
  • pre 标签是块级元素,具有 HTMLPreElement DOM 接口,且具有默认的 margin;其他元素则大部分继承自 HTMLSpanElement,为行内元素
  • var 元素的内容默认具有斜体,其他则是默认等高字体;可以通过 CSS 重置效果,一般是通过 reset.css 默认设置

文本强调元素

代码相关的强调,使用上述的代码呈现元素;除代码之外,HTML 还提供了一些其他的强调元素

  • strong, 表示文本非常重要;默认具有加粗效果
  • b, 表示相对于普通文本字体上的区别,但不表示任何特殊的强调;默认具有加粗效果
  • em, 强调某个短语;默认具有斜体
  • i, 表示从正常文本区分的内容;默认具有斜体
  • mark, 标记状态的内容;默认具有高亮效果

真正具有强调含义的是 strong、em;b、i 不具有强调效果,只是语义化突出内容

b vs strong

两者都默认具有加粗效果

strong 标签表示严重强调内容 ,常用来强调重要语句;只是它默认是加粗的,这个强调效果可以是红色、下划线、背景色等等;

b 则是用来语义化表示突出的文字,不具有强调效果;如产品名、人物名、关键字

如果只是为了单纯的加粗引起注意,请使用 font-weightL bold; 进行加粗

em vs i

两者都默认具有斜体效果

em 表示强调内容,通常用来强调短语;如需要着重标识的单词,如搜索引擎的关键字就是使用 em 实现的

i 则用来语义化从正常内容中突出文字,如科学术语、化学方程、旁白、说明、书籍名、电影名

em vs mark

mark 用来突出显示的文本通常是外部引用的文本,或者标记成特殊审查的内容;具有高亮效果

不要为了语法高亮而使用 mark 标签;你应该用 strong 元素来实现这个目的(语法高亮)

mark 一定是具有特殊标记、外部引用 等内容突出效果时使用;即必须与正常内容产生关联性

label 解决可访问性问题

表单图标如 radio、checkbox 可点击区域非常小,很容易点不中

html 复制代码
<!-- 方案1:单独包裹 -->
<label>
  扩大区域 
  <input name="input" type="checkbox" />
</label>

<!-- 方案2: for + id 关联 -->
<label for="test2">
  扩大区域  
</label>
<input name="input" type="checkbox" id="test2" />

<!-- 方案3:双管齐下 -->
<label for="test3">
  扩大区域 
  <input name="input" type="checkbox" id="test3" />
</label>

通过 label 包裹后,就可以扩大点击区域,如上,点击扩大区域文本也会切换 checkbox 的选择;

理论上,直接通过 label 包裹就可以生效、使用 for + id 关联单独就可以生效;如上述代码方案1、方案2;但为了兼容性,推荐使用方案3,双管齐下

label 除了扩大点击区域,也常用来实现一些自定义的组件样式,如下,是一个 label + 隐藏的文件选择空间;我们只需要控制 label 的样式即可

html 复制代码
<label for="fileInput">选择文件</label>
<input type="file" id="fileInput" hidden>

area 元素的应用

area 元素用来标记图片的热点区域,一般配合 map 使用,可以通过 TAB 检索 area 查看形状;这在电子邮件场景下非常有用,因为邮件不支持复杂的布局(支持 table)

html 复制代码
<img src="mm1.jpg" alt="美女" usemap="#MM">
<map id="MM" name="MM">
  <area shape="rect" coords="20,20,80,80" href="#rect" alt="矩形">
  <area shape="circle" coords="200,50,50" href="#circle" alt="圆形">
  <area shape="poly" coords="150,100,200,120" href="#poly" alt="多边形">
</map>
  • shape,表示热点的形状,支持矩形rect,圆形circle以及多边形poly
  • coords,热点形状区域坐标
  • href,跳转链接,area 可以看做半个 a 标签
  • target,同 a 的 target 属性,控制链接打开方式
  • alt 同图片的 alt,表示热点区域的描述信息

area 解决 a 标签嵌套问题

a 标签无法嵌套,即使你改变为 block 布局,依然会造成渲染错误

为啥需要 a 标签嵌套?

好像咱们正常情况下,a 标签内部就不应该有内容可以点击跳转吧?是的,正常不应该有,但有一种场景,就是埋点热力图分析;a、input 默认具有热力图分析功能,外层的 a 不设置跳转,内层各区域跳转

模拟 a 标签

当一个块级 a 内部还有一个模块可以跳转时,使用普通的 span 等元素模拟,

  • 1、需要通过 click 事件处理;
  • 2、模拟时还需要考虑 tabindex、role 等无障碍访问;
  • 3、然后还需要阻止外层 a 的访问事件,即需要阻止事件冒泡,不然会有两个跳转

使用 area

使用 area 则天然的不需要阻止冒泡、设置 tabindex、role;完美的解决 a 标签嵌套问题

元素嵌套问题

HTML 对于元素的嵌套有一定的限制,目的是为了保证元素功能及其语义;更多的是一种强制的记忆,熟悉标签的使用规则,这也是早期 div 布局横行的原因之一,用 div 来组织文档结构,根本不存在这些所谓的嵌套问题

同时,应该尽可能减少嵌套层级,影响页面性能和爬虫读取

思考

现在常用的 flex 布局,让嵌套层次越写越深...

a 内部不能嵌套 a、input、select

原理也简单,a、input、select、button 它们都有自己的行为;一旦 a 标签内部嵌套了这些标签,容易引起行为或功能的混乱

p 标签不允许嵌套块级标签

如 p、h、header 等;均不能嵌套在 p 标签内部

原理也简单,p 标签用于表示一个段落,那段落里怎么能又放一个段落呢?这在本质上就是违反语义的,段落里不会再有段落了,只能有文本呈现元素

detail 元素展开收起

html 复制代码
<details>
  <summary>详情</summary>
  我是具体描述
</details>

html5 提供 details、summary 来实现展开收起行为(三角图标+描述,点击 toggle 展开收起)

  • details 标签内放详细描述的内容,默认收起,可以通过设置 open 属性默认展开
  • summary 用来设置具体描述 slot,缺省时展示"详细信息"
  • 我们可以重置 summary 的三角形等样式,而不需要额外的 js 代码来实现展开与收起功能

思考

好像没有办法实现点击时切换 summary 里面文案,如展开/收起这样的效果?伪类 + content + attr 也控制不了;so,大概率还是得 js 来

可访问性 fieldset 和 legend

表单元素之间默认并没有关联。当我们有一组如省市区的选择表单时,无障碍用户并不知道它们之间有关联

我们可以将多个有关系的表单放到 fieldset 元素内部,legend 标签则表示这个组的标题

适用于有关联多个表单,通过 fieldset 包裹,legend 描述信息:

  • 多个有关系的单选按钮(是否)
  • 省市区等多个有关系选择框,legend 就可以是"收货地址"这样的文字
html 复制代码
<fieldset>
  <legend>收货地址:</legend>
  <span>省</span>
  <select>
    <option>测试省</option>
  </select>
  <span>市</span>
  <select>
    <option>测试市</option>
  </select>
  <span>区</span>
  <select>
    <option>测试区</option>
  </select>
</fieldset>

最佳实践:

  • 使用时避免过度嵌套;同时如果是单个表单,不要使用
  • 尽量使用 label 标签来标记每个控件,以便更好地理解和使用表单
  • 只用来包裹 input、select、button 等元素

HTMLUnknownElement 与 customElement

HTMLUnknownElement:规范以外的标签元素,不能是短横线命名规则(短横线命名规则的是自定义元素)

  • 例如 HTML5 已经不在支持 font 这样的标签,如果你在页面中使用,那它就是一个未知元素
  • 或者你随便写的一个元素,只要不是短横线命名,如 <username></username>

检测是否为未知元素:document.createElement('username') instanceof HTMLUnknownElement === true;

customElement

customElement 是 web components、shadow DOM、Vue 模板的核心;必须满足短横线命名规则;

创建时的两个核心:

  • 继承 HTMLElement、HTMLFormElement、HTMLDivElement、HTMLSpanElement 等类声明的自定义类
  • 通过 customElements.define('custom-ell', HTMLCustomElement);

一个完善的自定义元素模版;大致理解即可,想要深入掌握,在 shadow DOM 中再做分析

picture 标签

picture 本身是一个很实用的标签,常用来在不同场景使用不同图片;但由于语义化开发并没有太多人关注,且存在替代方案,所以使用的人一直不多

使用场景

  • 不同尺寸屏幕显示不同图片
  • 不同浏览器显示不同后缀图片

[重要]渲染的时候,浏览器优先使用顺序使用 <source> 元素,<img> 元素兜底

不同尺寸屏幕显示不同图片

html 复制代码
  <picture>
    <source srcset="../../statics/images/learn/html_good.png" media="(min-width: 640px)">
    <source srcset="../../statics/images/learn/html_bad.png" media="(min-width: 800px)">
    <img src="../../statics/images/learn/layout.png">
  </picture>

上述效果,也可以通过 css 媒体查询实现

不同浏览器显示不同后缀图片

比如说我们期望使用 avif、webp 等更小,压缩效果更好的图片格式,怎么实现优雅降级呢?

一种方式是通过判断兼容性,采用不同的格式;

另一种就是通过 picture 标签,由于它渲染时会优先按顺序解析 source 元素的图片格式,然后 img 标签兜底

当然,终极的方案是交给云服务厂商处理的,通常 COS 服务支持通过配置进行图片优化,直接处理所有图片,完全不用一个一个手动转格式

template 元素

template 中的内容不会渲染,提供了一种可复用内容的方式,使用方式

  • 1、<script type="text/template"></script> 非标准的方式
  • 2、内容放到 textarea 标签,设置 display: none;
  • 3、<template></template> 推荐

template 标签内容默认是隐藏的;且可以放在任意位置,如 style、script、div 等标签

思考

上述 3 种方案,本质都是在页面上放置隐藏元素;这是不利于 seo 的;早期,为了更好的 seo,开发者经常通过隐藏元素来提升页面的权重,搜索引擎有一套完整的算法可以针对这部分内容进行有效识别,防止作弊,反而会影响 seo 效果

因此,针对现代的搜索引擎,最好不要带有隐藏的元素,防止被误认为作弊(如果一定需要有,放在页面底部)

子元素无效性

template.content 返回一个 document fragment,所有子节点的查询、处理均需要通过 template.conent 操作

js 复制代码
// 无效 
document.querySelect("#myTemplate").querySelector("h2")

// 获取到 template 的 h2 
document.querySelect("#myTemplate").content.querySelector("h2")

应用

  • 预设数据,如某段 html、css,只在特定的条件启用
  • 延迟加载,将页面上暂不需要的内容放在 template 中,在需要的时候才追加到文档中渲染
  • 作为模板引擎,动态生成内容

meter 元素

meter 的意思是计量表,在 Web 中,任何与丈量有关,需要分阶段提示的场景,都非常适合 meter 元素

特性&使用

meter 具有最多三种效果,正常状态的绿色UI、警戒状态的橙色 UI、危险状态的红色 UI

非常适合例如剩余油量、温度、降雨量、游戏中人物血量、强中弱三级密码强度等等场景

html 复制代码
<meter min="0" max="100" low="30" high="60" optimum="80" value="20"></meter>
  • min、max 表示数值范围,默认为 0-1
  • low、height 表示警戒值,low 表示低警戒值,height 表示高警戒值
  • value 表示当前值,默认为 0
  • optimum 属性表示最佳值,用来决定过低和过高值属于正常还是异常

关于 optimum

  • 如果 optimum 唯一 low - height 中间,则低于 low 或高于 height 都是警戒状态,low - height 之间为正常状态
  • 如果 optimum 小于 low,那么会有三种状态,低于 low 正常,low - height 警告,高于 height 危险
  • 如果 optimum 大于 height,那么会有三种状态,高于 height 正常,low - height 警告,低于 low 危险

iframe

iframe 是 HTML 提供用来在文档中嵌入另一个文档的内联框架

优点:

  • 可以用来解决加载缓慢的第三方内容,如客服、广告等
  • 异步加载,iframe 动态设置 src 可以实现异步加载内容,提升性能
  • 可以用来解决跨域通讯问题:domain + iframe,但目前 Chrome 已经开始限制 domain 的设置,只允许读取,建议更换为 postMessage 的形式

缺点:

  • 每个 iframe 都需要进行一次 HTTP 请求,从而增加了页面加载时间
  • iframe 会阻塞主页面的 onload 事件(可通过上述动态设置 src 解决)
  • SEO 不友好,无法被爬虫爬取

结束语

作为一个油盐不进的爱卷人士,这当然不是一个结束,后续将会持续进行更新。To Be Continue...

相关推荐
梦境之冢2 分钟前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun5 分钟前
vue VueResource & axios
前端·javascript·vue.js
m0_5485147722 分钟前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
AndrewPerfect22 分钟前
xss csrf怎么预防?
前端·xss·csrf
Calm55025 分钟前
Vue3:uv-upload图片上传
前端·vue.js
浮游本尊30 分钟前
Nginx配置:如何在一个域名下运行两个网站
前端·javascript
m0_7482398330 分钟前
前端bug调试
前端·bug
m0_7482329232 分钟前
[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结
前端·搜索引擎
新中地GIS开发老师38 分钟前
《Vue进阶教程》(12)ref的实现详细教程
前端·javascript·vue.js·arcgis·前端框架·地理信息科学·地信
m0_7482495440 分钟前
前端:base64的作用
前端