大家好呀,我是前端创可贴。
上一章我们一起学习了关于用户交互的第一部分,学习到了很多浏览器需要实现的很多底层规范,掌握了如何更好的与用户交互,这部分内容还是非常重要的,这一章我们再一起来学习相关内容的第二部分。
聚焦
HTML 用户界面通常由多个可交互部件组成,例如表单控件、可滚动区域、链接、对话框、浏览器标签页等,这些部件形成了一个层次结构,其中一些部件(例如浏览器标签页和对话框)包含了其他部件(例如链接和表单控件)。
当使用键盘与界面交互时,键盘输入会从操作系统传递到可交互部件的层次结构中,最终传递给被聚焦的部件。
举个例子,当前页面中包含了一些文本控件和链接,并且当前正在显示一个模态对话框,对话框里面包含一个文本控件和一个按钮。在这种情况下,可聚焦部件的层次结构为:
- 浏览器窗口:作为最高级别的父级元素,它包含多个子元素,其中之一是当前打开的浏览器标签页。
- 浏览器标签页:它包含了页面中的各种子元素,包括页面上的链接、文本控件,以及当前显示的模态对话框。
- 模态对话框:这是标签页中的一个子元素。对话框本身包含了它自己的子元素,即文本控件和按钮。
如果被聚焦的部件是对话框中的文本控件,键盘输入将会按照以下顺序传递:
- 首先,从图形操作系统传递到 ① Web 浏览器;
- 然后传递到 ② 标签页;
- 接着传递到 ③ 模态框;
- 最后传递到 ④ 文本控件。
虽然键盘输入会按照层次结构的顺序进行传递,但是键盘事件总是针对当前被聚焦的元素进行处理,例如上述的例子,聚焦输入框后进行键盘输入,只有输入框会触发键盘相关事件,外面的模态框是不会触发的。
数据模型
当浏览器窗口能够接收来自操作系统的键盘输入时,则该窗口拥有系统焦点(system focus)。说白了,就是当用户点击某个浏览器标签页时,它可以接收用户的键盘输入并将这些输入传递到内部的子元素,如果用户切换到其他程序,此时用户按下键盘,浏览器标签页理所当然的并不会接收这些输入。
当浏览器窗口的系统可见性状态为 visible,并且它本身具有系统焦点,或窗口里的可交互部件能够接收来自操作系统的键盘输入时,则该窗口拥有用户注意(user attention)。说白了,就是用户当前正在关注该浏览器窗口或标签页,而不是其他窗口或程序。
当浏览器窗口失焦时,用户注意也会随之丢失,而系统焦点也可能被转移到浏览器窗口内的其他系统部件(例如地址栏)。
可聚焦区域(focusable area),是指能够进一步成为键盘输入目标的界面区域,也就是能够接收焦点的元素或区域。可聚焦区域可以是元素、元素的一部分,或由浏览器管理的其他区域。例如表单控件、链接等。
每个可聚焦区域都有一个 DOM 锚点(DOM anchor),它是表示该可聚焦区域在 DOM 中位置的一个节点对象,也就是说在 DOM 中一定会有一个节点对象对应着该可聚焦区域。当可聚焦区域本身就是一个节点(Node)时,它本身就是其 DOM 锚点。当没有其他 DOM 对象表示该可聚焦区域时,DOM 锚点可以在某些 API 中用作可聚焦区域的替代。
可聚焦区域有两种特殊类型的聚焦状态:
1. 如果某个可聚焦区域包含在其文档的顺序聚焦导航顺序(sequential focus navigation order,定义了文档中可聚焦区域的相对顺序)中,并且浏览器判断该区域是可以顺序聚焦的,则称其为顺序可聚焦(sequentially focusable)。
a. 顺序可聚焦表示该元素可以通过键盘的顺序导航(按下 Tab 键进入下一个,按下 Shift + Tab 键进入上一个)进入焦点序列中,即用户在按下 Tab 键时,焦点会依次移动到这些顺序可聚焦的元素上。
b. 如果某可聚焦区域不在文档的顺序聚焦导航顺序中,就无法通过 Tab 键聚焦在该区域。当 tabindex
属性值(后文会详细介绍该属性,这里先混个脸熟)为负数、元素被 disabled 禁用、元素被样式隐藏,或者元素被设置 inert 属性等,元素就不在顺序聚焦导航顺序中。
2. 如果浏览器判断某个可聚焦区域是可以通过点击聚焦的,则称其为点击可聚焦(click focusable)。浏览器将具有非空 tabindex
值的可聚焦区域视为点击可聚焦区域。
a. 点击可聚焦表示该元素能够通过用户的点击操作获得焦点。当用户使用鼠标点击这些元素时,它们将成为当前焦点元素。如果某些元素不在顺序聚焦导航中,就不能通过 Tab 键聚焦在这些元素上,但是仍然可以通过点击聚焦。
可聚焦(Focusable)是指元素是否能够通过编程的方式获得焦点,例如通过 focus()
方法或 autofocus
属性。而顺序可聚焦和点击可聚焦则分别决定了浏览器在响应用户交互时的行为,前者是指在顺序聚焦导航(如按 Tab 键)时的响应,后者是指激活行为(如点击,上一章介绍过)时的响应。
即使某个元素是可聚焦的,并且包含在文档的顺序聚焦导航顺序中,浏览器仍然可能根据用户的偏好判断该元素不是顺序可聚焦的。例如,在 macOS 系统中,用户可以将浏览器设置为跳过非表单控件元素,或者在只使用 Tab 键(而不是 Option + Tab 键)进行顺序聚焦导航时跳过链接。
类似地,即使某个元素是可聚焦的,浏览器也可能判断该元素不是点击可聚焦的。例如,在某些用户代理中,点击非可编辑的表单控件不会使其获得焦点,也就是说,用户代理已判断此类控件不是点击可聚焦的。
因此,一个元素可以是可聚焦的,但既不是顺序可聚焦的,也不是点击可聚焦的。例如,在某些用户代理中,具有负整数 tabindex
值的非可编辑表单控件无法通过 Tab 键或者点击获取焦点,只能通过编程 API(如 focus()
方法)进行聚焦。
大家注意,聚焦并不是激活行为(激活行为在上一章也有介绍),也就是说,调用元素的 click()
方法不会导致该元素获得焦点。大家可以试一下,通过 click 方法触发某元素的点击事件,打印 document.activeElement
(当前被聚焦的元素,下面小节会介绍)并不是该元素。
tabindex 属性
通过 tabindex
属性我们可以将元素及其 DOM 锚点区域设定为可聚焦区域,允许或阻止它们成为顺序可聚焦区域,并确定它们在顺序聚焦导航中的相对顺序。
例如 div 元素内容为纯文本,默认情况下通过 Tab 键是聚焦不了该 div 元素的,但是给 div 元素加上有效的 tabindex 属性后,即可通过 Tab 键聚焦。
<div tabindex="0">前端创可贴</div>
tab index
这个名称来源于通常使用 Tab 键来导航可聚焦元素的习惯。术语tabbing
指的是通过 Tab 键在顺序聚焦的区域中向前移动。
大家可以看看淘宝、京东这些网站,他们在登录页都用到了 tabindex 属性:
如果指定了 tabindex 属性,那么它的值必须是一个有效的整数。正整数和 0 表示该元素在顺序聚焦导航中的相对位置,而负整数表示该元素在顺序聚焦中不可聚焦。
我们在使用 tabindex 属性时要小心,尤其是当值不是 0 或 -1 时,此时想要正确地使用这些值会相对有些复杂。
取值
tabindex 属性值可以是:
- 省略(或非整数值)
由浏览器决定该元素是否可聚焦,如果可聚焦,则决定它是顺序可聚焦、点击可聚焦还是两者都有。
- −1(或其他负整数值)
使元素可聚焦,并表示希望该元素为点击可聚焦,而非顺序可聚焦,也就是无法通过 Tab 键聚焦,所以负整数值只是让元素变为非顺序可聚焦,但是仍然会让元素变为可聚焦(可通过 focus()
等 API 聚焦)。但是浏览器可能会忽略关于点击和顺序可聚焦的期望,例如,根据平台约定或针对仅使用键盘的用户,会对特定元素类型进行特殊处理。
- 0
使元素可聚焦,并表示希望该元素既可点击聚焦又可顺序聚焦。同样的,浏览器可能会忽略关于点击和顺序可聚焦的期望。
- 正整数值
行为与 0 相同,但此外会创建相对顺序,具有更大 tabindex 属性值的元素将排在更后面,也就是说,按下 Tab 键,先聚焦 tabindex 值小的元素,后聚焦值大的元素。
大家注意,tabindex
属性不能用于让元素变为不可聚焦,最多让元素变为非顺序可聚焦而已。唯一的方法是使元素变为 disabled 或使其变为 inert 状态。
焦点管理 API
document.activeElement
用于获取当前文档中被聚焦的最深层次元素。如果某个元素处于聚焦状态(即用户的输入行为,例如键盘事件,会被该元素捕获),则 activeElement 将返回该元素。
但是,如果焦点在一个嵌套的 iframe
中的可聚焦元素上,那么 document.activeElement
会返回该 iframe
元素,而不会直接返回 iframe
内部的被聚焦元素。要获取 iframe
内部的具体被聚焦元素,需要使用 iframe.contentDocument.activeElement
。
<body>
<h1>前端创可贴</h1>
<input type="text">
<iframe srcdoc="
<div>
<h2>iframe 内容</h2>
<input type='text'>
</div>"
frameborder="0"></iframe>
</body>
document.hasFocus()
用于检测当前文档是否具有焦点,即是否有键盘事件被路由到该文档中。
如果当前文档(或嵌套在当前文档中的另一个文档,例如 iframe)具有焦点,则 document.hasFocus()
返回 true
,否则返回 false
。
通常用于在页面与其他浏览器标签页之间切换时判断当前文档的焦点状态。
if (document.hasFocus()) {
console.log("当前文档具有焦点。");
} else {
console.log("当前文档没有焦点。");
}
window.focus()
该方法用于将焦点移动到当前窗口。
在早期浏览器中,新打开的页面可以通过 opener
属性执行 focus 方法切换焦点回到原始页面 ,例如页面 A 新打开一个页面 B(同源或不同源均可),页面 B 通过 window.opener.focus()
即可聚焦到页面 A,window.opener 的介绍可见前面的这章内容。但是在现代浏览器中已经无效了,由于安全性和用户体验的原因,浏览器已经限制了这种跨窗口的焦点操作 。
不过需要注意,某些浏览器可能会限制 window.focus()
的使用,尤其是在没有用户操作(如点击或按键)触发时,也就是没有触发上一章我们学习过的用户激活。
element.focus([ { preventScroll: true } ])
将焦点移动到目标元素上。
默认情况下,如果目标元素当前不在视图中,调用 focus()
方法会将目标元素滚动到视图内。
通过 { preventScroll: true }
选项可以阻止这种自动滚动行为,尤其是在希望通过 CSS 或 JavaScript 手动控制滚动位置时,这个选项非常有用。
element.blur()
该方法用于移除目标元素的焦点,并将焦点移动到视口中。但是不建议通过使用该方法来聚焦视口,而是使用 html 元素的 focus 方法。
修改焦点环样式
如果觉得默认的焦点环(使用 Tab 键聚焦元素时,元素周边会有一圈颜色用来标识当前元素被聚焦)很难看,不要使用 blur()
方法来隐藏焦点环,可以使用 CSS 的 :focus-visible
伪类覆盖 outline 属性。
<head>
<style>
div:focus-visible {
outline: 2px solid red;
border-radius: 4px;
}
</style>
</head>
<body>
<div tabindex="0">前端创可贴</div>
</body>
autofocus 属性
通过 autofocus
属性在页面加载时,自动聚焦到指定的元素上,从而用户可以直接开始输入而无需手动点击以获得焦点。该属性主要用于优化用户体验,例如在登录页中自动聚焦到用户名输入框,用户无需额外操作即可开始输入。
如果设置了 autofocus 属性的元素位于 dialog 元素或者设置了 popover 属性元素的内部,则该元素会在 dialog 元素或者 popover 属性元素显示时才会自动获得焦点。这种行为可以理解为 autofocus 的作用范围被延迟到了 dialog 或 popover 的显示时机,而不是在页面加载时立即生效。
<body>
<h1>前端创可贴</h1>
<dialog id="dialog">
<input type="text" autofocus />
</dialog>
<button id="btn">打开 dialog</button>
<script>
btn.addEventListener("click", () => {
dialog.showModal();
});
</script>
</body>
autofocus
是一个布尔属性。该属性不仅可以应用在表单元素上,还可以应用在普通元素上,只不过普通元素默认情况下该属性不会生效。但是如果给普通元素加上 tabindex
属性或者 contenteditable
(该属性在后面小节会详细介绍~) 属性,就可以生效了。
autofocus 会受到其祖先元素上下文的影响,涉及到最近祖先 autofocus
作用域根元素(nearest ancestor autofocus scoping root element)。
要找到某个元素的最近祖先 autofocus
作用域根元素,遵循以下规则:
1. 检查自身是否为 dialog
元素
a. 如果当前元素 element
是一个 dialog
元素,则该元素本身就是最近的 autofocus
作用域根元素,直接返回当前元素。
2. 检查 popover
属性是否激活
a. 如果当前元素的 popover
处于显示状态,则当前元素也是 autofocus
作用域根元素。
3. 遍历祖先元素
a. 从当前元素开始向上遍历它的祖先元素,直到没有父元素为止。
b. 每遍历一个元素,都需要检查该元素是否是 dialog
元素,或者其 popover
属性是否激活。
c. 如果遍历完所有祖先元素,仍未找到 dialog 或 popover 激活的元素,则最终返回当前元素的最顶层祖先元素
同一最近祖先autofocus
作用域根元素中不能同时存在两个具有 autofocus
属性的元素,否则可能会导致焦点行为不确定。所以页面可以设置多个 autofocus 元素,但是必须要保障他们的最近祖先 autofocus 作用域根元素不同。
失效场景
大家考虑下这么一种情况,用户正在别的输入框输入内容,此时我们向 DOM 树中插入一个含有 autofocus 属性的节点,此时会发生什么呢??大家要记住,用户的交互永远是最高优先级,所以浏览器并不会将用户正在交互的输入框失焦,焦点并不会改变。
如果当前文档不是活跃状态,例如窗口最小化了,aotofocus 当然不会生效。还有当元素是 disabled 状态、inert 状态或者被样式隐藏,也都会不生效。
还有一种情况是权限不足也会导致 autofocus 不生效,例如设置了 sandbox 属性的 iframe 元素,并且没有设置 autofocus 相关的权限,那么 iframe 里面的 autofocus 元素并不会自动聚焦。
<!-- 没有 autofocus 相关权限,输入框不会自动聚焦 -->
<iframe sandbox="" srcdoc="<input type='text' autofocus>" frameborder="0"></iframe>
<!-- 有了足够的权限,输入框会自动聚焦 -->
<iframe sandbox="allow-scripts allow-same-origin" srcdoc="<input type='text' autofocus>" frameborder="0"></iframe>
分配键盘快捷键
创可贴我是一个很爱用键盘快捷键的人,能用快捷键的我绝不用鼠标,所以咱们一起来看看,如何给我们的页面创建自定义快捷键呢?
通过 accesskey
属性可以为可激活或可聚焦的元素指定一个键盘组合快捷键,以便用户能够快速激活或聚焦这些元素。具体的键盘组合是由浏览器决定的,并且会基于用户的键盘布局、平台上已有的键盘快捷方式以及页面中其他已指定的 accesskey 属性来进行设定。
accesskey
属性的值是一个或多个单个字符(如字母或数字),每个字符代表一个快捷键组合。多个字符用空格分隔,例如:accesskey="s d 1"
。
accesskey
属性值中的字符仅仅是提供给浏览器的参考信息,而浏览器会根据当前上下文及平台规则来决定具体使用的键盘组合。不同平台(如 Windows、macOS、Linux)对键盘组合的处理方式可能不同,因此同一个 accesskey 属性值在不同平台上的表现可能不同。
既然我们指定了 accesskey 还需要浏览器根据不同平台等来决定具体的快捷键组合,那么我们该怎么知道快捷键组合到底是什么呢?这时候就需要用到 accessKeyLabel
属性了,该属性返回由浏览器实际分配给元素的键盘组合(包括修饰键如 Alt、Ctrl 等)的字符串表示形式。例如某个元素的 accesskey 属性值为 "s", 而实际分配的快捷键组合为 Alt + Shift + S
,则 accessKeyLabel 会返回 "Alt + Shift + S"。
const element = document.querySelector('button[accesskey="s"]');
console.log(element.accessKeyLabel);
不过 accessKeyLabel 属性的兼容性很差,Chrome、Edge 等浏览器完全不支持,Safari、Firefox 等浏览器是支持的,所以如果你用的是 Chrome,就可以用例如 Firefox 打开页面后,获取一下该属性。一般来说,macOS 系统的快捷键是 Ctrl + Option + 自定义按键
,Windows 系统是 Alt + Shift + 自定义按键
。
<h1>前端创可贴</h1>
<input type="text" accesskey="s">
大家在设计 accesskey 时,要尽量避免使用已经在平台中占用的常用快捷键(如 Alt + F4
、Ctrl + C
等),以防止造成冲突或意外行为。
建议大家不要为每个页面元素都指定 accesskey,而是优先为常用功能(如提交、导航、帮助)分配快捷键,以减少用户混淆。
扩展:快捷键的最常见实现方式
大家可以看到,其实 accesskey 属性的功能还是比较基础的,我们平时访问一些网站时,经常会看到通过 Command + K
或者 Ctrl + K
这样的组合快捷键可以打开搜索框等,这些组合键可以不那么依托于平台和浏览器,可以做到组合键较为简短(按 Ctrl + Option + 按键
或者 Alt + Shift + 按键
真的很累啊!!!),并且可以通过 Javascript 实现更加复杂的功能。
所以一般我们会通过自定义键盘事件,监听键盘的输入,匹配到了指定的按键后执行自定义的逻辑即可,例如打开搜索框。
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
position: absolute;
top: 100px;
left: 50px;
padding: 10px;
border: 1px solid #ccc;
background: white;
}
</style>
</head>
<body>
<h1>前端创可贴</h1>
<div id="search" style="display: none">
<input type="text" placeholder="搜索" />
</div>
<script>
document.addEventListener("keydown", event => {
// metaKey 代表 Command,ctrlKey 代表 Ctrl
if ((event.metaKey || event.ctrlKey) && event.key === "k") {
event.preventDefault();
if (search.style.display === "none") {
search.style.display = "block";
} else {
search.style.display = "none";
}
}
});
</script>
</body>
通过 keydown 事件监听键盘输入,并且识别组合键是否为指定的 Command + k
或者 Ctrl + k
。
编辑
contenteditable 属性
contenteditable
属性用于表明某元素是可编辑的,效果类似于输入框,例如给一个 div 元素添加 contenteditable 属性后,该元素便添加到了顺序聚焦导航顺序中,即可以通过 Tab 键聚焦该元素,前文所提到的 autofocus 属性也可以生效了。该元素就会类似于一个输入框一样可以编辑内容。
contenteditable 属性值可以是:
true
或者空字符串:支持富文本格式,例如选中一段文字后按下Ctrl + B
或者Command + B
会加粗,这点和 Input 输入框就不一样了,Input 输入框只支持纯文本。这种情况下就形成了一个天然的简易的富文本编辑器,功能还是比较强大的,像是一个简易的 Word 文档。
false:
不支持编辑;
plaintext-only:
只允许编辑纯文本内容而不支持富文本格式,选中一段文字后按下Ctrl + B
不会生效。
该属性是可继承属性,如果元素没有指定该属性,或者属性值无效,则会继承父元素的 contenteditable 属性值。
contenteditable 属性可以让普通元素变为可编辑,因此加入了顺序聚焦导航顺序中,即可以通过 Tab 键聚焦该元素,但是如果存在嵌套的情况,即父元素和子元素都是设置了 contenteditable 属性的普通元素,子元素默认情况下是不会加入顺序聚焦导航顺序的,也就是说无法通过 Tab 键聚焦子元素。可以给嵌套的 contenteditable 子元素加上 tabindex 属性,就可以解决该问题。
通过 Javascript 可以获取 contenteditable 属性值:
element.contentEditable; //返回 true、false、plaintext-only 或者 inherit,可以赋值新值改变属性值,如果新值无效会抛出 SyntaxError 异常
element.isContentEditable; // 如果元素可编辑,返回 true,否则返回 false
简易的富文本编辑器
contenteditable 属性是个非常有意思并且很强大的功能,它能轻松的生成一个天然的简易富文本编辑器,举个例子:
<div contenteditable>前端创可贴</div>
上述代码给 div 元素设置了 contenteditable 属性后,就会变为可编辑,当选中元素内文本并按下 Ctrl + B
或者 Command + B
后,文本会加粗,并且会自动修改相应的 HTML 代码。
可以看到,文本自动加上了 b
标签。
再例如 markdown 文件里有一段带有相应格式的文字,下图可以看到格式还是比较复杂的:
此时我从 markdown 文件复制文本内容并粘贴到设置了 contenteditable 属性的元素中:
可以看到,格式被完美的还原,并且 HTML 代码也自动带上了 CSS 样式,这可不就是纯天然的富文本编辑器嘛!
designMode
通过 document.designMode
可以设置让整个文档可编辑,上面的 contenteditable 属性是元素级别的,该属性是文档级别的。同样支持富文本格式。
document.designMode; // 如果文档是可编辑的,返回 on,否则返回 off。可以赋值新值改变属性值,让整个文档变为可编辑或不可编辑。赋值新值后,会聚焦文档并重置该文档中的已选中的区域
document.designMode = 'on';
designMode 设置为 on 之后,文档内所有元素也会同样的变为简易的富文本编辑器!
页面内编辑器的最佳实践
在使用编辑宿主(editing host,使用了如 contenteditable 、designMode 属性的普通元素从而变成可编辑)元素时,建议大家将 white-space
CSS 属性设置为 pre-wrap
,以便更好地处理编辑内容的格式和显示。
默认的 white-space 属性值为 normal
时,有以下特性:
- 所有的空白字符(包括换行)都会当成空格处理;
- 元素内首尾的空白符会直接忽略;
- 多个空格会被合并。
这些默认行为在普通的网页展示中是比较合理的,比如代码的排版不会对展示产生过多影响,但是在编辑上下文中可能会导致内容显示和实际编辑行为之间不一致。
这并不满足 WYSIWYG
(所见即所得,What You See Is What You Get) 编辑器的需求,WYSIWYG 编辑器要求用户在编辑区域内看到的内容能够精确反映 HTML 文档最终的显示效果。所以在编辑内容时,需要保留用户输入的所有空白字符,包括换行和多个连续空格。所以默认的 white-space 属性值并不能满足这个需求。所以建议大家将具有编辑功能的普通元素的 white-space
设置为 pre-wrap
。
拼写和语法检查
通过 spellcheck
属性可以让浏览器进行拼写和语法检查。大家在使用输入框的时候,输入英文时有时会看到文字下面出现了红线,这就是拼写和语法检查在起作用,默认情况下可编辑元素自动打开拼写和语法检查:
<h1>前端创可贴</h1>
<textarea></textarea>
注意,如果你的浏览器在输入上述文字后没有出现红线,说明你的浏览器可能没有开启拼写检查功能,例如 Chrome 需要在设置里开启:
浏览器在对可编辑元素的拼写和语法检查时,根据默认设置或用户偏好,浏览器会为可编辑元素设定一种拼写和语法检查的默认行为。有三种默认行为:
- true-by-default:默认情况下,元素将会进行拼写和语法检查,只要它的内容是可编辑的,并且没有通过
spellcheck
属性明确禁用拼写检查。
- false-by-default:默认情况下,元素将不会进行拼写和语法检查,除非通过
spellcheck
属性明确启用了拼写检查。
- inherit-by-default:元素的默认行为将与其父元素相同。如果该元素没有父元素,则不能应用这种默认行为。也就是说,该元素的拼写检查行为将从其祖先元素继承。
spellcheck
属性的取值可以是:
- true 或者空字符串:会进行拼写和语法检查;
- false:不会进行拼写和语法检查。
当没有设置 spellcheck 属性值或者属性值无效时,默认值都是默认状态,默认状态该元素会根据默认行为执行拼写检查,基于其父元素的 spellcheck 状态来确定。
但是大家注意,拼写和语法检查功能可能有安全风险,官方规范并没有规定如何进行拼写检查,也没有规定拼写检查的具体实现方式,所以浏览器可能会将元素的内容发送给第三方服务以获取拼写检查结果。这篇文章介绍了什么是拼写劫持(spell-jacking),以及如何防范。
所以建议大家敏感信息不要开启拼写和语法检查功能。
书写建议
通过 writingsuggestions
属性,浏览器在用户输入可编辑区域时可以提供书写建议,这些建议通常以灰色文本的形式出现在光标后方,完成用户的句子。但是大家注意,这个属性的兼容性很差,Chrome 直到 124 版本才支持。
<input type="text" writingsuggestions />
writingsuggestions
属性的值可以是:
- true 或者空字符串:开启书写建议功能;
- false:不开启书写建议功能。
元素未指定该属性值时,会继承父元素的 writingsuggestions
属性值。属性值无效时默认为 true。
自动大写
通过 autocapitalize
属性可以控制文本输入中的自动大写行为,尤其在使用虚拟键盘或语音输入等方法时非常有用。
<input type="text" autocapitalize="sentences" placeholder="请输入">
autocapitalize 属性主要影响虚拟键盘和语音输入的行为,对于物理键盘的输入行为没有影响,一般都是运用在移动端。而且在使用 URL、Email 或 Password 类型的输入元素时,autocapitalize 属性不会启用自动大写。
autocapitalize 属性值可以是:
- off:不应用自动大写,所有字母默认小写;
- none:同样表示不应用自动大写;
- on:启用自动大写,句子的第一个字母自动大写;
- sentences:同样表示句子的第一个字母自动大写;
- words:每个单词的第一个字母自动大写;
- characters:所有字母自动大写。
自动校正
自动校正(Autocorrection)是文本输入的一种辅助功能,能够在用户通过可编辑元素进行输入时自动纠正拼写错误。
<textarea autocorrect="on"></textarea>
通过 autocorrect
属性控制自动校正的行为。同样的,autocorrect 属性永远不会使类型为 URL、Email 或 Password 的输入元素启用自动校正。
autocorrect 属性值可以是:
- on 或者空字符串:开启自动校正,用户偏好设置会影响该功能;
- off:不开启自动校正。
inputmode 属性
对于移动端来说,很多场景会使用到不同的虚拟键盘类型,例如输入纯数字时会用到纯数字的虚拟键盘,如果所有场景下都使用默认的虚拟键盘,对于用户的交互体验来说并不友好,例如纯数字场景可能会做判断禁用非数字字符,但是提供给用户的虚拟键盘却又包含了非数字字符,这显然是多余的并且容易引发歧义的。
通过 inputmode
属性,我们开发者可以提示浏览器使用合适的输入模式,以便于用户根据所需输入的内容获得最佳的输入体验,特别适用于移动设备。inputmode
属性主要用于表单控件(如 input 元素)或编辑宿主中的元素(例如使用 contenteditable 属性的元素),它提供了一种方式来指定最适合用户输入内容的输入机制。
inputmode
属性是一种提示,并不能保证所有的浏览器都能完全支持该属性,所以我们在设计时最好进行一些兼容性测试。
虽然 inputmode
可以指定理想的输入模式,但是并不会限制用户使用其他输入方式。例如,设置 inputmode="numeric"
并不会强制用户只能输入数字,它只是一种提示和建议。
inputmode 的值可以是:
- none: 不展示虚拟键盘,禁用输入。适用于内容自行提供键盘控件的场景。
- text: 浏览器应显示适合文本输入的虚拟键盘,支持用户所在语言环境的字符输入。
- tel: 浏览器应显示适合输入电话号码的虚拟键盘,包括数字键 0-9、"#" 和 "*" 字符。在某些语言环境中,键盘还可能包括字母标记(例如,美国的数字键 "2" 可能还标有字母 A、B、C)。
- url: 浏览器应显示适合输入网址的虚拟键盘,包含有助于输入 URL 的特殊键,如 "/" 和 ".",以及常用字符串的快捷输入(如 "www." 或 ".com")。
- email: 浏览器应显示适合输入电子邮件地址的虚拟键盘,带有输入 "@" 和 "." 等字符的键。
- numeric: 浏览器应显示适合输入纯数字的虚拟键盘,适用于输入 PIN 码等场景。
- decimal: 浏览器应显示适合输入小数的虚拟键盘,支持输入数字和与语言环境相关的小数点符号。
- search: 浏览器应显示为搜索优化的虚拟键盘,通常包含搜索按钮或快捷方式。
当 inputmode
属性未指定或浏览器不支持其指定的状态时,浏览器会根据上下文信息来决定显示的虚拟键盘类型。例如 input
元素会使用 type
属性或 pattern
属性等上下文信息来确定应向用户展示哪种类型的虚拟键盘。
enterkeyhint 属性
对于移动端来说,回车键有时候会有一些不同的含义,它的功能可以是提交表单、发送消息、搜索等,如果所有功能的回车键都长一个样子,必然容易引发歧义,也不好设计 icon 的样式。
通过 enterkeyhint
属性,我们开发者可以自定义回车键的显示方式,以便为用户提供更合适的提示,该属性可以帮助用户更好地理解回车键的功能。
enterkeyhint 属性的值可以是:
- enter: 通常表示插入一个新行,适用于文本输入。
- done: 提示输入已经完成,通常表示不需要再输入了,并且输入法编辑器将会关闭。
- go: 表示用户完成输入后应该导航到输入目标位置,常用于跳转到链接或目标页面。
- next: 指示移动到下一个可接受文本输入的字段。
- previous: 指示移动到上一个可接受文本输入的字段。
- search: 提示用户进行搜索,显示搜索操作提示,并将输入内容用于搜索。
- send: 表示用户应该发送输入的内容到指定目标,例如发送消息或提交表单。
当 enterkeyhint 属性未指定或浏览器不支持其指定的状态时,浏览器会根据上下文信息来决定显示默认的操作标签或图标,例如使用 inputmode、type 或者 pattern 属性来选择合适的操作提示或图标显示在虚拟键盘的回车键上。
结束语
这一章我们一起学习了聚焦的相关内容,包括它的数据模型(也就是各种名词)、非常重要的 tabindex 属性、焦点管理相关的 API、如何修改焦点环样式,以及同样很重要的 autofocus 属性,学习了以后才发现原来一个看起来简简单单的聚焦,原来这么多东西~
然后学习了如何给元素分配自定义键盘快捷键,大家就可以给你们的网站加一些自定义快捷键,得瑟一下~还扩展了一下我们平时更为常用的快捷键实现方式。
最后学习了编辑的相关内容,内容有点多,而且都还是很重要的内容,毕竟我们经常会在页面里嵌入很多可编辑元素,而且还有很多 PC 端和移动端相关的编辑方面的优化,比如拼写和语法检查、自动大写、自动校正等等,这些优化可以让用户在输入时大大提高输入的效率,减少打错字的次数。
虽然用户交互方面的优化很多时候并不是我们开发的重点,但是如果对于交互方面做到了足够好的优化的话,可以让用户在访问网站时感到非常丝滑,可以提高用户的留存率。
那么这一章的介绍就结束了,咱们下一章再见啦。
欢迎关注我的公众号,前端创可贴。