- 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