- From: François REMY <francois.remy.dev@outlook.com>
- Date: Fri, 14 Nov 2014 23:12:59 +0100
- 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