打印

SD2021: 各浏览器对元素在没有设置 tabindex 属性时触发 onfocus 事件以及通过其 focus() 方法获得焦点的情况有差异

作者:陆远

标准参考

根据 W3C HTML4.01 规范中的描述,onfocus 是 HTML 中的标准事件,它在元素通过鼠标或者键盘 TAB 导航获得焦点时触发,一般应用在 A、AREA、LABEL、INPUT、SELECT、TEXTAREA、BUTTON 元素上。此事件不冒泡。

A、AREA、BUTTON、INPUT、OBJECT、SELECT 与 TEXTAREA 元素支持 tabindex 属性,这个属性指定了当前元素在当前文档中的 TAB 导航的位置,取值为 0 到 32767 的整数。

根据 W3C DOM Level 2 (HTML) 规范中的描述,HTMLSelectElement、HTMLInputElement、HTMLTextAreaElement、HTMLAnchorElement 这几个接口(对应 HTML 标签为 SELECT、INPUT、TEXTAREA、A)存在 focus() 方法,此方法可以使当前元素获得键盘焦点。

关于 focus 的更多资料,请参见 HTML4.01 规范 18.2.3 Intrinsic events、DOM Level 2 (HTML) 规范 1.6.5. Object definitions、DOM Level 2 (Event) 规范 1.6.5. HTML event types 中的内容。

关于 tabindex 属性的更多资料,请参见 HTML4.01 规范 17.11.1 Tabbing navigation 中的内容。

问题描述

各浏览器中,原生可以触发 onfocus 事件以及通过其 focus() 方法获得焦点的元素不相同,而在元素设置了 tabindex 属性后焦点获取情况也不相同。
在 IE 中,DIV 和 SPAN 元素若在当前的 IE 中触发了 hasLayout 则也可以触发 onfocus 事件以及通过其 focus() 方法获得焦点。

造成的影响

这个问题可能造成某些元素在某些浏览器中可以获得焦点,而在其他浏览器中没有任何反应。

受影响的浏览器

所有浏览器  

问题分析

由于相关的测试代码较多,故不在页面上展示,具体代码请参见页面底部测试页面部分。

对于常见 HTML 元素的测试,分别测试出:

  1. 在缺省状态(原生)下可以通过 focus() 方法使其获得焦点的元素——focus_native.html onfocus_native.html
  2. 在 IE 中触发了 hasLayout 特性后可以通过 focus() 方法使其获得焦点的元素——focus_hasLayout.html onfocus_hasLayout.html
  3. 查看元素在设置了 tabindex 属性后可以通过 focus() 方法使其获得焦点的元素——focus_tabindex.html onfocus_tabindex.html
  4. 查看元素在设置了 tabindex 属性后也不能通过 focus() 方法使其获得焦点的元素——focus_cannotFocus.html onfocus_cannotFocus.html

对于 focus() 方法的结果为:

focus() 方法检测
  IE6 IE7 IE8(Q) IE8(S) Fireofox Chrome Safari Opera
A AREA BUTTON INPUT SELECT TEXTAREA 原生 原生 原生 原生 原生 原生
BR COL COLGROUP MAP 不能 不能 tabindex 不能 不能 不能
CAPTION FIELDSET TABLE TD 原生 原生 tabindex tabindex tabindex tabindex
CODE 不能 不能 tabindex tabindex tabindex tabindex
DIV SPAN hasLayout hasLayout tabindex tabindex tabindex tabindex
IFRAME 原生 原生 不能 不能 不能 不能
LABEL tabindex tabindex 原生 原生 原生 tabindex
LEGEND tabindex tabindex 原生 tabindex tabindex tabindex
OBJECT EMBED 原生 原生 原生 不能 不能 tabindex
TBODY TFOOT THEAD tabindex 不能 tabindex tabindex tabindex tabindex
其他 HTML 元素1 tabindex tabindex tabindex tabindex tabindex tabindex

注 1:这些 HTML 元素包括:ABBR ACRONYM ADDRESS B BDO BIG BLOCKQUOTE CENTER CITE DD DEL DIR DFN DL DT EM FONT FORM H1 H2 H3 H4 H5 H6 I INS IMG INS KBD LI MENU OL P PRE Q S SAMP SMALL STRIKE STRONG SUB SUP TH TR TT U UL VAR。

对于 onfocus 事件的结果为:

onfocus 事件检测
  IE6 IE7 IE8 Firefox Chrome Safari Opera
A AREA BUTTON INPUT SELECT TEXTAREA 原生 原生 原生 原生 原生
BR CODE COL COLGROUP MAP 不能 tabindex tabindex tabindex tabindex
CAPTION FIELDSET TABLE TD 原生 tabindex tabindex tabindex tabindex
DIV SPAN hasLayout tabindex tabindex tabindex tabindex
IFRAME 原生 不能 原生 原生 不能
LABEL tabindex 不能 不能 不能 tabindex
OBJECT EMBED 原生 原生 tabindex tabindex 不能
其他 HTML 元素1 tabindex tabindex tabindex tabindex tabindex

注 1:这些 HTML 元素包括:ABBR ACRONYM ADDRESS B BDO BIG BLOCKQUOTE CENTER CITE DD DEL DIR DFN DL DT EM FONT FORM H1 H2 H3 H4 H5 H6 HR I IMG INS KBD LEGEND LI MENU OL P PRE Q S SAMP SMALL STRIKE STRONG SUB SUP TBODY TFOOT TH THEAD TR TT U UL VAR。

可以看到各浏览器对于 A AREA BUTTON INPUT SELECT TEXTAREA 这几个元素默认即可触发 onfocus 事件以及通过其 focus() 方法获得焦点。而对其他元素则体现出了差异。

需要注意的是,DIV 和 SPAN 元素在 IE 中若触发了 hasLayout1 特性之后即可通过 focus() 方法获得焦点,且触发 onfocus 事件。

虽然 W3C 规定只有 A AREA BUTTON INPUT OBJECT SELECT TEXTAREA 元素支持 tabindex 属性,但是在各浏览器中其他大部分元素在设置了 tabindex 属性后即可通过 focus() 方法获得焦点,且触发 onfocus 事件。

注 1:这里的触发 hasLayout 是指使得当前版本 IE 中元素的 currentStyle 对象中 hasLayout 属性为 true。

解决方案

对于一般常见的可视元素,若需要元素可触发 onfocus 事件以及通过其 focus() 方法获得焦点,则应为其设置 tabindex 属性。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.8
Chrome 6.0.490.1 dev
Safari 5.0.1
Opera 10.61
测试页面: focus_native.html
focus_hasLayout.html
focus_tabindex.html
focus_cannotFocus.html
onfocus_native.html
onfocus_hasLayout.html
onfocus_tabindex.html
onfocus_cannotFocus.html
本文更新时间: 2010-08-17

关键字

focus hasLayout tabindex onfocus 焦点