HTML

DOCTYPE 的作用是什么?

DOCTYPE 是 Document Type 的缩写。DOCTYPE 总是与 DTD (Document Type Definition) 相关联。

DTD 定义了某种类型的文档应该如何构造(例如,button 可以包含 span 但不能包含 div),而 DOCTYPE 声明了文档_应该_遵循哪个 DTD(例如,此文档遵循 HTML DTD)。

对于网页,DOCTYPE 声明是必需的。它用于告诉用户代理您的文档遵循哪个版本的 HTML 规范。一旦用户代理识别出正确的 DOCTYPE,它将触发与此 DOCTYPE 匹配的无怪癖模式 (no-quirks mode) 来读取文档。如果用户代理无法识别正确的 DOCTYPE,它将触发怪癖模式 (quirks mode)。

HTML5 标准的 DOCTYPE 声明是 <!DOCTYPE html>

如何提供多语言内容的页面?

我假设这个问题是关于最常见的情况,即如何提供一个包含多种语言内容的页面,但页面内的内容应以一种一致的语言显示。

当向服务器发出 HTTP 请求时,请求的用户代理通常会发送有关语言偏好的信息,例如在 Accept-Language 头中。然后服务器可以使用此信息来返回文档的相应语言版本(如果存在此类替代版本)。返回的 HTML 文档也应在 <html> 标签中声明 lang 属性,例如 <html lang="en">...</html>

当然,这对于让搜索引擎知道相同的内容有不同语言版本是无用的,因此您还必须在 <head> 中使用 hreflang 属性。例如:<link rel="alternate" hreflang="de" href="http://de.example.com/page.html" />

在后端,HTML 标记将包含 i18n 占位符和以 YML 或 JSON 格式存储的特定语言内容。然后服务器通常借助后端框架,动态生成包含该特定语言内容的 HTML 页面。

在设计或开发多语言网站时,需要注意哪些事项?

  • 在 HTML 中使用 lang 属性。
  • 将用户导向其母语 — 允许用户轻松便捷地更改其国家/语言。
  • 基于栅格图像(例如 png、gif、jpg 等)中的文本不是可扩展的方法 — 将文本放置在图像中仍然是一种流行的实现方式,以便在任何计算机上显示美观、非系统字体。然而,要翻译图像文本,每串文本都需要为每种语言创建单独的图像。像这样超过少数的替换操作很快就会失控。
  • 限制性词语/句子长度 — 有些内容用另一种语言编写时可能会更长。请注意设计中的布局或溢出问题。最好避免在文本量会破坏设计的方面进行设计。字符数在标题、标签和按钮等内容中起作用。对于正文或评论等自由流动的文本,它们的影响较小。
  • 注意颜色的感知方式 — 颜色在不同语言和文化中被感知的方式不同。设计应适当使用颜色。
  • 日期和货币的格式 — 日历日期有时会以不同的方式呈现。例如,美国是“May 31, 2012”,而欧洲部分地区是“31 May 2012”。
  • 不要连接翻译后的字符串 — 不要进行类似 "The date today is " + date 的操作。这会在词序不同的语言中出错。请使用带有参数替换的模板字符串来代替每种语言。例如,看看下面两个句子,分别是英语和中文:I will travel on {% date %}{% date %} 我会出发。请注意,由于语言的语法规则,变量的位置不同。
  • 语言阅读方向 — 在英语中,我们从左到右、从上到下阅读,在传统日语中,文本从上到下、从右到左阅读。
  • 有用之处 — 在路径中包含语言环境(例如 en_US, zh_CN 等)。

`data-` 属性有什么用?

在 JavaScript 框架流行之前,前端开发者使用 data- 属性来将额外数据存储在 DOM 本身中,而无需使用其他技巧,例如非标准属性或 DOM 上的额外属性。它旨在存储页面或应用程序私有的自定义数据,对于这些数据没有更合适的属性或元素。

如今,通常不鼓励使用 data- 属性。原因之一是用户可以很容易地通过浏览器中的检查元素来修改数据属性。数据模型最好存储在 JavaScript 本身中,并通过可能通过库或框架实现的数据绑定来与 DOM 保持同步。

然而,数据属性的一个完全有效的使用是为端到端测试框架(例如 Selenium 和 Capybara)添加一个钩子,而无需创建无意义的类或 ID 属性。元素需要一种方法被特定的 Selenium 规范找到,而像 data-selector='the-thing' 这样就是一种有效的方法,而不会使语义标记变得混乱。

将 HTML5 视为一个开放的 Web 平台。HTML5 的构建块是什么?

  • 语义化 — 允许您更精确地描述您的内容。
  • 连接性 — 允许您以新的创新方式与服务器通信。
  • 离线和存储 — 允许网页在客户端本地存储数据并更有效地离线操作。
  • 多媒体 — 使视频和音频成为开放网络中的一流公民。
  • 2D/3D 图形和效果 — 允许更广泛的展示选项。
  • 性能和集成 — 提供更高的速度优化和更好地利用计算机硬件。
  • 设备访问 — 允许使用各种输入和输出设备。
  • 样式 — 允许作者编写更复杂的样式主题。

描述 `cookie`、`sessionStorage` 和 `localStorage` 之间的区别。

所有上述技术都是客户端的键值存储机制。它们只能将值存储为字符串。

| | cookie | localStorage | sessionStorage | | --- | --- | --- | --- | | 启动者 | 客户端或服务器。服务器可以使用 Set-Cookie 头 | 客户端 | 客户端 | | 过期时间 | 手动设置 | 永久 | 关闭标签页时 | | 跨浏览器会话持久性 | 取决于是否设置了过期时间 | 是 | 否 | | 随每个 HTTP 请求发送到服务器 | Cookie 会通过 Cookie 头自动发送 | 否 | 否 | | 容量(每个域) | 4kb | 5MB | 5MB | | 可访问性 | 任何窗口 | 任何窗口 | 同一个标签页 |

注意:如果用户决定通过浏览器提供的任何机制清除浏览数据,这将清除所有存储的 cookielocalStoragesessionStorage。在设计本地持久性时,务必牢记这一点,尤其是在与服务器端存储在数据库或其他类似方案(当然,这些方案会持久化,无论用户行为如何)进行比较时。

描述 `<script>`、`<script async>` 和 `<script defer>` 之间的区别。

  • <script> - HTML 解析被阻塞,脚本立即被获取和执行,HTML 解析在脚本执行后恢复。
  • <script async> - 脚本将与 HTML 解析并行获取,并尽快执行(可能在 HTML 解析完成之前)。当脚本独立于页面上的任何其他脚本时使用 async,例如分析脚本。
  • <script defer> - 脚本将与 HTML 解析并行获取,并在页面完成解析后执行。如果有多个,每个延迟脚本按照它们在文档中出现的顺序执行。如果脚本依赖于完全解析的 DOM,defer 属性将有助于确保 HTML 在执行之前完全解析。延迟脚本不得包含 document.write

注意:asyncdefer 属性对于没有 src 属性的脚本将被忽略。

为什么将 CSS 的 `<link>` 放在 `<head></head>` 之间,而将 JS 的 `<script>` 放在 `</body>` 之前通常是个好主意?您知道任何例外情况吗?

<link> 放在 <head>

<link> 放在 <head> 中是构建优化网站的正确规范的一部分。当页面首次加载时,HTML 和 CSS 同时被解析;HTML 创建 DOM(文档对象模型),CSS 创建 CSSOM(CSS 对象模型)。两者都需要在网站中创建视觉效果,从而实现快速的“首次有意义绘制”时间。这种渐进式渲染是衡量网站性能得分的优化类别。将样式表放在文档底部会阻止许多浏览器进行渐进式渲染。一些浏览器会阻止渲染,以避免在样式更改时重新绘制页面元素。然后用户只能看到空白页面。有时会出现未样式化内容的闪烁 (FOUC),显示未应用样式的网页。

<script> 放在 </body> 之前

<script> 标签在下载和执行时会阻塞 HTML 解析,这会减慢您的页面速度。将脚本放在底部将允许 HTML 首先被解析和显示给用户。

<script> 放在底部的一个例外是当您的脚本包含 document.write() 时,但现在使用 document.write() 不是一个好习惯。此外,将 <script> 放在底部意味着浏览器无法开始下载脚本,直到整个文档被解析。这确保了您的需要操作 DOM 元素的代码不会抛出错误并停止整个脚本。如果您需要将 <script> 放在 <head> 中,请使用 defer 属性,它将实现相同的效果:仅在 HTML 解析后运行脚本,但浏览器可以更早地下载脚本。

请记住,将脚本放在闭合 </body> 标签之前会造成页面在空缓存上加载速度更快的错觉(因为脚本不会阻塞文档其余部分的下载)。但是,如果您有一些代码要在页面加载期间运行,它只会在整个页面加载完成后才开始执行。如果您将这些脚本放在 <head> 标签中,它们会更早开始执行——所以在预热缓存上,页面实际上会显得加载更快。

<head><body> 标签现在是可选的

根据 HTML5 规范,某些 HTML 标签,如 <head><body>,是可选的。谷歌的样式指南甚至建议删除它们以节省字节。然而,这种做法仍未被广泛采用,性能增益可能微乎其微,对于大多数网站来说,这可能无关紧要。

什么是渐进式渲染?

渐进式渲染是指用于提高网页性能(特别是改善感知加载时间)以尽快渲染内容进行显示的技术。

在宽带互联网普及之前,它更为普遍,但如今在现代开发中仍然被使用,因为移动数据连接变得越来越流行(且不可靠)!

此类技术的示例:

  • 图片延迟加载——页面上的图片不会一次性全部加载。当用户滚动到显示图片的页面部分时,JavaScript 将用于加载图片。
  • 优先渲染可见内容(或首屏渲染)——仅包含渲染用户浏览器中首次显示所需的最少 CSS/内容/脚本,以便尽快显示,然后您可以使用延迟脚本或监听 DOMContentLoaded/load 事件来加载其他资源和内容。
  • 异步 HTML 片段——在后端构建页面时,将部分 HTML 刷新到浏览器。有关该技术的更多详细信息可以在此处找到。

为什么要在 `img` 标签中使用 `srcset` 属性?解释浏览器在评估此属性内容时使用的过程。

当您想根据用户设备的显示宽度向用户提供不同的图像时,您可以使用 srcset 属性——向 Retina 显示屏设备提供更高质量的图像可以增强用户体验,而向低端设备提供低分辨率图像可以提高性能并减少数据浪费(因为提供更大的图像不会有任何可见差异)。例如:<img srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 2000w" src="..." alt=""> 告诉浏览器根据客户端的分辨率显示 small、medium 或 large 的 .jpg 图形。第一个值是图像名称,第二个值是图像的像素宽度。对于设备宽度为 320 像素的情况,会进行以下计算:

  • 500 / 320 = 1.5625
  • 1000 / 320 = 3.125
  • 2000 / 320 = 6.25

如果客户端的分辨率为 1x,则 1.5625 最接近,浏览器将选择对应于 small.jpg500w

如果分辨率为 Retina (2x),浏览器将使用高于最小值的最接近分辨率。这意味着它不会选择 500w (1.5625),因为它大于 1 且图像可能看起来不好。然后浏览器将选择结果比率更接近 2 的图像,即 1000w (3.125)。

srcset 解决了您希望向窄屏设备提供较小图像文件的问题,因为它们不需要像桌面显示器那样巨大的图像——并且还可以选择向高密度/低密度屏幕提供不同分辨率的图像。

您以前使用过不同的 HTML 模板语言吗?

是的,例如 Pug(以前是 Jade)、ERB、Slim、Handlebars、Jinja、Liquid 和 EJS。在我看来,它们或多或少都是相同的,提供相似的内容转义功能和有用的过滤器来操作要显示的数据。大多数模板引擎还允许您注入自己的过滤器,以防您在显示之前需要自定义处理。

Canvas 和 SVG 有什么区别?

Canvas 基于像素,处理像素,而 SVG 基于矢量,采用形状的数学描述。Canvas 采用命令式绘图,每一步都用 JavaScript 指定,非常适合动画和游戏等动态交互式图形。

相反,SVG 使用声明式绘图,形状和路径直接在 HTML 中定义,使其更易于访问和 SEO 友好。由于其较低的开销,Canvas 最适合复杂的场景,但缩放可能会导致图像质量下降。SVG 是分辨率独立的,可适应各种屏幕尺寸而不会牺牲质量。

最终,canvas 适用于动态、性能要求高的图形,而 SVG 则擅长可伸缩、分辨率独立的图形,并具有固有的可访问性和 SEO 优势。

HTML 中的空元素是什么?

HTML 中的空元素是指在起始标签和结束标签之间不包含任何内容的元素。它们是自闭合标签,这意味着它们在闭合角括号 (>) 之前有一个斜杠 (/)。空元素的一些常见示例包括:

  • <img>: 用于在文档中嵌入图像。
  • <input>: 用于接受用户输入。
  • <br>: 用于插入换行符或强制换行符。
  • <hr>: 用于创建水平线或分隔符。