-
Notifications
You must be signed in to change notification settings - Fork 23
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
I want to be able to listen to changes to Element.matches, similarly to matchMedia #387
Comments
I've attempted to draft a couple of different replies to this now, but every time I open it I get stuck a little in whether or not I am sure what the ask actually is. This asks specifically for an There has been a long history of wanting something more like the latter and attempts to speculatively polyfill or build paths toward answers... Here are a few that come to mind:
Because there are a lot of things one could potentially do with more powers here, there are a lot of use cases and not all proposals or libraries have addressed all of them but basically I think they fall into a few broad categories of:
We could get into listing a lot more concrete use cases I think, if we could nail down the desire(s) expressed here a little better? |
Hi :) Want author here, thank you for taking the time to respond I'll try and clarify it a little bit by providing some real world scenarios Float LabelsFloat Label implementations can use The issue is that However, I think .float-label-wrapper:has(input:placeholder-shown) label {
/* move label out of the way */
} Displaying an input's error message when
|
If these are specifically the use cases, then I believe you can see some related history here in the links in w3c/csswg-drafts#1067, with a long a desire to let you express this in CSS itself (which seems your preference based on the above)... Sorry, it's hard to have a cannonical one as there have been many proposals on this, but that link is rich with links and refs you can follow back and back. Would a CSS only solution that these would provide be your preference, or would a live match callback idea on a single element still be preferable? Note the ones I linked up above (when I thought you were looking more for JS stuff) are more like observers which wouldn't require you to have a reference to the element in the first place... not sure if that matters at all? |
Thanks for mentioning me @bkardell, and to complete the list of previous work around this topic:
That translates to the fact that all selectors are applied live when an element matches, but there's no way to trigger, notify, or change anything, when the element doesn't match anymore its state. I could implement this at some point, but it feels wrong, or unexpected, as there's nothing in the platform similar (attributeChangedCallback, connectedCallback, and disconnectedCallback are all we have ... no selectorChangedCallback). The elephant in the room... is that every primitive we have to observe DOM changes is either very slow (imagine a MutationObserver for every single attribute change or any modification on any element on the page), or incapable of catching pseudo classes changes, so that even if there is a possibility to create a very convoluted solution with JS, this would mean that all observed selectors should diff from a previous state to a current one, and such observer cannot even use a WeakMap, because WeakMap doesn't allow crawling its content, so the whole architecture in JS only would be very memory-leak prone, or not very easy to handle even using WeakRef, as the callback to signal a node doesn't exist anymore, hence it won't match any selector, cannot be retrieved back (or it won't be weak), so we have literally no way to implement what I believe is being asked here. A Possible Solution ?What I think the HTML+CSS+JS combo misses, is the ability to be notified whenever an element gets re-painted, or better, whenever an element changes its "CSS state". As pseudo example, and as possible MVP for implementation, I'd love to have something like the following: CSS.observe('div.opened', (selector, records) => {
console.log(selector); // '.opened'
console.log(records); // a list of records
});
// a way to drop the observer
CSS.unobserve(sameSelector, sameHandler);
// there should be no way to CSS.disconnect() or CSS.clear()
// as that would be obtrusive and disaster prone across libaries Let's see a practical example (Codepen): <!doctype html>
<style>
div {
height: 0;
overflow: hidden;
}
div.opened {
height: auto;
}
</style>
<button onclick="example.classList.toggle('opened')">open</button>
<div id="example">
Some content here.
</div> Ideally, the previous JS would basically pass, after the first button click: listener(
'div.opened',
[{target: {the_div_with_id: 'example'}, matches: true}]
); After the second button click, as the listener(
'div.opened',
[{target: {the_div_with_id: 'example'}, matches: false}]
); Specs in a nutshell
I have no idea if this is explained well or it makes sense at all, but I believe a similar primitive, provided by the browser, would enable million new and better ways to augment the DOM, without needing to:
I hope this comment/idea somehow makes sense, but I'd be more than happy to expand more. This would cover everything, including the :has case, which I don't find particular interesting, once anyone can observe any selector, so the scope of this idea goes beyond pseudo / has, it's about the CSS engine passing along elements that got updated after a specific selector, only if such specific selector was observed. |
title: I want to be able to listen to changes to Element.matches, similarly to matchMedia
date: 2021-05-27T14:32:13.591Z
submitter: Guylian Cox
number: 60afad6ddd1319252815bea6
tags: [ ]
discussion: https://github.com/WebWeWant/webwewant.fyi/discussions/
status: [ discussing || in-progress || complete ]
related:
url:
type: [ article || explainer || draft || spec || note || discussion ]
Being able to exploit CSS's reactivity with JS would be incredible
Some scenarios:
If posted, this will appear at https://webwewant.fyi/wants/60afad6ddd1319252815bea6/
The text was updated successfully, but these errors were encountered: