Reputation: 4581
I am trying to have a load of divs which are horizontal scrolled. Each div is absolute positioned (the red box in my example) so that it is visible outside of the scrolling container. I have an example that works well but seems I have lost the ability to scroll. The scroll bar appears but scrolling it does not move the divs.
By adding position relative to the overall container I can get the divs to scroll, but they don't show outside of the container.
Please help me be able to show contents outside of container yet maintain scrollability.
<div style="overflow-x:scroll; height:40px; white-space: nowrap; background:black;">
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
</div>
Upvotes: 3
Views: 3971
Reputation: 4148
I slightly edited your code snippet and added a class to the black container, to easily style its direct children with this:
.container > div {
border: 1px solid green;
}
.container > div {
border: 1px solid green;
}
<div class="container" style="overflow-x:scroll; height:40px; white-space: nowrap; background:black;">
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
<div style="display:inline-block; margin-left:50px; width:500px; height:40px">
<div style="border:1px solid black; height:40px; width:500px; position:absolute">
<div style="position:absolute; height:100px;width:500px; background:Red; top:5px; left:5px"></div>
</div>
</div>
</div>
Now you should be able to see that the scrolling is actually working, but only for the green divs. The other elements (black border divs and red divs) are not scrolling because they have position: absolute;
. This means that they are taken out of the document flow and since no other element has position: relative
, they are absolute relative to the body. That's why, if you scroll with the main scrollbar, they will actually scroll.
You could add position: relative;
to the container, but doing so, as you said, the elements won't overflow the container.
As far as I know, there's no way to solve this with just css and you probably have to make them scroll through some Javascript.
A very basic example:
const container = document.querySelector('.container');
const boxes = document.querySelectorAll('.box');
container.addEventListener('scroll', (e) => {
let offset = e.target.scrollLeft;
for(let box of boxes) {
box.style.transform = `translateX(${offset}px)`;
}
});
.container > div {
border: 1px solid green;
}
.fake-width {
width: 2000px;
}
.boxes {
display: flex;
}
.box {
background: blue;
}
.box + .box {
margin-left: 50px;
}
<div class="container" style="overflow-x:scroll; height:40px; white-space: nowrap; background:black;">
<div class="fake-width"></div>
</div>
<div class="boxes">
<div class="box box-1" style="display:inline-block; margin-left:50px; width:500px; height:40px">
</div>
<div class="box box-2" style="display:inline-block; margin-left:50px; width:500px; height:40px">
</div>
<div class="box box-3" style="display:inline-block; margin-left:50px; width:500px; height:40px">
</div>
</div>
</div>
As you can notice, if you go this route, you don't even need to keep the divs inside the scrolling container. You could, depending on what exactly you are going to build, but you don't need to.
Upvotes: 2