Using: Has() as a CSS Parent Selector and much more
webkit.org
webkit.org
! Hide question suggestions
www.quora.com##div.qu-borderAll:has(div:has-text(/^Questions for you$/))
! Hide space suggestions
www.quora.com##div.qu-borderAll:has(div:has-text(/^Discover New Spaces$/))
! Hide 1) left nav bar, 2) footer (clap, comment), 3) right side bar
medium.com##div:has(> nav)
medium.com##div:has(> div:has(> article)) ~ div:last-child
medium.com##div:has(> div:has(> div:has(> div:has(> a[href^="https://help.medium.com"]))))
! Hide non-relevant seach results
www.youtube.com##ytd-search ytd-shelf-renderer:has(h2:has-text(People also watched))
www.youtube.com##ytd-search ytd-shelf-renderer:has(h2:has-text(For you))
www.youtube.com##ytd-search ytd-shelf-renderer:has(h2:has-text(Previously watched))
www.youtube.com##ytd-search ytd-shelf-renderer:has(h2:has-text(Results for similar searches))
www.youtube.com##ytd-search ytd-shelf-renderer:has(h2:has-text(New for you))
! Hide unused buttons (useful for vertical monitors)
www.youtube.com##ytd-toggle-button-renderer:has(yt-formatted-string:has-text(Dislike))
www.youtube.com##ytd-button-renderer:has(yt-formatted-string:has-text(Share))
www.youtube.com##ytd-button-renderer:has(yt-formatted-string:has-text(Thanks))
www.youtube.com##ytd-button-renderer:has(yt-formatted-string:has-text(Clip))Also very happy to see Apple and the Safari team push web standards forward!
Sliding door technique: https://alistapart.com/article/slidingdoors/
Bulletproof buttons: https://www.456bereastreet.com/archive/200705/creating_bulle...
Firefox had it from 2006, prefixed.
IE was the holdout, not having it until v9 in 2011.
[0]: http://css3pie.com/
> I remember in the early days cobbling together elements with top-left, top-right, etc image slices. Want't really too long ago.. maybe 10 years?
To me this is core ajax and php era, so ~2002-2006 which would be about 18 years ago.
By the time CSS standards for rounding corners arrived a lot of pain has been inflicted on us developers, but by now it feels as if this era never existed (same with pre/post flex to take another CSS milestone)
Leading is when you implement something and no one else as started. Example, Firefox and Chrome shipped WebGL2 and Safari did nothing for 4 years.
When multiple browsers are implementing the same standard at the same time and one ships a couple of weeks earlier that's not leading. Leading implies followers. Maybe in this case Firefox will follow both Chrome and Safari since Firefox has (no "has" support in Firefox Nightly)
You seem to be reacting with some anti-WebKit bias here, didn’t read the article about the history of this feature, or are taking a very odd view of “leading” to avoid giving credit to the WebKit team.
The article gives the history, and links you to it:
- eyeo approached Igalia to sponsor work on has:() in early 2021 (Igalia blogged about it May 2021, after having been working on it for a little while)
- Igalia worked on early prototypes to collect data and write tests to drive the conversation around :has() forward
- the WebKit team at Apple picked it up and started doing the hard work of a real and powerful implementation
- they shipped :has() in Safari Technology Preview 137 in December 2021
- they shipped :has() in Safari 15.4 on March 14, 2022
- Igalia did the engineering work to implement :has() in Chromium, which will ship in Chrome 105 on August 30, 2022
- the Chrome issue for :has(), which was created in May, you’ll see it openly references using WebKit’s work and approach
- other browsers built on Chromium won’t be far behind
- Mozilla is currently working on the Firefox implementation
> It's not like Safari are leading with this feature and others are catching up. Leading is when you implement something and no one else as started.
I think, given the timeline and everyone who is actively involved referencing WebKit with the real-world proven and shipped implementation, it’s exactly like that.
> When multiple browsers are implementing the same standard at the same time and one ships a couple of weeks earlier that's not leading. Leading implies followers.
This isn’t a couple-week lag. WebKit has (and continues to) lag in areas—but :has() isn’t one of them, as WebKit is literally the reference implementation here, was in Tech Preview 8 months ago, and has been released in Safari for 5 months. I think it’s fair and accurate to acknowledge that WebKit :has(followers).
I’m happy that Safari, who have been at times been criticised for not keeping up, are on this occasion helping to push web standards forward. That has nothing to do with who was “first”, but in this case they happen to have been. If they were two weeks behind I would have made the same comment on a thread about a blog post on their own blog.
With this particular feature, that's exactly what's happening. It's not the first time Apple shipped a new web platform feature before Google and Mozilla; it's the fact that it's been the most highly anticipated CSS feature in the recent history of the web platform.
Leading implies followers.
Apple shipped :has() December 2021 in Safari Technology Preview 137; it's been shipping in production since March 14, 2022 with Safari 15.4. That's a big gap in web time before Chrome ships in production.
layout.css.has-selector.enabled
The off by default is presumably due to fact that spec was not exactly settled yet, at least judging by discussion here:
i tried using firefox's experimental :has() on my personal css framework that's using all the latest features css features like :has(). on first glance, it looks like there are some bugs with firefox, but i'm excited that they're working on it. the simple parent selector case seems to work, but complex layout seems to confuse the layout engine.
:has() is easily my most anticipated css feature since grid at least (wish safari would support subgrid!).
At least on paper. In reality, the smaller coops don't grow big enough and so can be resourced starved and kinda get stuck in a death spiral as people leave to pursue other alternatives while the remaining members hoard power and control for themselves and make new employees basically not full owners but minions, etc.
There's no perfect system but I'd rather take the risks of equality than work under an oppressive hierarchy.
Not everyone cares about that though. Some would rather earn the big bucks, be led by execs, and not have to worry about the rest of the business.
Am I in a HN bubble where everyone are always complaining about safari, or is that genuinely unusual?
On the other hand, if Safari doesn’t support a feature Chrome supports, then that’s a problem for Safari because developers are going to be using that feature.
There’s this sort of naive attitude that “all browsers should just implement all the specifications.” But in reality all browsers take a fair amount of leeway with what specifications they implement, what timeline they implement them in, and etc. There are plenty of fundamental differences between engines that effect browser compatibility, that haven’t been addressed for years.
“Safari is behind Chrome” is just way too linear of a narrative. Web compatibility is a patchwork of over a thousand specifications.
I think that's a bit of an exaggeration/retconning. Between NetCaptor, Maxthon, etc., that's the era that gave us huge innovations: tabbed browsing, popup blockers, ad blocking, site groups, search in the URL bar, and so much more. And CSS, and GeoCities, and streaming video and animated applets/games/Flash...
There was so much innovation going on, the real difficulty was in being able to display your content to your audiences. CanIUse wasn't around then and there were huge incompatibilities between IE, Netscape, Opera, eventually Phoenix, etc.
It wasn't the diversity in engines that allowed innovation, it was the market exploring different features and eventually converging on the ones that people really wanted. If anything, having redundant engines slowed down actual development. IE6 was king for a few short years, and in those few years the web was more stable than it ever was before or since, and content was king instead of engine differences.
For now Chrome has the best of both worlds: market dominance and rapid innovation. They have no meaningful challengers anymore... Firefox/Gecko is dead and WebKit is only a thing because of iOS, and thankfully it at least shares a heritage with Blink.
I think your link proves the opposite point: that the web ecosystem is wasting time on interop instead of actual features. We don't need three renderers that do roughly the same thing, but nothing exactly the same. It was Chrome's hegemony over the last 5-10 years that actually gave us huge leaps in web usability, dev specialization, best practices, and content creation. The real changemaker was making Javascript safe and fast enough that native in-browser programming became a reality.
There is no such thing as web standards in reality, only Blink and WebKit's mostly-compatible implementations. If we could move past that delusion and just converge resources on Blink/V8 and just evolve that, the web would be better off for it.
Thanks to Mozilla we then got asm.js, wich evolved into Wasm and ultimately replaced NaCl.
Now imagine there was one engine and Google could implement whatever they wanted? RIP privacy and well-designed standards.
Then Flutter came out of nowhere and reintroduced everyone to Dart again.
Mozilla is largely Google funded anyhow. If they wanted to drop funding and go their own way they could do so anytime.
It would have a far better chance of working if the Chrome/Blink team were spun out of Google into a nonprofit that is protected from the financial influence of Google.
Chrome has been doing some terribly shady stuff with Blink whether we look at their various tracking proposals, “portals” which are a blatant attempt at ossifying Google as basically the internet itself, or the extreme standard-stuffing they continue to participate in to ensure no further competitors can pop up.
But beyond that nearly every point you raise here is completely off.
WebKit is superior to Blink, in almost all ways. It’s simply a much better browser and has been for a couple years now. Faster, lighter, and supports nearly everything you need. Every time I’m forced use Chrome, it’s like having to walk through a shady neighborhood - I literally can’t wait to close it. That thing sucks memory and battery in a way no app should, and Googles numerous shady tactics in trying to get you to login so they can avoid your privacy settings is downright hostile.
Leaps in best practices? Is that a joke? Web Components pushed by them is one of the worst things to happen to the web. Half of the standards they’ve pushed are actually regressions.
And again, Chrome is much slower and more bloated. If anything Safari is far better today for delivering a more native experience.
And your last paragraph is very much the kicker. The funny thing is the Safari thing is the only thing keeping Chrome in check. If this is what they’ve tried to get away with with Safari, I don’t understand how you can be advocating for even less competition. Interop is an incredible project that will save developers massive amounts of time, while ensuring we don’t end up with the most privacy invasive and manipulative company of all time controlling the web for the next 1000 years. Thank god for Safari.
You might want an advertising company to have unilateral control over the shape of that pipe, but some of us feel more comfortable knowing there’s a viable alternative with competing priorities.
I, for one, wouldn't like using the web with a web browser built by an advertising company pushing for Manifest V3 and killing adblockers as a result.
Given the history of those two, that’s amusing.
Safari has consistently been the fastest, more battery and privacy concerned browser.
Safari is WebKit, which historically has given us a lot of the CSS standard niceties we take for granted.
It also supports webp, even though I never use it. It’s a Google thing, not widely supported by image editors and which fails to be consistently better than a properly optimized jpeg.
If you thing you need webp try running it through MozJPEG first
I would like to see a decent true successor to JPEG which does stuff like alpha channels, but the annoying extend-embrace-extinguish approach Google used with WebP has turned me off of considering it very seriously.
To me, a format must offer significant advantages to overtake decades old standards.
Webp does lossy compression with alpha, think photographs with transparent parts. Png can't do that lossily and jpegs can't be transparent.
Dittering, quantization and lots of dirty tricks:
Questions like: will you be able to open them in 20 years, does this version of ImageMagic supports it, are not things I’d want to deal with daily.
Yeah, thanks but no thanks.
Hard to compete with standards with expired patents and equivalent if not better performance when the other side is sponsored by a single company. Especially one not particularly known for long term commitment to their projects.
Typically I've seen webp served at the CDN or client, where a png or jpeg alternative is also available, and where (hopefully) the website owner has the original asset somewhere safe.
Between "now" and "nobody uses webp" anymore, it's still a super useful format to speed up pages for a majority of users. That doesn't mean you should rely on it to be a safe archival medium, but that's not the only consideration.
Of course nobody is going to force you to use that (or really notice if you don't). It's just one image format out of gazillions.
With blurry backgrounds for example JPEG invents new colors. webp just blurs.
I worked on a media heavy fashion site a few years ago and dealing with Safari not allowing you to dynamically add new audio/video elements with auto play (or to auto play at all in low battery mode) was a real headache. By default it’s great, just offer the option to get permission for experiences that require it.
Currently most solutions are to load a number of empty audio buffers when the user first clicks and repurpose those for auto playing content later.
If a user has visited a multimedia focused web site (eg: online catwalk show), why not allow them to opt in for that session rather than force them to have a cut down experience?
There are work arounds? Looks like they need to be even more aggressive.
And yes. Making a streaming application. The CDN that the media is provided through uses cookies to coordinate "side band" metadata. On Safari, there's no way to get at the metadata due to the cookie policy. So, you get the media, but literally no metadata or features associated with it. It's a worse experience for any Safari user and doesn't actually enhance their privacy in any way whatsoever.
The workaround was to get the streaming provider to allow the correlation ID that would normally be conveyed through a cookie to be conveyed through URL parameters instead.
So.. to the extent that I could track you between two sessions, the workaround means I still can. Not that I need to track you, but because I need to correlate two streams between two different servers onto one device.
What's changed in that regard?
The CSS WG spent quite a lot of time and effort deliberating on a standard which wouldn’t have a significant performance impact. They only support a subset of selectors as arguments, to minimize their complexity.
Though as far a pre-existing complexity in modern engines goes: engine performance has regressed (in absolute end-user terms), and engine conplexity is also a barrier to entry for competing/new engines. So this isn't exactly "good".
However, for actual CSS, I don't think this is a good idea. You shouldn't need the has() selector if you write your own CSS and HTML.
Edit; I actually had a use case were I was building an expanding menu, without JavaScript, it involved a ~ and > selector on a checkbox to get that to work. The :has selector would’ve made it straight forward.
Also going back to the roots of CSS, :has() is ideal for semantic markup where you don’t want or need to use excessive class names. Obviously with class heavy frameworks and methodologies that are in vogue :has() is less relevant.
There is more than one way to use CSS.
> Your CSS should describe how the HTML looks
That’s literally what :has() does, based on the structure of the document.
And at any rate, removing classes and IDs as much as possible and just having a page full of semantic tags is generally a goal for a certain school of web development.
div:has(:focus-visible)
for showing the focus state on a parent element. This is otherwise impossible without using JavaScript.So now, instead of adding class to an element to choose how to display those differences of content, I can just use :has() selector. Thus removing even more design concerns from the HTML back into the CSS where it belongs.
But yea you’re right that it’s not going to be really common
now that we throw our hands in the air, say “fuck it”, and first&foremost serve “apps”, single-page or not, styled with utility class systems like tailwind, it feels a lot less meaningful to the average poor sap hired to make web frontends
It feels like the last ten years of web dev has been the entire industry giving up on the idea that web pages are supposed to be pages.
parent:has(child)
Instead of parent < child
Which seems a bit more intuitive to me given that the inverse is a thing.You can also match descendants of something with the :has() selector. It really is more than a “parent selector”
div:has(b) a
which matches a link inside a div that also contains bold text. The important part is that 'b' and 'a' can be very different places in the hierachy, they don't need to be same like like a 'b + a' selector.
Check this out
```css
figure:has(input[type="checkbox"]:checked) figcaption {
/\* if a figure has a checkbox checked,
apply this to its figcaption... \*/
font-size: 90%;
font-style: italic;
margin: 0.6rem 0 0.1rem;
}
```
https://codepen.io/julienreszka/pen/yLKZRRXPersonally, I prefer the actual syntax over your expecation. The first thing in the selector are actual elements that will be styled if certain conditions are met. That also matches how the existing pseudo-classes have been applied.
> “if I’m in a hover state make my parent green, regardless of who/what the parent is”
*:has(> *:hover):hover:parent()
So it’s a post fix to go back up the tree.
I prefer the flexibility of :has().
One is opening the developer tools. Have more than a couple tabs with the dev tools open and I can easily have Safari itself go over 8GB and I start to feel the thrashing when switching between apps and stuff. Closing dev tools for certain tabs when I no longer need them helps.
Two, for whatever reason, is streaming YouTube videos - not playing pre-recorded ones but watching livestreams. I suspect the culprit is actually the chat box but I'm not sure. For now, if I want to watch a YouTube stream for more than a couple minutes, I'll usually pass it to Streamlink which allows me to watch the stream through VLC and bypass the web interface entirely - I don't participate in or care about the chats anyway.
I even set up a Zsh function I can invoke with "sl" which automatically fires up Streamlink with whatever URL I currently have in my clipboard.
https://github.com/GarrettAlbright/Dotfiles/blob/master/.zsh...
Incidentally, if you open up Activity Monitor and go to the Memory tab, it'll show you how much memory each Safari tab is using… well, sort of. It uses the domain name of the site as the "Process Name," but that's not very useful if you have more than one tab open with a page from the same domain name. I really wish they'd put the full page title and/or URL in there and/or let you switch directly to the offending tab from Activity Monitor.
All that being said… Naturally, Safari is the most well-integrated and performant macOS browser, and it puzzles me why even self-described Mac fans would use anything else for anything other than testing.
Instead, try to avoid the need to define styles that way. Learn to rely on the cascade. Pick an authoring style for sizing, margins and paddings and stick to it. I tend to prefer h-margin and v-padding on containers and v-margins and h-padding on content.
There are things they've done that are amazing, and which I respect (like JavaScriptCore), but overall Safari is the worst popular browser. I don't get how people can stand it, but again I don't get how people can stand iOS either.
> But do you ever see a “Best viewed with Safari” notice? No, you don’t. Another browser takes that special place in web developers’ hearts and minds.
> Chrome is the new IE, but in reverse. [1]
What has the biggest impact on me as a user isn’t the quantity of bells and whistles the browser’s engine has, but how efficient it is because nobody likes battery vampire apps and how much the browser tilts the balance of control in favor of the user, because third parties on the web are best treated as adversarial until proven otherwise.
Chrome provides a nice experience for devs, but its user experience continues to slip.
The article that you are commenting on explicitly mentions the focus on performance while considering this feature. They even state to have been able to achieve "fantastic performance, even in the presence of large DOM trees and large numbers of :has() selectors".
The idea is not new at all. People have been asking for something like this for many years. You know why it never happened? Because it would be slow. Maybe the webkit devs have found a really fast and clever way to do it. But shitting on people for voicing their well founded skepticism is not a good sign. Especially when all we have is their word.
> You know why it never happened?
Yes, I do.
> Especially when all we have is their word.
Does that mean you don't trust their word? Good. Would you trust their own benchmark? No? The parent selector has been in Safari 15.4 since March, 2022. So feel free to do your own benchmark. There is not just their word.
You might also find the lengthy explainer of Igalia, where performance is discussed, interesting: https://github.com/Igalia/explainers/tree/main/css/has
Being skeptic is not a bad thing. But (uninformed) criticism without any specifics is far from "well founded skepticism". JavaScript interpreters used to be very slow twenty years ago, now they are extremely fast. That can happen to CSS evaluation, too.
What is your point exactly? That performance should be one of the most important aspects in browser engine development? I agree. Hence, I asked OP to elaborate their claim that this selector harms slow devices. And I'm not interested in the (outdated?) historical concerns of a parent selector. But the actual effect of the specific selector implementation in WebKit which this discussion is about.