查漏补缺之 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...

相关推荐
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
emmm4594 小时前
html兼容性问题处理
html
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js