关于 HTML/SVG 用法的有趣随机事实

Avatar of Catalin Rosu
Catalin Rosu

DigitalOcean 为您的旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

上次,我们看到了 平均网页 的样子,使用了来自约 800 万个网站 的数据。 这是一个很大的数据集,我们一直在继续筛选它。 我们这次又回来了,展示一些关于标记用法有趣的随机事实。

隐藏 DOM 元素

隐藏 DOM 元素有多种方法:完全隐藏、语义隐藏或视觉隐藏。

考虑到当前的做法和建议,请查看通过 HTML 或 CSS 隐藏内容的最常用方法的发现结果。

选择器 计数
[aria-hidden] 2,609,973
.hidden 1,556,017
.hide 1,389,540
.sr-only 583,126
.visually-hidden 136,635
.visuallyhidden 116,269
.invisible 113,473
[hidden] 31,290

no-js HTML 类

当 Modernizr 等 JavaScript 库运行时,no-js 类将被删除,并被替换为 js。 这样,您就可以根据浏览器中是否启用了 JavaScript 来应用不同的 CSS 规则。

我们发现共有 844,242 个元素的 HTML 类列表包含 no-js 字符串。 其中超过 92% 是 html 元素。

如果您想知道剩下的 8%,请查看前 10 名

元素 计数
html 782,613
body 31,256
a 17,833
div 7,364
meta 1,104
ul 905
li 789
nav 768
span 431
article 263

noscript

HTML noscript 元素定义了一部分标记,该标记充当对禁用客户端脚本的用户或浏览器不支持客户端脚本的用户提供的备用内容。 客户端脚本语言通常是 JavaScript。

我们在 Google 前 20 名结果的 800 万个页面中发现了 3,536,247 个 noscript 元素。

AMP

Accelerated Mobile Pages (AMP) 是 Google 的一项计划,旨在加快移动网络的速度。 大多数出版商正在以 AMP 格式并行提供其内容。

为了让 Google 和其他平台知道它,您需要 将 AMP 页面和非 AMP 页面链接 起来。

在我们查看的 800 万个页面中,我们只找到了 1,944 个非 AMP 页面使用 rel=amphtml 引用了其 AMP 版本。

链接属性和值

href=”javascript:void(0)

我们找到了 2,002,716 个带有 href="javascript:void(0)"a 元素。 无论您是编码按钮还是编码链接,您都 做错了

href=”javascript:void(0)”
(a) 您使用错误的元素编码按钮
(b) 您使用错误的技术编码链接
Heydon Pickering

target=_blank 带或不带 rel=noopener

我们分析的锚点中有 43,924,869 个使用 target="_blank" 而不与 rel="noopener" 结合使用。 在这种情况下,如果缺少 rel="noopener",您将让用户面临网络钓鱼攻击的风险,这被认为是安全漏洞。

锚点/链接 计数
[target=_blank] 43,924,869
[rel=noopener] 40,756
[target=_blank][rel=noopener] 35,604

MDN:

使用 target 时,您应该考虑添加 rel=”noopener noreferrer”,以避免利用 window.opener API。

Ben HalpernMathias Bynens 也写了一些关于这个问题的好文章,常见的建议是:不要使用 target=_blank,除非您有充分的理由。

href=#top

似乎使用 #top 作为 href 值来将用户重定向到当前页面的顶部部分是一种常见的做法。 我们发现 377,486 个带有 href=#top 值的 a 元素。

lang

Léonie Watson:

HTML lang 属性用于识别网页上文本内容的语言。 此信息有助于搜索引擎返回特定语言的结果,它也用于切换语言配置文件以提供正确口音和发音的屏幕阅读器。

在我们能够查看的 8,021,323 个页面中,有 5,368,133 个页面在 html 元素上使用 lang 属性。 约 70%!

div

平均网页大约有 71 个 div。 这个数字是在 8,021,323 个页面中遇到了 576,067,185 个 div 元素后计算出来的。

header vs footer

2,358,071 个页面使用 header 元素,而 footer 被 2,363,665 个页面使用。 我们还发现,只有 2,117,448 个页面同时使用 headerfooter

元素 计数
footer 2,363,665
header 2,358,071

链接不是按钮

divspan 也不是。

元素 属性和值 计数
a class=btn 3,251,114
a class=button 2,776,660
span class=button 292,168
div class=button 278,996
span class=btn 202,054
div class=btn 131,950

作为交换,以下是原生按钮的统计数据

选择器 计数
button 4,237,743
input[type=image] 1,030,802
input[type=button] 916,268

未指定类型的按钮

说到按钮,button 元素的 默认类型submit。 确保您始终指定按钮类型,因为我们发现大约 1,336,990 个缺少 type 属性的 button 元素。 这大约占野生状态下发现的 button 总数的 31.5%。

BEM 语法

如果你是一位 CSS 爱好者,你可能听说过 BEM,它是一种流行的 HTML 类命名约定。

了解 BEM 命名风格,其中包含包含双下划线或双破折号的字符串,我们可以推测只有 20,463 个元素使用 BEM 命名风格。

Bootstrap & Font Awesome

显然,我们只找到 1,711 个页面链接到包含 bootstrap[.min.].js|.css 的 CSS 或 JavaScript 资源。此外,看起来有 379 个页面链接到包含 font-awesome[.min.].css 的 CSS 资源。

我本来预计会更多。

WordPress

在我们分析的总数中,有 1,866,241 个页面包含 <meta name="generator" content="*WordPress*">。我们只能假设还有更多使用 WordPress 的页面,但有些人选择从其来源中删除此元信息。

.clearfix VS .clear VS .cf

有很多命名风格用于这种众所周知的 CSS 工具,可以帮助清除浮动。以下是细分。

选择器 计数
.clearfix 19,573,521
.clear 10,925,887
.cf 1,102,698

Favicon

现代浏览器会自动异步获取 /favicon.ico。因此,不要手动指定其根位置,只需将其放置在那里。除非出于某些原因,你更喜欢将它放在其他位置。

看起来有 354,024 家发布商仍在 head 中链接 /favicon.ico

空元素

是否关闭 空元素,这是一个问题。虽然 HTML 两种方式都可以,但建议不要关闭空元素。至少为了简洁起见。

元素 计数
<img/> 121,463,561
<br/> 67,595,285
<link/> 61,746,984
<meta/> 46,688,572
<br> 34,492,680
<input/> 27,845,389
<img> 17,844,667
<meta> 15,133,457
<link> 11,740,839
<input> 7,231,827
<hr/> 2,610,890
<hr> 1,690,891
<param/> 1,390,339
<area/> 1,336,974
<area> 1,025,183
<param> 698,611
<source/> 435,877
<base/> 389,717
<embed/> 304,954
<source> 286,380
<wbr> 237,606
<col/> 151,757
<col> 145,434
<base> 105,688
<wbr/> 77,922
<embed> 56,610
<track/> 376
<track> 310
<keygen/> 1
<keygen>

tabindex

在劫持 Tab 顺序时,使用 tabindex 来解决一些断开的 UI 元素,通常只会 将问题推到文档级别.

常见的建议是谨慎使用它。我们确实注意到 552,109 个 HTML 元素使用 tabindex 属性来覆盖使用键盘导航时的默认设置。

缺少 alt 的图像

在分析了这组数据后,这个永恒的 SEO 和可访问性问题似乎仍然很常见。在总共 139,308,228 张图像中,几乎有一半缺少 alt 属性或使用空值。

元素 计数
img 139,308,228
img alt="*" 73,430,818
img alt="" 32,603,650
img w/ missing alt 33,273,760

自定义元素

不包括 Web Component 标记,以下是一些捏造的标记或自定义元素,与 MDN 的 HTML 元素参考 不同。

元素 计数
<o:p> 808,253
<g:plusone> 273,166
<fb:like> 111,806
<asp:label> 76,501
<inline> 53,026
<noindex> 51,604
<icon> 42,703
<block> 34,167
<red> 33,424
<ss> 27,451

我们也找到了 21,403 个 h7 元素。

A11Y

ARIA 使用的第一条规则:

如果你可以使用本机 HTML 元素 [HTML51] 或具有你所需语义和行为的属性(已内置),那么使用它,而不是重新利用一个元素并添加 ARIA 角色、状态或属性来使其可访问,请这样做。

地标角色

ARIA 地标角色 帮助使用辅助技术设备的用户浏览你的网站。

验证 文档时,你可能会看到此警告消息:“对于元素 header,banner 角色是不必要的”。这是因为像 iOS Safari 这样的浏览器目前不支持上述隐式映射,因此,目前最好继续添加这些地标角色,避免 HTML 验证警告。

关于 HTML5 隐式映射,以下是统计数据

元素 计数
<nav role=navigation> 1,144,750
<header role=banner> 675,970
<footer role=contentinfo> 613,454
<main role=main> 236,484
<article role=article> 129,845
<aside role=complementary> 105,627
<section role=region> 4,326

autoplay

视频和音频 autoplay 被认为是一种不好的做法,不仅影响可访问性,也影响可用性。

因此,不要自动播放,这将使所有用户满意。

查看来自 108,321 个 video 和 64,212 个 audio 元素的总数的调查结果。

元素 计数
<video autoplay> 31,653
<video autoplay=true> 5,601
<audio autoplay> 2,595
<audio autoplay=true> 339
<video autoplay=false> 79
<audio autoplay=false> 22

maximum-scale

Maximum-scale 定义最大缩放比例,当设置为 maximum-scale=1 时,将不允许用户缩放页面。你不应该这样做,因为缩放是一个重要的可访问性功能,很多人使用它,因为它通过满足用户的需求提供了更好的体验。

来自 HTML 5.2 编辑草案,2016 年 10 月 4 日的警告:

作者不应抑制或限制用户调整文档大小的能力,因为这会导致可访问性和可用性问题。

但是,我们确实发现了 1,047,294 个使用maximum-scale=1 的网站和 87,169 个设置了user-scalable=no 值的网站。同时,326,658 个页面同时使用maximum-scale=1user-scalable=no

role=button

button 设置role=button 是允许的,但不建议,因为button 已经具有role=button 作为默认隐式 ARIA 语义。尽管如此,我们确实发现了 26,360 个设置了role=buttonbutton 元素。

以下是其他值得注意的元素的细分,它们的默认行为被role=button 覆盖了

元素 计数
<a role=button> 577,905
<div role=button> 85,565
<span role=button> 21,466
<input role=button> 8,286

关于如何正确地使事物可点击,MDN 做了一个总结

使用按钮角色标记链接时要小心。预期按钮使用空格键触发,而预期链接使用回车键触发。换句话说,当链接用作按钮时,仅添加 role=”button” 不足以。还需要添加一个监听空格键的键事件处理程序,以保持与原生按钮的一致性。

SVG

在 HTML 中包含 SVG 有多种方法,我们对它们进行了总结,发现总共有5,610,764 个 SVG 引用

如何使用 SVG %
在 HTML 中内联 SVG 代码 97.05%
将 SVG 用作<img> 2.88%
将 SVG 用作<object> 0.05%
将 SVG 用作<embed> 0.02%
将 SVG 用作<iframe>

object、iframe 和 embed 方法的使用率低于 1%。

data-*=svg

有 17,920 个元素的data-* 属性值包含字符串svg。大多数元素是<svg><img>

前 5 个 data-* 值

  1. http://www.w3.org/2000/svg – 471
  2. hg-svg – 127
  3. svg-siteline-facebook – 114
  4. icon-facebook.svg – 95
  5. twitter.svg – 95

id*=svg

有 141,813 个元素的id 属性值包含字符串“svg”。大多数元素是<svg> 或其内部元素

前 5 个 id 值

  1. emotion-header-title-svg – 16,281
  2. cicLeftBtnSVG – 5,793
  3. cicPauseBtnSVG – 5,793
  4. cicPlayBtnSVG – 5,793
  5. cicRightBtnSVG – 5,793

class*=svg

有 329,004 个元素的 class 属性值包含字符串“svg”。大多数元素是<svg><i><img>内部元素

前 10 个 class 值

  1. sqs-svg-icon--social – 58,501
  2. nav_svg – 29,826
  3. svg – 28,604
  4. mk-svg-icon – 24,193
  5. svg-icon – 12,255
  6. icon_svg – 7,956
  7. ico ico-svg ico-40-svg – 3,980
  8. svg temp_no_id temp_no_img_src – 3,794
  9. svgIcon-use – 3,127
  10. svg temp_no_img_src – 3,017

关于上面的前十名,也许值得一提的是,sqs-svg-icon--social 是 Squarespace 网站模板使用的 (类似 BEM 的) 命名约定。

currentColor

有 868,194 个 SVG 内部元素包含值currentColor,主要用于fillstroke 属性。

前 10 个 SVG 元素

  1. <symbol> – 845,626
  2. <path> – 12,834
  3. <g> – 6,073
  4. <path> – 3,207
  5. <circle> – 1,885
  6. <svg> – 1,061
  7. <polygon> – 575
  8. <rect> – 480
  9. <line> – 412
  10. <use> – 206

SVG 作为背景图片 (旅程!)

为了找出某个元素是否使用 SVG 作为背景图片,情况要复杂一些。我们的大部分数据只使用了 HTML 文档,但我们找到了一种解决方案来获取活动样式表。

在我们能够从 6,359,031 个域中收集数据的总数量中,84.5% (5,371,806) 使用带有 CSS 背景图片的 HTML 元素,而只有 1.2% (82,008) 个域使用至少一个 SVG 背景图片。

此外,在总共 92,388,615 个带有 CSS 背景图片的 HTML 元素中,0.5% (439,447) 使用了 SVG 背景图片。

过程

我们遍历了所有 HTML 文件,并将本地/相对 CSS 文件引用转换为绝对引用,例如<link rel="stylesheet" href="style.css"> 变为<link rel="stylesheet" href="http://www.domain.com/style.css">

这花费了一些时间,因为我们对第一次运行的结果进行了一些抽样,发现结果不一致,不得不重新开始该过程。压缩文件大小为 65GB(解压缩后为 323GB),因此处理需要几天时间才能生成上述结果集并不奇怪。

尝试并放弃 PhantomJS

由于可以通过 CSS 应用背景图片,因此我们需要一些东西来呈现 DOM 并对其应用样式。我们想到了一个我们非常熟悉的工具:PhantomJS。我们对实际页面进行了一些测试,发现一切似乎运行正常。然后我们构建了我们的 Java 客户端来与 PhantomJS webserver 交互:启动、打开页面、提取输出、处理响应、保存结果,然后清理,但在尝试在一台机器上使用和扩展呈现过程时,遇到了灾难性的性能结果。

呈现一个 HTML 文件可能需要几秒钟到几分钟,我们无法知道 PhantomJS 在做什么。再加上资源使用量随着 DOM 的增大而呈指数级增长,这让我们不得不放弃它,寻找其他替代方案。

使用 Selenium 运气更好

幸运的是,一位同事正在尝试在无头 Chrome 之上使用Selenium。由于他在 PhantomJS 缺乏的各个领域都获得了令人鼓舞的结果,我们考虑离开 Java 一切包办的舒适区,并在需要时将任务委托给其他工具。测试结果非常有希望 - 无头 Chrome 看起来非常适合我们的需求:超快的启动时间、很棒的渲染时间,以及对停止进程的完全控制。

Selenium web driver 实际上会关闭二进制文件,而不是我们向 PhantomJS 发送exit 命令并希望它不在 100% 负载下,因此它会实际处理它。这使我们能够单独控制每个进程,而不必每隔几分钟使用一次killall 以及在其中一个进程失控并占用 CPU 时停止所有进程。

这种方法的唯一问题是,JavaScript 无法再包含在单个独立的 JS 文件中,然后传递到 PhantomJS 可执行文件,而必须内嵌在 HTML 文件中。以下是我们使用的脚本的简化版本,它依赖于 Window.getComputedStyle() 方法。

let backgroundImages = [],
    allElem = document.querySelectorAll("*"),
    allElemLength = allElem.length;

for (let i = 0; i < allElemLength; i++) {
  let style = window.getComputedStyle(allElem[i], false),
  backgroundImage = style.backgroundImage.slice(4, -1);
  backgroundImages.push(backgroundImage);
}

保存数据将通过调用一个简单的 PHP 脚本来完成。我们进行了一些更大规模的测试来验证我们的选择,一切运行都非常完美,所以我们继续建立了一个可扩展的环境。

我们再次处理了所有 HTML 文件,并注入了上面的 JavaScript 代码段。下一个挑战是将所有内容上传到亚马逊。 S3Browser,我们使用它进行“休闲”的列出和下载/上传,似乎不够快(至少免费版本不行)。所以,我们寻找了一个替代方案,并找到了 s3-parallel-put.

我们在本地 Linux 机器上设置了它,将 SSD 移过去,然后很快上传了 65GB 的压缩文本数据。它使我们的机器和运行在它上面的本地 Jenkins 服务器瘫痪了 - 直到我们升级了旧的 Q9550 CPU :)。

问题出现在开始扩展时。我们发现,即使 Selenium 驱动程序报告页面已成功渲染,我们的单台 Web 服务器也会不堪重负,停止保存结果。这也意味着我们的许多队列消息会被浪费(被消费并从队列中删除),而不会产生任何结果。

因此,我们决定使用 Redis,建立一个更细致的系统来跟踪已处理/未处理的文件:每次我们开始处理一个文件时,我们都会将域名插入到 Redis 集合中。每次我们处理完一个文件(我们的 PHP 脚本会被调用)时,我们都会将域名插入到另一个 Redis 集合中。关键是保持这两个集合之间的差异最小(任何超过一定值的差异都意味着某些东西没有正常工作),并且如果需要,可以轻松地进行重试。

硬件设置

对于我们的硬件设置,我们首先在 10 台 Amazon c4.large 机器上运行 10 个线程 * 每台机器 1 个 Chrome 实例,这些机器由一台运行在 m3.medium 上的 Apache Web 服务器提供服务,最初它做得非常糟糕。在调整了 Apache 的设置后,我们逐渐将所有内容都扩展到了 40 台 c4.large 机器,这些机器由运行在 4 台 m3.medium 机器上的 Apache Web 服务器提供服务,它们位于负载均衡器后面。我们的 Redis 实例为所有 10 个线程 * 40 台机器 * 每 5-20 秒 3-4 个请求提供服务,它运行在 r3.large 机器上。因此,大约是 **每秒 60-320 个请求**。

在成本方面,很难给出确切的支出金额或 CPU 时间,因为我们在拥有一个完全功能化且稳定的生态系统之前遇到了许多问题。理想情况下,一台机器需要大约 45 秒来处理 100 个文件:下载、解压缩、渲染和清理。

问答/后续

为什么会有这么多 tbody 元素?

对于上述新数据,我们对 800 万份文档进行了又一次全面的扫描,还修复了一个解析清理问题,即 jsoup 解析器会自动为所有表格添加 tbody 元素。这就是一些人在评论中提出的问题的答案:“为什么会有这么多 tbody 元素?”

因此,大多数页面使用的元素数量现在是 25tbody 的统计数据现在已经减少了。

body 占 99%?

简单回顾一下:根据 规范,省略 body 是可以的:起始标签:可选,结束标签:可选。

所以,根据你的评论,最令人惊讶的结果之一是 body 元素丢失了 1%。我想我欠你一个解释,为此我进行了更深入的解析,以获得一些见解。

  • 正如 你们中的一些人已经猜到,大多数页面缺少 body 标签,因为 frameset 使用频率很高。
  • 使用 meta http-equiv="refresh" 的客户端重定向方法,后面没有 body 内容,这是另一个原因。
  • 令人失望的是,在预计在 Google 上排名靠前的页面中,有很多页面使用粗糙的 JavaScript window.location 解决方案来将人们重定向到其他域名。同样,这些页面完全没有包含 body 部分。
  • 一些标记为缺少 body 的页面完全崩溃了,例如由于 PHP 错误。一些页面省略了起始 body 标签,但没有省略结束标签。

想要更多?

你是否想查看某个元素/属性的统计数据?请在 Twitter 上联系我,或在下面留言,我们会想办法!

另外,请确保你查看了 完整统计数据