前几天我收到了 State of HTML 2024
的调查问卷邮件,于是倒了杯水就打算把问卷填了,还在里面看到了一些没接触过的新知识,今天来分享一下整个问卷的一些内容,如果你没有收到这篇问卷,欢迎倒杯水,看看都有些什么。
传送门:https://survey.devographics.com/en-US/survey/state-of-html/2024
本篇问卷主要有以下内容:
每一个问题都有三个选项:
以及是否感兴趣和体验如何的额外选项。
推荐自己填写一遍,后续还可以收到年度邮件,甚至可以在填写的时候选择感兴趣的内容,后续会收到更新的信息。
没听说过,很感兴趣!
支持一个可选列表作为 input
输入的自动填充选项的功能,看代码:
<form action="/action_page.php" method="get">
<label for="browser">Choose your browser from the list:</label>
<input list="browsers" name="browser" id="browser">
<datalist id="browsers">
<option value="Edge">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
<input type="submit">
</form>
这个标签笔者毫无印象,但是看起来非常适合做表单中的字符串输入功能,尤其是需要提供一定的动态或静态的选项时使用。
需要注意的是,这个标签的功能和 Select
标签没有太多重合,option
提供支持嵌套文本,但是渲染需要自定义控制才好看,浏览器默认的渲染比较丑,并且如果选择了 option
,那么 input
的值也会渲染成 option
的 value
,那种后端枚举选项作为表单值的情况就不太适合了。
用过,想再次使用
大多数浏览器会根据输入框的 name
去保存一些信息(通常浏览器会弹窗一次询问用户是否保存数据),如果开发者给输入框添加了 autocomplete
属性,浏览器就会弹出对应保存的 name
的数据作为自动填充的内容。
看代码:
<input name="address_firstline" autocomplete="billing street-address" />
没听过,感兴趣
从用户的相机捕获文件(仅支持移动端浏览器):
<input type="file" accept="video/*" capture>
笔者极少做移动端的功能,对此毫无印象,不过看起来还是很实用的。
没听过,感兴趣
程序从控制端打开一个选择器(选择颜色、日期等)
<input id="dateInput" type="date">
<button onclick="dateInput.showPicker()">Select date</button>
这是 input
元素的一个方法,开发者可以获取一个 input
去调用此方法显示选择器,但是看了看兼容性:
如图所示,基本都是最近 2 年才支持的功能 ,如果你的产品用户使用一些旧的浏览器,可能需要额外的 polyfill 来支持此功能。
没听说过,没啥兴趣
这是一个允许通过 JS 更轻松地提取和操作表单数据值的 API。
let fd = new FormData(form);
let data = JSON.stringify(Object.fromEntries(fd));
自动从提供的 form
标签提取所有表单字段,创建一个对象,可以再通过 JSON
序列换转为一个对象。笔者开发表单几乎不会使用原生的 name
和 value
这样的值来控制数据,极少有使用原生 form
的功能来直接创建表单和提交数据的场景和需求。
此前不知,现在稍微了解一点也不错。
听过,感兴趣
自定义伪类和属性来控制 select
的样式:
select,
::picker(select) {
appearance: base-select;
}
默认情况下,浏览器会为 <select>
元素提供特定的外观样式,比如下拉箭头、边框等。::picker
允许开发者定制表单选择器的下拉箭头或其他类似的 UI 元素(例如日期选择器或颜色选择器),现如今组件开发大行其道,在不需要自己控制样式时,稍微了解一下即可。
听过,感兴趣
标签可以用 contenteditable
属性来允许用户直接编辑内部文本,结合 plaintext-only
则限定了输入格式为纯文本。
<h2 class="title" contenteditable="plaintext-only"></h2>
默认此属性的值为 false
,即不允许编辑。但是,也可以设置为 true
允许用户编辑,此时用户不仅可以编辑文本,也可以插入 html
元素,因此某些场景下需要限制为纯文本。
没听过,感兴趣
这是一个 2024 年才提出的新接口,EditContext
的主要目标是为富文本编辑器、代码编辑器、虚拟键盘应用程序等提供更好的输入控制和交互方式,尤其在复杂的输入场景中,能更灵活地处理光标位置、文本选区、输入模式等。
const canvas = document.createElement("canvas");
const editContext = new EditContext();
canvas.editContext = editContext;
目前依然是一个实验性功能,兼容性堪忧。不开发富文本的内容,几乎用不上。而一旦开发富文本,恭喜你进入了一个天坑。
没听说过,不感兴趣
caretPositionFromPoint
是一个实验性的 Web API,主要用于获取光标(插入符号)在页面上的精确位置。它允许开发者根据用户在页面上点击的位置(通过屏幕坐标 x
和 y
)来确定光标应该插入文本的具体位置。
这个 API 在处理文本编辑、富文本编辑器以及复杂的鼠标操作(例如点击某个位置并移动光标)时非常有用。
告辞!
听说过,感兴趣
通过对话框交互是一个常见的需求,原生的 dialog
目前已经是一个广泛支持的功能了(类似火狐、Safira已经在两年前支持此标签)。
<dialog id="confirm">
<form method="dialog">
Are you sure?
<button value="1">Yes</button>
<button value="0">No</button>
</form>
</dialog>
这个标签支持模态和非模态,也就是说开发者可以控制打开此对话框时,用户是否可以和页面其他标签交互。
总的来说,html
在进步~
用过,想再次使用
HTML 原生可以交互切换以隐藏或显示内容的公开小部件,用在一些需要控制显示和隐藏的边栏内容时很方便,我们不需要创建一些状态值去保存和控制其状态。
<details>
<summary>Details</summary>
Longer content
</details>
没听过,感兴趣
2023 年左右发布的新特性,提供一种方式允许开发者将弹出窗口和元素之间绑定,改变一直以来的弹出窗口实现方案。
<button popovertarget="foo">Toggle the popover</button>
<div id="foo" popover>Popover content</div>
但兼容性堪忧,不建议立即使用。
inert
属性
没听说过,感兴趣
inert
属性是一个于 2022 年发布的 HTML 全局属性,它可以让元素暂时失效,使其在用户界面中不可交互。设置 inert
的元素及其子元素将不会响应用户的点击、焦点、滚动等交互行为,并且不会被辅助技术(如屏幕阅读器)关注到。
也就是说,使用模态框或者某些弹窗时可以控制默认界面不受影响了,如此一来就可以解决以往需要处理的页面滚动造成的影响的需求了。
此外,也可以给某个正在加载的内容添加此属性,以免触发某些未准备好的交互逻辑。
用过,没兴趣
Clipboard API
提供一个异步读写剪贴板的接口(仅支持在安全的上下文中使用,例如 HTTPS):
navigator.clipboard
.readText()
.then(
(clipText) => (document.querySelector(".editor").innerText += clipText),
);
剪贴板管理依然推荐使用 clipboard.js
这样的库,它能解决太多兼容性问题,节省时间和精力。
用过,感兴趣
诸多网络相关的资源都可以设置懒加载状态,即仅在需要时加载某些资源。
在具有大量图片或视频、iframe 之类的页面,非常适合使用懒加载属性,让用户滚动到可见区域再加载资源。
<img src="picture.jpg" loading="lazy" />
<iframe src="supplementary.html" loading="lazy"></iframe>
通常情况下,这样的处理方案已经足够了。但是,如果想更精细控制何时加载资源,滚动距离多远时加载资源,则推荐使用 Intersection Observers
接口。
用过,感兴趣
这两个属性可以帮助浏览器在不同的宽度下选择不同的图片资源。
<img
srcset="fairy-med.jpg 480w, fairy-large.jpg 800w"
sizes="(max-width: 600px) 480px, 800px"
src="fairy-large.jpg"
alt="Elva dressed as a fairy" />
没听说过,感兴趣
link
标签支持设置 rel
提示来提升某些资源的加载权重。
<link rel="preload" href="picture.jpg" />
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
用过,感兴趣
在 html
头部的 meta
属性中添加内容安全策略,可以防止跨站脚本攻击。网站所有者可以告诉浏览器哪些资源可以被加载到其网页中,从而限制潜在的安全风险。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.example.com">
如上所示,浏览器仅加载当前域名和 https://cdn.example.com
的脚本、字体、图片、样式表网络资源。
没听过,感兴趣
fetchpriority 属性是 HTML5 引入的一个新属性,它用于告诉浏览器,在加载页面资源时,应该优先加载哪些资源。简单来说,就是给资源分配了一个优先级,让浏览器在有限的网络资源下,能够更有效地分配资源,从而提升页面的加载速度和用户体验。
<img src="logo.svg" fetchpriority="high" />
这个属性是全局属性,可以和 script
标签的 defer
或者 async
配合,同时控制资源的加载和执行时机以及资源优先级。也可以配合 link
的 rel
属性来控制资源的预先加载和空闲时预先加载未来可能用到的资源。
字体、样式表、脚本、接口数据等等,都是可以控制加载时机、优先级的。组合使用这些技巧可以让你的 web 应用的用户体验得到提升(这需要一定的经验,否则过度使用这些属性可能会导致资源浪费,影响页面加载速度)。
没听过,感兴趣
script
的 blocking="render"
是一个相对较新的 HTML 属性,主要用于控制资源加载对页面渲染的影响。当一个资源被赋予 blocking="render"
属性时,浏览器会在加载和解析该资源的过程中暂停页面的渲染。
<script blocking="render" async src="async-script.js"></script>
这个属性是为了解决某些因关键样式文件未完全加载就渲染页面,导致样式闪烁或者布局错乱的问题。
仅使用 async/defer/preload
只会控制加载资源和执行的时机,不会阻塞页面渲染。
闻所未闻,感兴趣
允许将 3D 图形内容嵌入到 HTML 中。
<model src="3d-assets/car"></model>
没有接触过此类技术和问题,大吃一惊。
没听说过,感兴趣
<video src="fun.mp4" controlslist="nodownload"></video>
视频类媒体标签,可以设置控制列表来控制是否显示默认的控件,上述代码则禁止显示下载按钮,当然也可以添加或隐藏自定义的按钮。
没听过,感兴趣
CSS Custom Highlight API 是一组 CSS 属性,它允许开发者自定义文本高亮时的外观。通过这个 API,我们可以更精细地控制文本高亮的颜色、背景、边框等样式,从而打造出更具个性化的用户界面。
// css
::highlight(my-custom-highlight) {
background-color: blue;
}
::-moz-selection { /* Firefox */
background: #ffcc00;
color: #fff;
}
// js
const parentNode = document.getElementById("foo");
const range1 = new Range();
range1.setStart(parentNode, 10);
range1.setEnd(parentNode, 20);
const highlight = new Highlight(range1);
CSS.highlights.set("my-custom-highlight", highlight);
CSS.highlights
和 Highlight
对象,它们允许更精细地控制文本的高亮显示。你可能见过使用 <span>
标签包裹文本并应用CSS类的方法,两者各有优缺点,并且这是一个较新的 API,还得考虑兼容性问题。
没听过,感兴趣
用于将 HTML 字符串解析为文档片段,然后替换 DOM 中元素的子树。
const value = "<p>This is a string of text</p>";
document.getElementById("target").setHTMLUnsafe(value);
某种意义上来说,这种方法难以维护,且容易产生 XSS
漏洞,但是在很多时候都非常有用,我们确实需要这种方式去渲染一些不安全的内容。
这个 API 是 2024 年发布的,目前兼容性堪忧,其发布是为了解决 Element.inserHTML
存在的潜在问题:丢失 Shadow DOM
:如果插入的 HTML 字符串包含 <div>
元素,这些元素的属性(如 shadowroot
)可能会被忽略或丢失。它们不会在 DOM 中被解析为 Shadow DOM,导致无法实现预期的封装和样式。
Shadow DOM
是一种将 DOM 元素封装起来的技术,它允许创建与主文档 DOM 隔离的独立 DOM 树。这样可以确保封装的元素及其样式不与页面的其他部分冲突,也不会受到外部 CSS 或 JavaScript 的影响。它是 Web 组件(Web Components)技术的重要组成部分。
使用 Shadow DOM
可以创建独立于主文档的 DOM 树的节点,其样式与外部样式表无关联,非常适合创建自定义的组件。
常见的应用场景有:Chrome 插件开发中的 Content
内容,即在页面添加插件的节点和样式,避免影响主文档,也避免被主文档的样式影响。
没听说过,不感兴趣
同样是今年发布的 API
,用于解析 HTML 字符串(可能包含声明性影子根),以创建新的 Document 实例。
没听说过,不感兴趣
这是一个较新的国际化 API
,用于根据语言的特定规则对文本分段。
听说过,感兴趣
<template>
是 HTML
中用于定义一段可重用、延迟渲染的内容的元素,通常用于 Web Component
!<template>
在 Web 组件开发中经常与 Shadow DOM 结合使用。可以将模板的内容插入到 Shadow DOM 中,实现更好的封装和样式隔离。
<template id="my-template">
<style>
.card {
background-color: #f9f9f9;
padding: 1rem;
}
</style>
<div class="card">
<h2>Title</h2>
<p>Shadow DOM content</p>
</div>
</template>
<div id="my-component"></div>
<script>
class MyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
const template = document.getElementById('my-template');
const content = template.content.cloneNode(true);
shadowRoot.appendChild(content);
}
}
customElements.define('my-component', MyComponent);
</script>
<my-component></my-component>
在流行的组件库 React/Vue/Angular
之外,原生的 Web Component
依然存在着生存空间。
原生的 Web Component
的优势在于”无框架依赖“,即可以在 React、Vue、Angular、Svelte 甚至原生 HTML 中使用,不存在依赖某个特定框架的锁定问题。
通过这个技术开发一些轻量级的库,看起来非常方便。
或许,未来是你的
。
闻所未闻,感兴趣
<sl-switch>Switch</sl-switch>
可以在原生的 HTML
中使用自己或他人定义的自定义元素。
闻所未闻,感兴趣
class MyElement extends HTMLElement { … }
customElements.define("my-element", MyElement);
闻所未闻,感兴趣
const registry = new CustomElementRegistry();
registry.define('sub-element', SubElement);
作用域自定义元素注册表(Scoped Custom Element Registries)是一个新的 Web API,用于管理和定义在特定作用域内的自定义元素注册表。它通过为不同的文档片段(例如,Shadow DOM)或组件提供独立的自定义元素注册表,解决了多个组件或微前端应用中自定义元素命名冲突的问题。
传统的自定义元素都是全局的,即通过 customElements.define()
来注册到全局注册表,如此一来即会导致命名冲突和隔离性不足的问题,在微前端架构场景下尤为明显,因此每一个 DOM
树或者 Shadow DOM
都急需自己的自定义元素注册表。
用过,感兴趣
这是一种将组件的样式和结构与外部文档隔离的方式。
class MyElement extends HTMLElement {
constructor() {
super();
// 创建一个 Shadow DOM 并附加到当前元素上
const shadowRoot = this.attachShadow({ mode: 'open' });
// 向 Shadow DOM 中添加内容
shadowRoot.innerHTML = `
<style>
p {
color: red;
}
</style>
<p>This is a shadow DOM content!</p>
`;
}
}
customElements.define('my-element', MyElement);
在这个例子中,<my-element>
内部的内容被封装在一个 Shadow DOM 中,外部页面无法直接访问或修改它的内部结构和样式。
闻所未闻,感兴趣
通过 HTML
定义 Shadow
树!
<host-element>
<template shadowrootmode="open">
<!-- Shadow content -->
</template>
</host-element>
闻所未闻,感兴趣
通过 slot="slot_name"
属性给 Web Component
设置插槽,接收外部传入且具有对应 slot
属性的内容。
看起来,Web 组件的命名插槽与Vue 插槽都是通过插槽的概念将外部内容动态插入到组件内部的指定位置,二者有类似的地方。
以下内容都是组件相关,且笔者不了解的内容:
ElementInternals
API对此不再一一介绍。
笔者糊了很多代码,但是几乎没做过无障碍的东西。
用过
诸如;<main>
, <nav>
, <aside>
, <header>
, <footer>
, <section>
这样的标签非常常见。
没听说过,感兴趣
<div role="button" tabindex="0">I’m Tabbable</div>
tabindex
属性用于指定 HTML 元素在使用 Tab 键进行页面导航时的顺序。通过设置 tabindex
属性,你可以控制元素是否可以通过 Tab 键获得焦点,以及获得焦点的顺序。
<div role="button">
: 将一个普通的 div 元素赋予了按钮的角色。这告诉屏幕阅读器和其他辅助技术,这个 div 元素应该像一个按钮一样被对待。
闻所未闻,感兴趣
焦点组是一种新的Web平台功能,允许开发者更好地控制键盘导航和焦点行为。
<div focusgroup="wrap horizontal">
<!-- child elements -->
</div>
闻所未闻,感兴趣
<search>
是 2023 年发布的一个通用的搜索标签,语义上将元素内容的用途标识为具有搜索或过滤功能。
<search>
<form action="search.php">
<label>Find: <input name="q" type="search"></label>
<button>Go!</button>
</form>
</search>
无障碍是一个好的产品应该关注的话题,很遗憾我没有这样的经历。
闻所未闻,感兴趣
文件系统访问 API 可以访问用户本地设备上的文件和目录。
const handle = await window.showSaveFilePicker(opts);
此特性仅支持在某些安全的上下文中使用,例如 HTTPS
和 web workers
。
访问本地设备的文件系统一直是热门话题,或许浏览器会逐步开放这部分的功能。
闻所未闻,感兴趣
这个 API
可以为应用设置数字徽章,简单说就是类似 PWA
或者 Electron
这样的场景下,可以通过这个 API
设置徽章通知。
我找到一篇文章介绍:快速了解navigator API setAppBadge在很多客户端应用程序中,一般会通过应用图标的角标来显示当前消息 - 掘金
navigator.setAppBadge(unreadCount)
还是非常实用的,也许未来我会用到。
闻所未闻,感兴趣
打开一个分享窗口,支持通过各种程序分享当前的应用。
navigator.share(shareData)
我记得 vueuse
提供了一个钩子来创建快速分享的方案,或许用的就是这个 API
!
以下都是 PWA
相关的内容:
PWA
控制它们的启动方式。PWA
将自身注册为某些文件类型的处理程序。PWA
在标题栏区域显示自定义内容,其控件成为覆盖层!太好了,就需要这个!PWA
的打包、权限和签名更新。PWA 绝对值得投入一些精力!
以下是一些工具提问,笔者接触过的不多,顺便稍微发出来看看:
这篇分享到此为止了,我大概花了两小时时间写这篇内容,边写边查相关的知识点,或许未来会在某个场景下想到这部分内容。
先这样,👋🏻