- From: Emilio Cobos Álvarez via GitHub <sysbot+gh@w3.org>
- Date: Mon, 29 Jul 2019 22:18:42 +0000
- To: public-css-archive@w3.org
aHere's the intersection code that I thought of: https://stackoverflow.com/questions/9011668/get-element-at-point-in-entire-page-even-if-its-not-visible
Upon re-reading it I think what that code is trying to do would be better done by something like flex or grid, but I haven't thought out too much how, it seems it's sort of like the masonry layout stuff.
Anyhow... The usecase that prompted me to propose it was some investigation in https://github.com/mozilla/fathom/issues/91. But I've seen similar code elsewhere in sites like Facebook and such (see https://bugzilla.mozilla.org/show_bug.cgi?id=1381071#c1 for example).
The facebook code is:
```ts
function isVisible(element: HTMLElement): boolean {
// Look upward in the DOM until we either reach the document or
// find something hidden.
let elem = element;
while (
elem &&
elem !== document &&
Style.get(elem, 'visibility') != 'hidden' &&
Style.get(elem, 'display') != 'none') {
elem = elem.parentNode;
}
// If we reached the document, the element is visible.
return elem === document;
}
```
The code in the Mozilla add-on was similar too:
```js
export function isVisible(fnodeOrElement) {
const element = toDomElement(fnodeOrElement);
for (const ancestor of ancestors(element)) {
const style = getComputedStyle(ancestor);
if (style.visibility === 'hidden' ||
style.display === 'none' ||
style.opacity === '0' ||
style.width === '0' ||
style.height === '0') {
return false;
}
}
return true;
}
```
(I skipped [some branch](https://github.com/mozilla/fathom/blob/5cf2e902d3cdd01368ed72e7796b848f741e17b0/utilsForFrontend.mjs#L477) which was doing some viewport stuff because it's not clear what it's trying to do, I think it's trying to check elements scrolled out of view towards the top, or something).
The question that code is trying to answer is whether a given node is "visible", for some definition of visible. Both functions are bogus in multiple ways:
* They don't work with anything that looks like shadow DOM in any way.
* They assume `visibility` works differently than how it works (`visibility: visible` inside `visibility: hidden` is definitely visible).
* The `style.width` and `style.height` checks in the add-on code is wrong (should be `0px` instead), they're meaningless is `overflow` is `visible`, etc...
* They don't handle other ways to make an element "hidden".
The add-on use-case is even worse because walking the DOM from an add-on is slower due to security wrappers / proxies.
In the add-on use-case at least, the complaint against `elementsFromPoint()` was that it returned false for out-of-viewport elements. But using it actually _improved_ performance compared to all the DOM walking and layout querying (mostly because of the reduced number of DOM calls, actually).
It seems to me like a good improvement over those two functions but, that being said, chances are that a more thought-out proposal may want a bit more flexibility. For example, people may want to ignore all scroller clips, or maybe only those with user-scrollable overflow (that is, don't ignore `overflow: hidden` clips but ignore `overflow: scroll` clips)... In any case ignoring the viewport clip is a pretty good improvement over the situation now.
The Facebook code doesn't need to deal with all of the web, but libraries / frameworks and extensions do, this could allow them to write actually correct code :)
--
GitHub Notification of comment by emilio
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/4122#issuecomment-516183855 using your GitHub account
Received on Monday, 29 July 2019 22:18:44 UTC