This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 23854 - Please remove *:focus rule from html.css
Summary: Please remove *:focus rule from html.css
Status: RESOLVED INVALID
Alias: None
Product: WHATWG
Classification: Unclassified
Component: HTML (show other bugs)
Version: unspecified
Hardware: Other other
: P3 normal
Target Milestone: Unsorted
Assignee: Ian 'Hixie' Hickson
QA Contact: contributor
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard: blocked awaiting further details from...
Keywords:
Depends on:
Blocks:
 
Reported: 2013-11-19 00:11 UTC by contributor
Modified: 2014-04-09 22:09 UTC (History)
5 users (show)

See Also:


Attachments

Description contributor 2013-11-19 00:11:37 UTC
Specification: http://www.whatwg.org/specs/web-apps/current-work/
Multipage: http://www.whatwg.org/C#phrasing-content-1
Complete: http://www.whatwg.org/c#phrasing-content-1
Referrer: 

Comment:
Please remove *:focus rule from html.css

Posted from: 2620:0:1002:1005:ae16:2dff:fe07:523b
User agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1707.0 Safari/537.36
Comment 1 Eric Seidel 2013-11-19 00:19:45 UTC
Currently, a naive implementation of :focus would require a browser to invalidate style on all elements every time the focus changes as it potentially could draw an outline.

We could detect the special case of :focus being defined by html.css (html5 spec) and instead do something smarter.

But we could also just fix the spec to be more specific, and have this selector only match focusable elements:

[tabindex]:focus, a[href]:focus, link[href]:focus, button:focus, input[type!=hidden]:focus, select:focus, textarea:focus, menuitem:focus, [dragable]:focus, td:focus, iframe:focus, frameset:focus {
  outline: auto;
}

Yeah, that's much more verbose.  But it's also much clearer/faster to implement.
Comment 2 Eric Seidel 2013-11-19 00:26:36 UTC
The current spec defeats an optimization I added to avoid these needless recalcs in crbug.com/315923.  Maybe other engines are smarter, but currently WebKit/Blink recalc style on the entire document every time you you focus/blur a tab, or when changing focus within a document (and the body was the previous focused node) even though the body doesn't actually draw focus.

We have a relatively large amount of CSS insantity for :focus already in blink/webkit:
http://blink.lc/blink/tree/Source/core/css/html.css#n1007
http://trac.webkit.org/browser/trunk/Source/WebCore/css/html.css#L1036
Comment 3 Ian 'Hixie' Hickson 2013-11-19 21:50:19 UTC
I don't understand. Why would you need to invalidate style on any element other than the one that used to match :focus and the one that now matches :focus?

In particular, if the rule in comment 1 would somehow invalidate fewer elements' styles than the rule in comment 0, why not just implement :focus as the equivalent of :-x-focusable:focus, where :-x-focusable matches only elements that are focusable and therefore could theoretically match :focus?
Comment 4 Simon Pieters 2013-11-19 22:41:42 UTC
I think you forgot at least [contenteditable], summary, area[href], keygen... There's also the problem that the spec allows UAs to make basically any element focusable if it should be focusable according to platform conventions.

(Is td actually focusable?)
Comment 5 Elliott Sprehn 2013-11-19 23:13:29 UTC
@hixie because if you had a:focus span { } then the span matches different rules now too, if you had a:focus + span { }. So you need to invalidate style on the descendants and the siblings (and their descendants) to deal with the rule changes.
Comment 6 Ian 'Hixie' Hickson 2013-11-22 18:17:27 UTC
I don't understand how that affects this discussion.

The selector here is just "*:focus".

Even if the selector had combinators, you don't need to invalidate anything but the descendants and following siblings and their descendants (as relevant to the selectors used) of the element that had focus before, and the element that has focus now. I don't see how changing the rule from "*:focus" to "a:focus, b:focus, c:focus" (for values of a, b, and c similar to those in comment 1 and comment 4) would need to have any implementation effect.
Comment 7 Elliott Sprehn 2013-11-22 18:25:39 UTC
(In reply to Ian 'Hixie' Hickson from comment #6)
> I don't understand how that affects this discussion.
> 
> The selector here is just "*:focus".
> 
> Even if the selector had combinators, you don't need to invalidate anything
> but the descendants and following siblings and their descendants (as
> relevant to the selectors used) of the element that had focus before, and
> the element that has focus now. I don't see how changing the rule from
> "*:focus" to "a:focus, b:focus, c:focus" (for values of a, b, and c similar
> to those in comment 1 and comment 4) would need to have any implementation
> effect.

Because when you blur a window the default focused element is the <body> so we end up recalculating the style for all elements in the whole document again. Perhaps this is a just an implementation detail.

@eseidel I think we should just switch to the list of elements in Blink to improve performance and leave the spec alone. :)
Comment 8 Ian 'Hixie' Hickson 2013-11-22 19:10:49 UTC
I don't understand how changing the selector would affect this. The <body> element doesn't match :focus, so why would you be invalidating the whole document?
Comment 9 Elliott Sprehn 2014-01-02 21:14:39 UTC
(In reply to Ian 'Hixie' Hickson from comment #8)
> I don't understand how changing the selector would affect this. The <body>
> element doesn't match :focus, so why would you be invalidating the whole
> document?

I need to dig into this more, I think there may be some confusion with our implementation or the standard. I'll talk to Eric Seidel and see if we can figure out what the issue is on the web app we were observing.
Comment 10 Elliott Sprehn 2014-04-09 22:09:02 UTC
I don't think this is a real issue. We should be able to just be smarter about it.