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

Transform properties aren't removed from hidden grid items and that causes a fixed positioning issue. #1593

Closed
ianthedev opened this issue May 23, 2021 · 12 comments

Comments

@ianthedev
Copy link

ianthedev commented May 23, 2021

If the grid items or any of their parent elements have the hidden attribute and become hidden, then after a re-layout, the CSS transform properties won't be removed from grid items.

And after the hidden attribute is removed, the CSS transform properties remain exist. And that causes a fixed positioning issue that the grid items becomes the containing block of any fixed-positioned child element, and that is undesirable in most cases. Please see MDN's explanation about how the containing block is determined in fixed positioning.

You can reproduce the transform properties' not being removed from grid items by using the official horrizontalOrder demo:

  1. Use browser's devtools to observe the CSS transform properties' being correctly removed from the grid items after a re-layout followed by a browser resizing.
  2. Add the hidden attribute on the grid container, and then observe the CSS transform properties' not being removed from the grid items after a re-layout followed by a browser resizing.
@thesublimeobject
Copy link
Collaborator

Could you perhaps explain your use case here, and even maybe do a CodePen for what you're trying to accomplish? I may be misunderstanding you, but I suppose I fail to see the intent here.

If add hidden as you explained on the Isotope docs page, you're right, the items do not get re-calculated. That said, when I add the attribute the grid will be hidden by the browser since hidden elements are not rendered by default (now whether the browser immediately un-renders those elements or just hides them and leaves their active properties, I don't know off-hand). On the other hand, the hidden property is overridden automatically by any explicit display properties, like display: block, for example. So if you add that, the grid will show up, and following the instructions the same way, the items are properly re-calculated.

So, it seems that if you wanted the grid to still show up even with hidden active, the re-calc works fine, but if it's hidden it doesn't work since the items aren't rendered. In the first case it works, but in the second here doesn't seem to be any valid reason for needing the recalculations to be done anyway.

Like I said, I may have misunderstood you, and if so, please clarify.

@ianthedev
Copy link
Author

ianthedev commented May 25, 2021

@thesublimeobject

The hidden attribute is for hiding inactive tab panels. Please see W3's tabs example.

When browser resizes, grid items in a hidden tab panel are re-layouted, but their CSS transform properties aren't removed. And after a hidden tab panel is unhided, the fixed positioning issue emerges.

@thesublimeobject
Copy link
Collaborator

I would really need a more specific example/codepen at this point.

That said, I think the best solution to your situation is realistically changing the way you're using/styling the tabs. Per the HTML spec the hidden attribute shouldn't be used for tabs—

The hidden attribute must not be used to hide content that could legitimately be shown in another presentation. For example, it is incorrect to use hidden to hide panels in a tabbed dialog, because the tabbed interface is merely a kind of overflow presentation — one could equally well just show all the form controls in one big page with a scrollbar. It is similarly incorrect to use this attribute to hide content just from one presentation — if something is marked hidden, it is hidden from all presentations, including, for instance, screen readers.

There are several other ways using that you could achieve the same layout with CSS/JS or some combo. That would eliminate the problem completely as it would take hidden out of the equation.

@ianthedev
Copy link
Author

ianthedev commented May 25, 2021

@thesublimeobject Specific example. Somehow the re-layout in a hidden tabpanel isn't working correctly in this example, but that's not important because my concern is about the CSS transform properties aren't removed.

I'll check with W3 about the spec of hidden.

@thesublimeobject
Copy link
Collaborator

Thanks for the example!

Somehow the re-layout in a hidden tabpanel isn't working correctly in this example

Honestly, I don't think it should be working; that has sort of been my point this whole time. When playing with this example, in order to be sure I was thinking through this correctly, I wrote a small function to output the styles of the tabpanel, grid, and one of the grid items. When the tabpanel is hidden, all of those items are essentially stripped of their style props since they are no longer marked necessary for render. So all of their widths/heights/etc. are just 0 or ''.

Therefore, when resizing the window while one of the layouts is hidden, Isotope cannot calculate the element styles since the browser is literally not bothering to render where they would be. It's not that those elements are just "not displayed", they are simply not rendered at all by the browser. So when you switch back to the layout that was hidden, it doesn't have any way to calculate the current element sizes unless you manually trigger some other event. I'm still not completely sure why it matters if the transform properties themselves are on there or not. As far as I can tell it's just retaining the values from before since that is likely the only values it has to process.

If you want to keep this hidden/tabpanel layout, you're going to need to attach a click listener to the tabpanels themselves and then attach a function that tells isotope to re-layout the items when the panel is switched. Unfortunately, I don't have more time right now to test this, but if you can't figure it out I can probably whip up an example for you later. Nonetheless, you should be able to just manually re-call isotope.layout() on whichever grid was hidden when the button is clicked, that way as soon as the items are re-rendered by the browser, isotope can recalculate the positioning of the items and lay them out correctly for the current browser size.

Does that make sense?

@ianthedev
Copy link
Author

ianthedev commented May 26, 2021

Well, my previous message wasn't stating the re-layout issue clearly. Sorry about that. Actually, the re-layout does not happen in a hidden tabpanel. Instead, a hidden tabpanel is temporarily unhided for the re-layout. And then the tabpanel is hidden again after the re-layout is done. I just compared my real use case with the example I created here and figured out why exactly the re-layout didn't work in this example. It has been fixed. Now the only issue is that the CSS transform properties aren't removed.

As for the hidden attribute, some person said the spec could be clearer and referred to this comment.

@thesublimeobject
Copy link
Collaborator

@ianthedev — I read some of the comments linked above, but I think I'm still in the camp that it would likely be better to just not use the hidden attribute for this layout, since I think there's better ways to achieve it that might not cause any requisite issues, but we can agree to disagree there as it's likely not a huge deal.

With regard to the updated Pen, I do see that the re-layout works correctly now. I guess I'm still a bit unclear on why it matters that the transform properties aren't being removed. As far as I can tell, the situations in which they aren't being removed in the Pen you provided, I don't seem to be able to grasp anyway in which they are negatively affecting the layout, since they seem to just be transform: translate3d(0, 0, 0).

Your original post says,

And that causes a fixed positioning issue that the grid items becomes the containing block of any fixed-positioned child element, and that is undesirable in most cases.

In which cases would this be undesirable? Are you saying that you have fixed positioned elements inside of the items themselves such that they are positioned relative to the viewport, and then when these transform props are left on the items, they items become the container relative to those fixed positioned items, therefore changing the relative positioning of the elements inside those items? This seems like a relatively specific use-case as I really can't image that many cases in which anyone is using fixed positioning relative to the viewport inside of the items themselves as that seems like a strange way to layout something in the first place, but again, maybe I'm still misunderstanding something.

Nonetheless, you could potentially just attach a layoutComplete listener and manually remove the transforms that you don't need, if they still exist after the layout has been completed?

@ianthedev
Copy link
Author

Nonetheless, you could potentially just attach a layoutComplete listener and manually remove the transforms that you don't need, if they still exist after the layout has been completed?

Thanks for the advice. That can be a provisional workaround.

@thesublimeobject
Copy link
Collaborator

@ianthedev — Per your other thread, you said that this issue isn't "solved" yet because you only consider this a provisional workaround. That said, I would personally consider this issue solved since I'm not entirely convinced this is actually a bug so much as an esoteric issue, which may or may not stem from the incorrect use of tabs with the hidden attribute. Especially given that this issue is directly related to the manner in which the hidden attribute works by default—preventing the rendering of elements within elements that contain that attribute—I'm not sure this would classify as an actual "bug".

@desandro — Would you mind confirming my intuition here? Or if you disagree, I can perhaps look into a fix for it, although as it stands I'm not really convinced that this is truly a bug.

@ianthedev
Copy link
Author

ianthedev commented Jun 1, 2021

@thesublimeobject

Actually, the re-layout does not happen in a hidden tabpanel. Instead, a hidden tabpanel is temporarily unhided for the re-layout. And then the tabpanel is hidden again after the re-layout is done.

@thesublimeobject
Copy link
Collaborator

thesublimeobject commented Jun 1, 2021

@ianthedev, from my response above —

With regard to the updated Pen, I do see that the re-layout works correctly now. I guess I'm still a bit unclear on why it matters that the transform properties aren't being removed. As far as I can tell, the situations in which they aren't being removed in the Pen you provided, I don't seem to be able to grasp anyway in which they are negatively affecting the layout, since they seem to just be transform: translate3d(0, 0, 0).

In which cases would this be undesirable? Are you saying that you have fixed positioned elements inside of the items themselves such that they are positioned relative to the viewport, and then when these transform props are left on the items, they items become the container relative to those fixed positioned items, therefore changing the relative positioning of the elements inside those items? This seems like a relatively specific use-case as I really can't image that many cases in which anyone is using fixed positioning relative to the viewport inside of the items themselves as that seems like a strange way to layout something in the first place, but again, maybe I'm still misunderstanding something.

While you did say the solution that I gave below these quotes from the above response would work as a provisional workaround, you never really detailed why this would be an issue, or why and in which case this sort of setup would be undesirable. So even beyond the tabpanel/hidden attribute case, I'm still not convinced this is actually even a remotely common issue such that it should be considered an actual "bug". Can you perhaps detail a use-case that you would deem common enough that this issue is beyond a more insular issue? I still really can't imagine almost any case that this sort of layout would be used, since using fixed positioning inside of the items themselves would seem to directly subvert the way that Isotope works in the first place.

@ianthedev
Copy link
Author

Let's forget it for now then.

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

No branches or pull requests

2 participants