Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[selectors4] :target-within? #457

Closed
LeaVerou opened this issue Sep 8, 2016 · 8 comments
Closed

[selectors4] :target-within? #457

LeaVerou opened this issue Sep 8, 2016 · 8 comments
Labels

Comments

@LeaVerou
Copy link
Member

LeaVerou commented Sep 8, 2016

A very common pattern is having a list of items (e.g. a gallery of products, or people, or a list of invoices etc) with every item being compact and showing little info until it's clicked, at which point all other items disappear and the item expands and displays all the data it contains in full size.

This can almost be done with CSS, by using :target to expand the item when the location hash matches its id. However, there is no way to make other items disappear in that case, so horrible hacks are usually employed, such as absolutely positioning the item to cover the list of other items.

Similar issues (and hacks to solve them) exist with UI patterns such as tabs, where if no tab is selected, one wants to show the first tab.

Since :focus-within is feasible, I don't see why :target-within wouldn't be, and it would immensely simplify such tasks. Thoughts?

@FremyCompany
Copy link
Contributor

Seems like a good idea to me

@FremyCompany FremyCompany added the selectors-4 Current Work label Sep 8, 2016
@nuxodin
Copy link

nuxodin commented Mar 9, 2017

@css-meeting-bot
Copy link
Member

The Working Group just discussed Target within, and agreed to the following resolutions:

  • RESOLVED: Add target within to selectors 4.
The full IRC log of that discussion <eae> Topic: Target within
<astearns> github: https://github.com//issues/457
<bradk_> i think "filter()" vs. "filter:" would lead to confusion
<eae> leaverou: This is probably best explained with an example. Image a photo gallery, clicking a phot enlarges it, often done with pseduo and having an anchor with a hash url. Every time you click an image it becomes the target.
<eae> leaverou: You also want to apply a style to the entire gallery without a selection, also done with target.
<eae> leaverou: No way to target the state where there is no hash.
<eae> leaverou: Suggested this on github but got no comments. Think it is useful and not terrible difficult to implement.
<eae> TabAtkins: I see the use case and see similar uses, I'm supportive of the use case.
<eae> ???: What if you have a photo gallery that also has some sections that aren't images that are stil targetable by a hash?
<eae> leaverou: Another use case for target-within as it allows both for the selected image and not to be supported.
<dbaron> s/???/dholbert/
<tantek> +1
<eae> Rossen: Any objections to target within?
<eae> RESOLVED: Add target within to selectors 4.
<leaverou> s/as it allows both for the selected image and not to be supported./as it allows you to use it on the image, which will apply both when the image is target or when it contains a target/

@o-t-w
Copy link

o-t-w commented Nov 29, 2017

A more general way of selecting parent elements, rather than confining the ability :focus-within and :target-within, would be amazing. They're a nice start though. I've already found using :focus-within very useful.

@tomhodgins
Copy link

tomhodgins commented Nov 29, 2017

A more general way of selecting parent elements, rather than confining the ability :focus-within and :target-within, would be amazing. They're a nice start though. I've already found using :focus-within very useful.

The way I see it, :has() is that more general way, it's already specced, but currently enjoys zero browser support. I too think having a way to select parents would be super helpful, but it seems like instead of supporting :has() we're speccing and supporting newer, smaller fragments of what :has() is already supposed to be able to do.

Isn't :focus-within functionally the same as :has(:focus)? And wouldn't :target-within be equivalent to :has(:target)?

If the general pattern of :<thing>-within correlates to :has(:<thing>), then let me brainstorm a few more selector ideas (I'm just pulling the list of existing pseudo-classes from CSS Selectors Level 3 & 4…)

  • :link-within
  • :visited-within
  • :hover-within
  • :active-within
  • :enabled-within
  • :checked-within
  • :empty-within
  • :blank-within
  • :drop-within
  • :current-within
  • :playing-within
  • :paused-within
  • :disabled-within
  • :valid-within
  • :required-within
  • etc…

Adding each of these would add quite a bit more of :has() original power to CSS, but we'd be missing out on ways to do things like:

  • :has(p)
  • :has(:nth-of-type(5))
  • etc…

I've experimented quite a bit with selecting parents and ancestors in CSS and I have found it useful, and I've even tried to DIY support like :has() using querySelector() from the context of elements matching a selector. If you want to check out the ways I've experimented with styling parents and ancestors have a peek at:

Alternatively to speccing a ton of newer, weaker, more limited selectors that do small aspects of what :has() should be already able to describe, I'd love to see browsers actually support :has() — does anybody know why that hasn't happened yet?

@LeaVerou
Copy link
Member Author

LeaVerou commented Nov 29, 2017

:has() is not in the fast selector profile and thus, even when supported by browsers, will not be available in regular CSS, just JS.
Browsers so far have not found a way to implement this efficiently enough for normal CSS, which is why we don't have such a feature yet, despite it being requested for almost 20 years.

We should really have an FAQ for this…

I do agree that duplicating syntax is not great though. If it were up to me, I'd just special case :has(:focus) and :has(:target) to be in the fast selector profile, and add more special cases as we discover them. But many (most?) others disagree with partially supporting syntax in certain contexts and think there should be a different syntax for that.

@js-choi
Copy link

js-choi commented Nov 29, 2017

There’s an alternative to @LeaVerou’s idea (i.e., her idea to turn :has(:focus) and :has(:target) into fast special cases of a slow/general version of :has()). It’s an alternative that’s worth also considering.

The alternative choice is to revise the current Selectors Level 4 draft so that :has() becomes an always-fast pseudo-class that accepts only a limited enumeration of arguments such as :focus, :target, :active, etc. :has(:focus) would be a valid fast selector, :has(:target) would be a valid fast selector, and :has(p) would be invalid syntax. :has(:focus) would be equivalent to that of :focus-within (which is a fast selector), and :has(:target) would be equivalent to this proposal’s :target-within.

Moreover, the current draft’s slow/general version of :has()—the one that takes a relative selector list—would be renamed. This renaming would hopefully be safe from breaking the existing web: it’s not yet implemented by any browser. For that slow/general version, a longer name—like :has-matches() or whatever—might be appropriate. :has-matches(p) would act like the current draft’s slow :has(p).

In this way, the shorter word :has would be used on the more-common thing: a fast, enumerated relational pseudo-class specifically for :has(:focus), :has(:target), and whatever else could be in the fast selector profile. The current slow, general relational pseudo-class would be renamed to :has-matches(…).

But no matter the choice made, ultimately, authors would probably use the fast/enumerated pseudo-class (i.e., in both general CSS and JavaScript/DOM) far more than the slow/general pseudo-class would probably ultimately be used by authors much less often (i.e., in JavaScript/DOM only).


Yet another alternative choice: The current draft’s slow/general :has() could be left alone and a new fast/enumerated pseudo-class for :focus, :target, etc.—like :within(:focus), :within(:target), etc.—would be created.

triple-underscore added a commit to triple-underscore/triple-underscore.github.io that referenced this issue Dec 3, 2017
Add :target-within to Changes section
w3c/csswg-drafts@0fdb0f8ec4b9d6dcb2302715ee4ab
35013a1a000

Add :target-within, resolves
w3c/csswg-drafts#457
w3c/csswg-drafts@d517bca980d01d13a1dc3765c0a3a
059c948402e

Add :focus-within to Overview
w3c/csswg-drafts@0933c5482c1ac25edf165e6c7b28c
66f1e561780

Add :is() example in specificity section, and add it in…
w3c/csswg-drafts@a9fddaf185d9885bd657cd222956b
ccc35486939

Add :is(), resolves w3c/csswg-drafts#1170
w3c/csswg-drafts@5948b1ce37463aa7f87fede040fac
9dd2c233329

Remove issue about :any-link naming, now that it's widely implemented.
w3c/csswg-drafts@33ae0979aff2c9a87cbd1e0f15ce5
632b1b1eaf3
@upsuper
Copy link
Member

upsuper commented Dec 6, 2017

In this way, the shorter word :has would be used on the more-common thing: a fast, enumerated relational pseudo-class specifically for :has(:focus), :has(:target), and whatever else could be in the fast selector profile. The current slow, general relational pseudo-class would be renamed to :has-matches(…).

FWIW, :focus-within in Gecko is currently implemented as a separate flag on all matching elements which is added or removed accordingly when focus changes.

What I want to say is that, the implementation of :focus-within, at least in Gecko, is not in a general enough way that can be applied to whatever pseudo-class you can find. The same approach may be applied to other single target pseudo-classes (e.g. :target), but it's definitely expensive for pseudo-classes which can have multiple matches, like :link, :enabled, etc.

Also we are always lack of room for more flags to track on elements, which means we may need to pay tradeoffs when adding any new flag, and thus even for single target pseudo-classes, we may want to avoid adding support for those which don't really have good use cases.

I'm not sure how other browsers implement :focus-within, but I would be quite interested if they can implement it with an approach which is both general and efficient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants