iron-list
iron-list copied to clipboard
List items overflow content hidden beneath lower items
Description
If an iron-list of items with overflow content (eg. dropdown menus) is used, an item's overflowing content will be hidden by the following item, as the lower item will have a higher stacking level.
I've got a fix for this, which sets the z index of each list item to the list size minus the item's list index, ensuring that earlier items stack above later items. The fix is here (with a demo for list items containing dropdown menus), but I occasionally rebase my fork to keep it up-to-date with this repository, so if that link doesn't work, the branch it's in is here. I can turn this into a PR, but there's no test because it's a visual bug fix and I don't know how you'd test that.
Expected outcome
Given the correct styling (eg. overflow: visible
), an item's overflow content should appear on top of content items lower in the list, as is commonly the case with dropdown menus.
Actual outcome
Overflow content appears beneath items lower in the list, making (for example) dropdown menus that are taller than the element they appear for unusable.
Live Demo
https://jsbin.com/sihuxoxaka/edit?html,output
Steps to reproduce
See the above live demo, which was adapted from the demo page added in the commit I linked to above.
Browsers Affected
- [x] Chrome
- [x] Firefox
- [x] Edge
Other browsers are untested.
Great issue, I got the same issue and waited for the fix as I thought there were other issues solving it - but they did not yet. I can add Safari to the list of affected browsers.
Closed issue that did not solve the problem : https://github.com/PolymerElements/iron-dropdown/issues/67
Still open issue that might be related : https://github.com/PolymerElements/paper-menu-button/issues/9
The one question that comes up for me with your proposed fix is, what do you expect people who's overflow content goes up out of the item (like the third option "bottom left aligned", here: https://elements.polymer-project.org/elements/iron-dropdown?view=demo:demo/index.html&active=iron-dropdown) to do with this fairly hard fix for one version of this issue? Seems like something that would need more flexibility if included in the main codebase or that should be handled by the implementer instead of the component. Thoughts?
That's a valid point, it doesn't handle dropdowns that extend above the top of the list item, but I can't think of a good general solution, since the problem is caused by iron-list items' stacking contexts, but caused for unrelated elements.
Does it seem like a lack of optimization for the implementer to manage their own z-index? a la:
<template is="dom-bind" id="demo">
<iron-list item="[[items]]">
<template>
<div style$="[[_computeZIndex(index, items)]]">[[item]]</div>
</template>
</iron-list>
</template>
<script>
var demo = document.querySelector('#demo');
demo._computeZIndex: function(index, items) {
return 'z-index:' + (items.length - index);
}
</script>
This could of course be managed more clearly and repeatably in a non-[is="dom-bind"] situation, but I think this allows you to cover your use case and others to manage z-index as they see fit for their implementation.
Given the probable complexity of a general solution, I'd be OK managing item z-indexes as an implementer, but is there not a cleaner way to do so without wrapping everything in a <template is="dom-bind">
?
That was just quickie short-handing on my part. There's no reason why it couldn't be done in a bunch of other ways. I usually wrap all of that into its own component, which helps me keep my implementations reusable across a growing code base.
This is because the DOM nodes that iron-list manages have style.transform = translate3d
which forces a stacking context. The current solution requires to append the menu outside the list. cc @valdrinkoshi as he was working on this problem.
~~Alternatively, I'd consider exposing a different way of rendering, e.g. using translate2d instead of translate3d.~~ That won't work
Is there any progress? Using <paper-menu-button>
inside of <iron-list>
is still a pain.
ping @valdrinkoshi
any update on this one? thanks guys for all the awesome elements!
I got a crude workaround for this issue. It works if you are using something like paper-dropdown-menu. You can check this link or here for the fix. I set the specific row with z-index-1 on menu open and reset z-index on menu close.
@sravan-s unfortunately this only works in shady
mode, because os shadow DOM encapsulation.
@blasten would you have a jsbon for that?
The current solution requires to append the menu outside the list
But doing that make the drop down appear at the wrong location right?
(similar issues arise with other elements embedded in the iron-list such as a paper-dialog so a generic solution/hack would be great in the meanwhile)
Cheers
I was trying to use paper-menu-button
inside a paper-toolbar
. The display area is limited to toolbar only, while it should overflow the toolbar and should be visible as an overlay on next elements.
@blasten what about using translateY
approach?
It seems that translate3d
is slightly better in terms of performance, but still the stacking context trap is annoying when using elements like paper-menu-button
or paper-tooltip
inside of iron-list
(or combining them both, which becomes even harder).
UPD: any translate
property value except of none
forces stacking context to appear.
So there is nothing to do here with iron-list
, but other elements, including iron-dropdown
, have to implement the solution themselves.
My current workaround is to set 'z-index' property for each .item
inside of iron-list
like this:
<div class="item" style="transform: translate(0px, 0px); z-index: 3;">
<div class="item" style="transform: translate(0px, 48px); z-index: 2;">
<div class="item" style="transform: translate(0px, 96px); z-index: 1;">
Any update on this?
FYI this affects Opera as well.
@web-padawan workaround is working for the moment. Thanks!
If anyone is interested in how to get this dynamically working in conjunction with iron-ajax. Here's my approach:
Add this to your iron-ajax call:
on-response="_jsonReceived"
Register these functions with polymer:
// calculate z-index
getIndex: function(itemIndex) {
return this._jsonReceived()-itemIndex;
},
// Count json items
_jsonReceived: function() {
return this.data.data.length;
}
Modify iron-list template to print correct z-index:
<div style$="z-index: [[getIndex(index)]]">
I found that reorganizing my structure to the like of how they have it structured in the PolymerElements/iron-scroll-threshold page fixed the issue for me at least.
I started with
<iron-list id="list" items="[[items]]" as="event" scroll-target="html">
<template>
<h1>hello</h1>
</template>
</iron-list>
<paper-spinner active="{{loadingEvents}}"></paper-spinner>
<iron-scroll-threshold id="scrollTheshold"
lower-threshold="500"
on-lower-threshold="_loadMoreData"
scroll-target="document">
</iron-scroll-threshold>
and refactored this to
<iron-scroll-threshold id="scrollTheshold"
lower-threshold="500"
on-lower-threshold="_loadMoreData"
scroll-target="document">
<template is="dom-repeat" items="[[items]]" as="event">
<h1>hello</h1>
</template>
</iron-scroll-threshold>
<paper-spinner active="{{loadingEvents}}"></paper-spinner>
I hope this may help.