While implementing a horizontal scroller for webapp I ran into an unusual and very elegant way to create one with minimal JS code based on a suggestion by @Sitemas3 in this SO thread. One can create a very responsive (in the sense of speed) horizontal scroller by simply reassigning the order
attribute of the children in a display:flex
container.
No issues thus far. However, for some of horizontal scrollers I have one further requirement. I want to make the first (in the sense of the one displayed on the extreme left of the screen) child element of the scroller wider. Not a problem in itself - just find "which" child element is on the left and add the relevant class to its classList
.
There is just one problem - since all I have done perform the scroll is reassign the order
attribute the order of the scroller's children in its children
attribute no longer reflects their current display position on the screen. This brings me to my question - is there a method that I am unaware of that will provide me the list of children in their display order as opposed to their order in the markup?
Strictly this does not matter - I can always loop through the child elements and apply the additional class as required but in my quest for efficiency I wondered if there is not a DOM method that does the hard lifting for me
A rough example of the way I am doing things is shown below. To summarize
- I have a
position:relative
outer container - Within it I have a
position:absolute
inner container
Given that the context here is mobile screens these two containers will always be 100vw
Within the inner container I have the actual contents which consist of
- A flex box
- Its children with an assigned order
Try clicking the Rotate Left button to simulate a horizontal scroll from left to right. And then the Rotate Right button to simulate a horizontal scroll from right to left. You will see that the actual scroll happens and the DISPLAY ORDER of the children changes. However, the order of the children in the DOM tree is unchanged.
function elFromId(id){return document.getElementById(id);}
elFromId('rotLeft').addEventListener('click',rotateLeft);
elFromId('rotRight').addEventListener('click',rotateRight);
function rotateLeft()
{
elFromId('one').style.order = 1;
elFromId('two').style.order = 2;
elFromId('three').style.order = 0;
}
function rotateRight()
{
elFromId('one').style.order = 0;
elFromId('two').style.order = 1;
elFromId('three').style.order = 2;
}
.relBox
{
position:relative;
}
.absBox
{
position:absolute;
left:0;
top:0;
right:0;
bottom:calc(100vh - 50px);
}
#container
{
min-height:50px;
display:flex;
column-gap:2em;
}
#container > div
{
display:flex;
align-items:center;
justify-content:center;
font-weight:bold;
font-size:2em;
~
<button id='rotLeft'>Rotate Left</button>
<button id='rotRight'>Rotate Right</button>
<div class='relBox'>
<div class='absBox'>
<div id='container'>
<div id='one' style='order:0'>One</div>
<div id='two' style='order:1'>Two</div>
<div id='three' style='order:3'>Three</div>
</div>
</div>
</div>