Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overflow scrolling on dynamically moving elements

var block = document.getElementById('block')

function myFunct() {
    block.style.transform = 'translateX(-400px)'
}
    .container {
        position:relative;
        width:400px;
        height:150px;
        margin:auto;
        background-color: blue;
        overflow:scroll;
        
    }
    

    
    #block {
        position:absolute;
        height:25px;
        width:100%;
        left:50%;
        bottom:50%;
        overflow: scroll;
        background-color: yellow;
        border:1px solid black;
        align-self: flex-end;
    }
    <div class="container">
        <div id="block"></div>
        <button onclick='myFunct()'>CLICK</button>
    </div>

In my example the block overflows the right side of the container and overflow is set to scroll. So you can scroll the right side and see the rest of the block. Then when I run the function, the block moves so it's overflowing the left side of the container. However it does not adjust to allow for scrolling left to see the rest of the block. What is the solution to allow for scrolling of other sides after functions are ran and blocks are moved to overflow those different sides.

like image 402
Harper Creek Avatar asked Jul 31 '19 18:07

Harper Creek


2 Answers

The real problem at hand is that the css property transform will only trigger a repaint on the Composite Layer, this was an optimization decision made to facilitate animations without triggering repaints on the Layout Layer . To trigger an entire layout repaint you should use a layout property like left or right:

Example:

function myFunct() {
    block.style.left = '0px'
}

Also the reason you are getting the scrollbar on initial load is because you have:

#block {
...
  left: 50%
...
}

More here on Compositor-Only Properties

Edit:

Although the above is true, switching to 'style.left' will still not cut it because block level elements have a default content flow direction of left to right or in css direction: ltr so this means you'll need to modify the content direction as well which should cancel out the need to use style.left. See below:

var block = document.getElementById('block')
var container = document.querySelector('.container')

function myFunct() {
    block.style.transform = 'translateX(-400px)'
    container.style.direction = 'rtl'
}
 .container {
        position:relative;
        width:400px;
        height:150px;
        margin:auto;
        background-color: blue;
        overflow:scroll;
    }
    

    
    #block {
        position:absolute;
        height:25px;
        width:100%;
        left:50%;
        bottom:50%;
        overflow: scroll;
        background-color: yellow;
        border:1px solid black;
     
    }
    <div class="container">
        <div id="block"></div>
        <button onclick='myFunct()'>CLICK</button>
    </div>
like image 55
KpTheConstructor Avatar answered Nov 08 '22 16:11

KpTheConstructor


Based on this, a the solution can be sort of 'hack' like this:

var block = document.getElementById('block')
function myFunct() {
    document.getElementsByClassName('container')[0].dir = 'rtl';
    block.style.transform = 'translateX(-400px)'
}
.container {
        position:relative;
        width:400px;
        height:150px;
        margin:auto;
        background-color: blue;
        overflow:scroll;
        
    }
    

    
    #block {
        position:absolute;
        height:25px;
        width:100%;
        left:50%;
        bottom:50%;
        overflow: scroll;
        background-color: yellow;
        border:1px solid black;
        align-self: flex-end;
    }
    
<div class="container">
  <div id="block"></div>
  <button onclick='myFunct()'>CLICK</button>
</div>

Thanks to @TemaniAfif that point me.

like image 22
A. Meshu Avatar answered Nov 08 '22 16:11

A. Meshu