featherlight icon indicating copy to clipboard operation
featherlight copied to clipboard

.featherlight:last-of-type CSS is not working

Open Jakobud opened this issue 8 years ago • 19 comments

  • [X] Bug report. If you’ve found a bug, you must provide a minimal example in a CodePen, starting from http://jsfiddle.net/JNsu6/15/ .

I'm trying to recreate this issue in jsfiddle, but no luck yet. What I'm doing is popping up a Featherlight box when the page loads using $(document).on('ready', function(){... }); The featherlight window appears and the .featherlight overlay is there, and it's using the .featherlight:last-of-type css rule. And, as elements on the page continue to load, all the sudden the the .featherlight element looses is background color, falling back to the background: rgba(0,0,0,0); rule.

At first this made me think there was for some weird reason another .featherlight element. But console.log( $('.featherlight').length ); reports back only 1 element.

So I'm not sure what is going on. I can recreate this consistently on my local development instance, but you can't access it online yet. I can't seem to recreate this problem in JSFiddle yet. Would you have any clues as to why this would be happening?

It's really weird. I inspect the .featherlight element and the .featherlight:last-of-type rule just isn't being applied to it, even though there is only 1 in the DOM. Take a look at the below screenshot. You can see $(.featherlight).length is just 1, but the rule still isn't being applied. I have no idea what is going on here.

screen shot 2016-06-29 at 3 39 19 pm

Any clues off the top of your head?

Jakobud avatar Jun 29 '16 21:06 Jakobud

A little bit more investigation with weird results:

While the Featherlight modal is open, Chrome dev tools reports the following using jQuery:

> $('.featherlight').length
< 1

< $('.featherlight:last-of-type').length
< 0

> $('body .featherlight').length
< 1

> $('body .featherlight:last-of-type').length
< 0

Really weird results. I thought that last-of-type returns simply the last element in the container, in this case the body element. Why is it returning 0? The element is clearly there. Whatever the reason is, is the same reason the CSS isn't working.

Jakobud avatar Jun 29 '16 21:06 Jakobud

Okay I figured it out. The problem is that, this last-of-type means that the .featherlight element HAS to be the last element in the body element.

I would definitely mark this up as a bug. In the case of my website, we are using a tag manager to load various 3rd party advertising tags to the page. Some of those have a delay on them and thus, those tags got inserted into the DOM AFTER the Featherlight code executed, which means that the .featherlight element is no longer the last-of-type in the body element.

Make sense? I'll think about a solution for this.

Jakobud avatar Jun 29 '16 22:06 Jakobud

I think maybe the only way to fix this is to make sure all featherlight elements end up in some sort of predetermined wrapper container, so that you can always guarantee that there are not going to be any of elements in this container that will screw up the :last-of-type selector.

I know there is the root option, but I would consider creating an extra element and not using body by default. There is no good way that the Featherlight library can guarantee that it's going to be the last element in the body element. If there is any sort of other DOM manipulation happening int he background while the lightbox is open and another element is added to the body, all the sudden your lightbox looses it's overlay background color since it's no longer last-of-type.

Jakobud avatar Jun 29 '16 22:06 Jakobud

Glad you've figured it out.

I think it was done this way for simplicity.

Maybe we should do as you suggest and deprecate the root option, in a v2 maybe?

Or check if $(root) is empty and root is '.something', then create the div automatically and change the default?

marcandre avatar Jun 29 '16 23:06 marcandre

I would not get rid of the root option. It could be helpful. I was also thinking to change root default from body to something else, like .featherlight-wrapper or something. Upon instantiation, if the root element is not found in the DOM, then it is created and appended to the body.

So now, every single featherlight modal, by default, will end up under the same unique div container. And if someone wants to specify their own root container, it will be used, whether it exists or not.

I assume the development branch is where you want pull requests directed?

Thanks,

Jakobud avatar Jun 30 '16 15:06 Jakobud

Sounds good, but I won't have time to work on that for a long while, so a PR is most welcome

marcandre avatar Jun 30 '16 23:06 marcandre

Development branch? Looks like its pretty out of date compared to master branch.

Jakobud avatar Jul 01 '16 17:07 Jakobud

lol, I nuked it :bomb:

marcandre avatar Jul 01 '16 17:07 marcandre

Is there a need for the :last-of-type modifier?

This worked for me:

.featherlight {
  background: rgba(0, 0, 0, 0.8);
}

teeparham avatar Mar 01 '17 00:03 teeparham

@teeparham Yes, for nested featherlights

marcandre avatar Mar 01 '17 15:03 marcandre

Adding a Google Recaptcha (v2) to a form in a featherlight overlay causes the background to disappear because of this issue. The Recaptcha element is inserted as the last element before the closing body tag thus nullifying the .featherlight:last-of-type css rule.

lukemcd avatar Jan 09 '18 21:01 lukemcd

I just came across this issue because LastPass inserts a <DIV> at the end of <BODY> for its little popup 'window'.

I know @Jakobud was talking about a PR, I'd be happy to contribute to that (or do it myself) but I'd need some direction about exactly the DOM should look like.

rob-deutsch avatar Jan 23 '18 05:01 rob-deutsch

I'm not sure what implications this has to other things, like IE8 or nested popups, but it seems to work with my limited testing.

xdhmoore avatar Feb 01 '18 18:02 xdhmoore

Re @xdhmoore's commit, ~ is a "general sibling" selector/combinator & is part of the CSS3 standard:

https://caniuse.com/#feat=css-sel3

teeparham avatar Feb 01 '18 18:02 teeparham

There are a couple of things in CSS 4 like :not() and :last-match() that could select only the last background instead of the first, but they don't seem to have full support yet. Of course, there's always js...

xdhmoore avatar Feb 01 '18 18:02 xdhmoore

Another weird idea I had was to change the element from a div to something custom, like <featherlight-instance>or something, like a web component. Then :last-of-type should work. I'm not sure how all the older browsers handle this though. According to that link, it requires a little bit of js in IE to declare the custom element. But maybe running that once would be enough for all instances. Or maybe if you aren't doing any real web component stuff, IE will just treat it like a div.

xdhmoore avatar Feb 01 '18 18:02 xdhmoore

Please provide a root for featherlight if you're encountering issues of that kind. AFAIK, that resolves all such issues.

marcandre avatar Feb 06 '18 06:02 marcandre

I can confirm the solution from marcandre resolved the conflict issue I had with Google Recaptcha v2. In the featherlight initialization I added: root: 'modals'

And just before the closing body tag I added: <modals></modals>

It is now working as expected.

lukemcd avatar Feb 06 '18 15:02 lukemcd

Careful with using <modals> elements. That is just a custom webcomponent that is definitely not cross browser compatible yet. It will be someday but not yet.

Jakobud avatar Feb 06 '18 20:02 Jakobud