preface

Have you ever encountered the need to add a new child element to a DOM element and then automatically scroll to the location of the new child element if the new element is outside the scope of the container?

So let’s learn a little bit about dom element scrolling while implementing an image like the one above and some other scrolling features.

Dom properties and methods you need to know

ScrollTop, clientHeight, and scrollHeight

The scrollTop property is the difference between the top value for the contents of a container element and the top value for the viewport of a container element, that is, the part of the container where the content slides up out of the container viewport. You can modify this property to control the scrolling state.

ClientHeight is a DOM property that describes the height of the container.

ScrollHeight is a DOM property that describes the height of the container’s content.

The relationship between the three attributes is shown in the figure below:

getBoundingClientRect()

This method is used to get geometric attributes for the layout of elements, such as left, right, top, bottom, height, width, and so on.

srollBy(x,y)

The DOM container’s scrollTo method can be used to directly control how far the scrollbar scrolls. This method is handy when you need to scroll to a specified element.

srollTo(x,y)

The DOM container’s scrollTo method can be used to directly control the scrolling bar to a specified position. This method is handy when controlling the scroll bar to scroll to the top or bottom.

Implement rolling control

To prepare

Let’s start with an HTML

<! DOCTYPEhtml>
<html>
    <head>
       <title>Scrollbar Settings in detail</title>
       <style>
          #scroll_container{
              height: 500px;
              width: 500px;
              overflow-y: scroll;
              padding: 50px;
              box-sizing: border-box;
          }
          .scroll_item{
              height: 200px;
              width: 500px;
              margin-top: 20px;
              background-color: aquamarine;
              display: flex;
              align-items: center;
              justify-content: center;
          }
       </style>
    </head>
    <body>
       <div  id="scroll_container">
           <div  id="scroll_container">
               <div id="item1" class="scroll_item">
                   <span>1</span>
               </div>
               <div id="item2" class="scroll_item">
                    <span>2</span>
                </div>
                <div id="item3" class="scroll_item">
                    <span>3</span>
                </div>
                <div id="item4" class="scroll_item">
                    <span>4</span>
                </div>
                <div id="item5" class="scroll_item">
                    <span>5</span>
                </div> 
           </div>
           <button onclick="addItem()">Add an element</button>
       </div>
    </body>
    <script>
        let container=document.getElementById("scroll_container");
        let index=5;
        // Add an element
        function addItem(){
            index+=1;
            let item=`<div id="The ${'item'+index}" class="scroll_item">
                            <span>${index}</span>
                        </div>`;
            container.innerHTML+=item;  
            setTimeout(() = >{ scrollToIndex(); })}</script>
</html>
Copy the code

The code above contains a scrollable region and can add elements to the scrollable region or scroll to the specified element position, as shown below.

Use scrollTop

Basic implementation

As we’ve explained scrollTop, we can control the scrolling of the scrollbar by changing the value of the container element scrollTop. The larger the value of scrollTop is, the greater the scrolling distance of the scrollbar relative to the original state (when scrollTop is 0).

Add a scrollToBottom() method to the code above: scrollToBottom()

function scrollToBottom(){
    let y=container.scrollHeight-container.clientHeight;
    container.scrollTop=y;
}
Copy the code

If we want to scroll to the top, we just need to set scrollTop to 0:

function scrollToTop(){
    container.scrollTop=0;
}
Copy the code

We can also easily scroll to a specified element with the getBoundingClientRect() method, where getBoundingClientRect(). Top represents the distance between the top of the current element and the top of the viewport:

function scrollToElement(el){
     container.scrollTop+=el.getBoundingClientRect().top;
}
Copy the code

Add animation

  • Scroll to the bottom

But the above code is too rigid to scroll, so we can animate it, using setInterval(). Analysis of the implementation of animation effect process, animation is nothing more than the change of a variable in a certain period of time, so we first need to know two variables, variable (scrollTop) offset and change time, and offset is the final value of scrollTop minus the original value, Change duration is usually set to a parameter that can be modified. With that in mind, let’s take scrolling to the bottom as an example:

// First write a scrollToBottom function
function scrollToBottom(el){
              if(! el){ el=container; }/ / the original value
              let startTop=el.scrollTop;
              / / final value
              let endTop=el.scrollHeight-el.clientHeight;
              // Generate an animation control function
              let scrollAnimationFn=doAnimation(startTop,endTop,300,el);
              // Execute the animation every 10ms
              let interval=setInterval(() = >{
                scrollAnimationFn(interval)
              },10)}/ * * *@description: a factory function that generates the animation control function (using closures) *@param {startValue: original variable value endValue: final variable value duration: animation duration el: element to perform scrolling animation} 
 * @return: null
 */
function doAnimation(startValue,endValue,duration,el){
              // Use closures to save the variables dy and step(the distance of each animation scroll)
              let dy=0;
              let step=(endValue-startValue)/(duration/10);
              // Returns the animation control function
              return function(interval){
                  dy+=step;
                  if(dy>=endValue-startValue){
                      clearInterval(interval); } el.scrollTop+=step; }}Copy the code

Modify addItem to add a scroll to the bottom animation:

function addItem(){
            index+=1;
            let item=`<div id="The ${'item'+index}" class="scroll_item">
                            <span>${index}</span>
                        </div>`;
            container.innerHTML+=item;  
            setTimeout(() = >{
                // scrollToIndex();scrollToBottom(container); })}Copy the code

Then add a button to scroll to the bottom of the HTML:

<button onclick="scrollToBottom()">Scroll to the bottom</button>
Copy the code

  • Scroll to the top

Follow the above method can also achieve a common drive picture scroll to the top:

// Write a scrollToTop function
function scrollToTop(el){
              if(! el){ el=container; }/ / the original value
              let startTop=el.scrollTop;
              / / final value
              let endTop=0;
              // Generate an animation control function
              let scrollAnimationFn=doAnimation(startTop,endTop,300,el);
              // Execute the animation every 10ms
              let interval=setInterval(() = >{
                scrollAnimationFn(interval)
              },10)}Copy the code

In order to adapt to scrolling to the bottom, we need to modify the judgment of animation stop time. The modified doAnimation() function is as follows:

function doAnimation(startValue,endValue,duration,el){
              // Use closures to save the variables dy and step(the distance of each animation scroll)
              let dy=0;
              let step=(endValue-startValue)/(duration/10);
              return function(interval){
                  dy+=step;
                  // use absolute value judgment
                  if(Math.abs(dy)>=Math.abs(endValue-startValue)){
                      clearInterval(interval); } el.scrollTop+=step; }}Copy the code

Finally, we’ll add a scroll bottom button to the HTML:

<button onclick="scrollToTop()">Scroll to the top</button>
Copy the code

The realization effect is shown as follows:

  • Scroll to the specified element

Start by adding the required buttons and input fields for the HTML element:

<input type="number" placeholder="Please enter the index element to scroll to." style="width: 200px;"/>
<button onclick="scrollToElement()">Scroll to the specified element</button>
Copy the code

Add an animation function that scrolls the specified element:

function scrollToElement(containerEl,el){
            if(! containerEl){/ / the parent element
                containerEl=container;
            }
            if(! el){// Get the element to scroll to
                let input=document.getElementsByTagName('input') [0];
                let id='item'+input.value;
                if(! input.value){ id='item'+index;
                }
                el=document.getElementById(id);
            }
            let startTop=containerEl.scrollTop;
            let endTop=startTop+el.getBoundingClientRect().top;
            let scrollAnimationFn=doAnimation(startTop,endTop,300,containerEl);
            let interval=setInterval(() = >{
                scrollAnimationFn(interval)
            },10)}Copy the code

The implementation effect is as follows:

Use scrollTo()

ScrollTo (x,y) is used in the same way that the scrollTop property is used. The scrollTo() method of the parent element can control the scroll bar to the specified position, in effect setting the value of scrollTop. Here’s an example:

// Use the y axis as an example
element.scrollTo(0,y);
element.scrollTop=y;
// The above two sentences have the same effect.
Copy the code

Therefore, using the scrollTo() method to control the scrollbar is basically the same as using scrollTop. We just need to modify the doAnimation() function as follows:

function doAnimation(startValue,endValue,duration,el){
              // Use closures to save the variables dy and step(the distance of each animation scroll)
              let dy=0;
              let step=(endValue-startValue)/(duration/10);
              return function(interval){
                  dy+=step;
                  if(Math.abs(dy)>=Math.abs(endValue-startValue)){
                      clearInterval(interval);
                  }
                  //el.scrollTop+=step; // Change this line of code to the following
                  el.scrollTo(0,el.scrollTop+step); }}Copy the code

The implementation effect is the same as using scrollTop.

Use scrollBy()

Basic implementation

We can also use scrollBy(x,y) to control the scrollbar. As explained above, the scrollBy() method controls the scrollbar to scroll a specified distance (note not position). ScrollBy () makes it easy to scroll to the specified element as follows:

function scrollToElement(containerEl,el){
    Since getBoundingClientRect().top is the distance between the top of the child element and the top of the parent element, this value is the offset of the child element relative to the parent element. We pass this value into scrollBy, which scrolls to the specified element
    containerEl.scrollBy(0,el.getBoundingClientRect().top);
}
Copy the code

Scroll to the bottom:

function scrollToBottom(containerEl){
    let dy=containerEl.scrollHeight-containerEl.clientHeight;
    containerEl.scrollBy(0,dy);
}
Copy the code

Scroll to the top

function scrollToTop(containerEl){
    let dy=-(containerEl.scrollHeight-containerEl.clientHeight);
    containerEl.scrollBy(0,dy);
}
Copy the code

Add animation

Here we modify the function generated by the animation, because the argument to scrollBy() is the offset of the variable, so we make the following changes:

        function scrollToBottom(containerEl){
              if(! containerEl){ containerEl=container; }//dy is the offset
              let dy=containerEl.scrollHeight-containerEl.clientHeight;
              let scrollAnimationFn=doAnimation(dy,300,containerEl);
              let interval=setInterval(() = >{
                scrollAnimationFn(interval)
              },10)}function scrollToTop(containerEl){
              if(! containerEl){ containerEl=container; }//dy is the offset
              let dy=-(containerEl.scrollHeight-containerEl.clientHeight);
              let scrollAnimationFn=doAnimation(dy,300,containerEl);
              let interval=setInterval(() = >{
                scrollAnimationFn(interval)
              },10)}function scrollToElement(containerEl,el){
            if(! containerEl){ containerEl=container; }if(! el){let input=document.getElementsByTagName('input') [0];
                let id='item'+input.value;
                if(! input.value){ id='item'+index;
                }
                el=document.getElementById(id);
            }
           //dy is the offset
            letDy = el. GetBoundingClientRect (). The top;letScrollAnimationFn = doAnimation (dy,300,containerEl);
            let interval=setInterval(() = >{
                scrollAnimationFn(interval)
            },10)}/ * * *@description: 
          * @param {type} 
          * @return: * /
         function doAnimation(dy,duration,el){
              // Use closures to save variables such as exe_dy and step (the distance of each animation scroll)
              let exe_dy=0;// The offset that has been executed
              let step=dy/(duration/10);
              return function(interval){
                  exe_dy+=step;
                  if(Math.abs(exe_dy)>=Math.abs(dy)){
                      clearInterval(interval);
                  }
                  el.scrollBy(0,step); }}Copy the code

The implementation effect is the same as using scrollTop.

The last

The above 👆 is my detailed summary and explanation of DOM scrollbar control, as well as some basic usage methods. Please correct any mistakes.

If you feel ok, please give a thumbs up