W3C home > Mailing lists > Public > www-style@w3.org > November 2014

RE: [selectors] adding a :has-focus pseudo class

From: François REMY <francois.remy.dev@outlook.com>
Date: Fri, 14 Nov 2014 23:12:59 +0100
Message-ID: <DUB405-EAS177C337E38FCF584A787856A58C0@phx.gbl>
To: "'Florian Rivoal'" <florian@rivoal.net>, "'www-style list'" <www-style@w3.org>
± We discussed this briefly at the Sofia F2F, but did not get to the bottom of
± the issue, so I’d like to reopen.
± 
± === Intro ===
± 
± The :hover and :active pseudo classes match more than the currently
± hovered or active element: they also match on ancestors of the element,
± and allow the host language to let more elements match, which html uses on
± labels and their labeled controls. The :focus pseudo class does not do this,
± but there are cases when you would want something like that.
± 
± Here are some use cases for a :has-focus pseudo class (previously suggested
± under names such as :contains-focus or :focusWithin), which would work like
± :focus, except with rules similar to :hover and :active for which elements it
± matches. I’m also giving details why alternative solutions that have been
± proposed don’t quite cut it.
± 
± === Use case 1 ===
± 
± You are making a UI widget/component that consists of several pieces that
± are logically one control and you want to show focus around all of it. For
± example, if you were building an increment entry that showed you its +/-
± steps as 2 buttons around the input, you might do something like this:
± 
±     <div class="increment-widget">
±        <div class="decrement-button">-10</div>
±        <input class="value" />
±        <div class="increment-button">+10</div>
±     </div>
± 
± You might want the focus border/outline to be around the "increment-
± widget" div to encompass the inc/dec buttons too, so it looks like a single
± widget from the user's perspective. The idea is you'd be able to say:
± 
±     .value:focus { outline: none; }
±     .increment-widget:has-focus { outline: 1px solid blue }
± 
± Without :has-focus you would have to resort to JS, and listen to focus/blur
± events on the input and attach some kind of "focused" class that you target
± yourself. It's possible, but there are complications with having to do that
± manually:
± 
± You have to be very careful whether the window currently has focus and
± only apply that "focused" class manually if it does. For example, if in receiving
± an AJAX response, or a timer going off you decide to focus that input, you
± only want to apply the "focused" class on the "increment-entry" if
± document.hasFocus() is true, else you'll get a blue outline even if the
± browser doesn't have focus which just looks wrong, but then you'd better
± remember you wanted it to have that focused class and now must listen to
± window.onfocus/onblur to toggle that focused class on/off to keep that
± behavior. Very messy, easy to mess up, and not too efficient with all these
± event handlers. Especially if you're going to have many of these on screen.
± 
± === Use case 1.5 ===
± 
± Same as use case 1, except you are using web components and the shadow
± dom to make your widget. Same difficulties as above, potentially complicated
± by the shadowiness of things.
± 
± === Use case 2 ===
± 
± For forms or input pages that have sections of data or distinct sections of
± interaction, :has-focus can be used to visually indicate the active area of the
± screen.  For example, a customer checkout page that has section 1 "Confirm
± Purchase", with items to buy, and areas to add/remove items, section 2
± "Billing Information" with inputs for credit cards, coupon codes, etc.  And a
± section 3 "Shipping" with address inputs, phone numbers, etc. As the user is
± tabbing through the screen the sections could light up , change background,
± or otherwise indicate which section was being worked on.
± 
± Implementing this through JS has the same complications as above.
± 
± === Use case 3 ===
± 
± When a control which has a label is focused, you may want to highlight both
± the control and the label.
± 
± Implementing this through JS has the same complications as above.
± 
± Note that if you want to combine this with case 1 or 2, it gets marginally more
± complicated as you now have to deal with several converging/overlapping
± ancestor chains.
± 
± === Why :has() won’t work ===
± 
± It has been suggested that this could be handled by :has(:focus), except that:
± 
± 1) :has() is not part of the fast profile and must not be implemented in
± dynamic browser selector matching.
± 
± 2) When using web components with a shadow dom, the hover state pierces
± through the shadow root, allowing :hover / :active to match ancestors of the
± web component when a (shadow) child of the component is hovered /
± active. :has(:focus) would not do that. A more complex selector can be made
± to deal with this using ::shadow (or /deep/ actually) but this would still
± depend on :has.
± 
± 3) like :hover and :active, :has-focus would allow the host language to define
± additional ways in which an element can match, as html does for labels and
± labeled controls. :has(:focus) would not mirror that behaviour. A more
± complex selector could be crafted to handle html labels specifically, but that
± would not allow the flexibility of allowing the host language to manage the
± mapping, and would still depend on :has().
± 
± === Conclusion ===
± 
± We should add a :has-focus selector, included in the fast profile, which:
± a - matches on elements that match :focus b - matches on parents of
± elements that match :has-focus c - allows the host language to define
± additional ways in which an element can match :has-focus (and then ping the
± whatwg to do their part)
± 
± Alternatively (and I would actually prefer that), we could add these b and c
± rules to the existing :focus pseudo class. However, given that :focus is
± already interoperable in not doing that, I am afraid we’d run into web compat
± problems. Anyone has (or can gather) data to check if we can do that?
± 
± === References ===
± 
± This is not the first time that this is being raised. See
± http://lists.w3.org/Archives/Public/www-style/2013Apr/0713.html
± or Sylvain here:
± http://lists.w3.org/Archives/Public/www-style/2013Jul/0294.html
± or StackOverflow:
±  * http://stackoverflow.com/questions/17957299/css3-style-on-focused-
± parent-element
±  * http://stackoverflow.com/questions/2212583/affecting-parent-element-
± of-focusd-element-pure-csshtml-preferred
±  * http://stackoverflow.com/questions/4388102/can-you-style-an-active-
± form-inputs-label-with-just-css
±  * http://stackoverflow.com/questions/5978239/anyway-to-have-a-label-
± respond-to-focus-css
± 
±  - Florian

I'm strongly in favor of this. 

FWIW, I faced such an issue very recently, in the supervision of context-menus and tab navigation. To be honest, I still think we need "nav-up/down/left/right/next/previous" with selectors to handle keyboard and logical navigation more easily, though. 
Received on Friday, 14 November 2014 22:13:28 UTC

This archive was generated by hypermail 2.3.1 : Monday, 2 May 2016 14:39:26 UTC