跳转到主要内容
Chang Wei's Blog昌维的博客

Article

前端开发中的placeholder与focus细节

2020年7月7日星期二 19:06Chang Wei (昌维) <changwei1006@gmail.com>zh-Hans-CN
永久链接:

前端开发中的placeholder与focus细节

placeholder

这是input和textarea标签的一个属性,用于在文本框内无任何文字时显示一个灰色的提示文字。他能够提示用户在文本框中正确输入内容。

通常这个文字的User-Agent样式(浏览器默认样式)的color属性(文字颜色)是灰色的,但是如果自己设计UI组件,通常会对字体颜色有另外一套定义方案,则这个颜色需要修改为正文字体颜色的较低一个档次(越低越偏白色),防止placeholder内容与input的value内容无法分辨,影响使用。

目前最新CSS没有将placeholder纳入标准属性,因此需要使用带有浏览器内核厂商的属性来修改该样式。

Chrome,Edge,国产浏览器极速模式等webkit内核下使用

::-webkit-input-placeholder

Firefox使用

:-moz-placeholder

请注意他们的区别,webkit不是常规的单冒号标识伪类,而是双冒号。双冒号表示这是一个“伪元素”,单冒号表示这是一个“伪类”。双冒号才是真正规范的写法。

当然从外观上来看通常没什么问题。但是如果你仔细操作,会发现Webkit内核下,placeholder内容在文本框内确实无法选中,但是如果从文本框外选择是可以被选中的,这不是一个很好的设计,例如通常情况下我们需要从网页中复制大段文字到Word或者其他文字排版工具里面,会误将这些placeholder复制过去,影响用户体验。

Input placeholder is selectable on Chrome
Input placeholder is selectable on Chrome

我们同样可以借助上面的“伪元素”::-webkit-input-placeholder 将这个feature禁用

&::-webkit-input-placeholder
  //fix a bug on webkit about placeholder can be selected
  user-select: none

相比之下Firefox则显得友好许多,默认情况下就已经禁止选中了。

Input placeholder is not selectable on Firefox
Input placeholder is not selectable on Firefox


&:focus

focus,焦点。在GUI图形用户界面中,他表示目前可以通过键盘进行交互的控件。在Windows上通常表现为一个黑色或者蓝色的实线(solid line)

Focus style on Windows 10 setting
Focus style on Windows 10 setting

Focus style on Windows 10 advanced system settings
Focus style on Windows 10 advanced system settings

而在旧版本中通常表现为一个黑色阴影或者虚线

Focus style on Windows 2008 advanced system settings
Focus style on Windows 2008 advanced system settings

细心观察的同学可能发现了在两个月前Google Chrome的更新中,将原本outline-color为蓝色的焦点样式改为了黑色。

Focus style with black outline on Chrome
Focus style with black outline on Chrome

看起来确实丑了一点。但是如果是无法使用鼠标的极端环境,或者残障人士通过语音等设备进行交互,那么这个焦点将会提供极大的帮助。例如纯键盘环境下我们可以通过Tab键进行切换控件焦点。

当然并不代表使用鼠标的情况下就不需要focus样式了,例如文本框仍然需要焦点样式,否则我们无法确认现在按下键盘之后,文字将会输入到哪。

通常在前端开发中,我们使用

:focus

这个伪类样式来实现

但是大部分情况下我们都用鼠标操作计算机,我们希望能够在鼠标操作的情况下,按钮button等控件在点击之后不显示这个focus样式,而在通过键盘Tab操作的情况下才显示。这样既尽可能保证了Accessible,又使得正常用户能够获得比较好的视觉美观效果。

这种行为我们自己给它定义一个名称叫做:启发式焦点显示

但是请注意,这个“启发式焦点显示”的行为在Chrome下很奇怪:如果你是直接使用button标签以及User-Agent样式(浏览器原生默认样式),没有对button标签的样式做任何覆盖和重写,那么上述“启发式焦点显示”的表现是默认存在的。但是如果你准备自己实现一个CSS框架中的按钮样式,例如antd的Button组件,那么你会发现这个“启发式焦点显示”的表现特性消失了。

Focus style with black outline on Chrome button with default styles
Focus style with black outline on Chrome button with default styles

上图为Chrome 83的情况,自己覆盖button标签的原生样式之后,点击按钮后会出现一个突兀的黑色outline,影响美观

因此需要你自己去实现。那么该怎么实现呢?

Selectors Level 4: The Focus-Visible Pseudo-Class

css的Selectors Level 4规范中提供了

:focus-visible

伪类替代原始的:focus伪类来解决这个问题

Focus style with black outline on Chrome button with pseudo-classes focus-visible
Focus style with black outline on Chrome button with pseudo-classes focus-visible

使用:focus-visible替代:focus,点击按钮之后没有突兀的焦点样式,保证视觉美观

:focus-visible目前在Firefox 78中是默认支持的,而在Chrome版本(2020年7月 Version 83.0.4103.116 (Official Build) (64-bit))中仍然为实验性支持功能,也就是说需要在

chrome://flags/#enable-experimental-web-platform-features

中开启才可以体验。而默认情况下这个特性是Disabled状态。所以为了使得默认情况下也能使用,需要使用WICG/focus-visible这个polyfill(兼容脚本)

WICG/focus-visible

观察如下Demo即可

源代码如下[1]

<html>
<head>
    <style>
        input, button {
            margin: 10px;
        }
 
        .focus-only:focus {
            outline: 2px solid black;
        }
 
        .focus-visible-only:focus-visible {
            outline: 4px dashed darkorange;
        }
    </style>
</head>
<body>
<input value="Default styles"/>
<button>Default styles</button>
<br/>
<input class="focus-only" value=":focus only"/>
<button class="focus-only">:focus only</button>
<br/>
<input class="focus-visible-only" value=":focus-visible only"/>
<button class="focus-visible-only">:focus-visible only</button>
</body>
</html>

效果如下

Demo focus only after click
Demo focus only after click

鼠标点击:focus only按钮时,按钮会出现一个比较明显且突兀的outline,虽然能够很明显看出当前的焦点按钮是哪个,但是却极大影响界面美观

Demo focus-visible after click
Demo focus-visible after click

鼠标点击:focus-visible only按钮之后,周边没有较为突兀的outline

Demo focus-visible after switch by Tab key
Demo focus-visible after switch by Tab key

使用键盘的Tab键切换焦点至:focus-visible only按钮之后,按钮周边仍然会出现较为明显的outline,提示用户该按钮为当前的焦点控件,意味着用户在此时按下Enter回车键等效于直接用鼠标点击该按钮

建议以后在新项目中都尽可能使用较为明显的focus样式,但是通过:focus-visible这个伪类来使得常规操作情况下不显示这个比较明显且突兀的焦点样式。

参考

[1] https://developer.mozilla.org/zh-CN/docs/Web/CSS/:focus-visible