preface

In practical applications, scrolling to the top of the page or a location is often used. Generally, simply use anchor points or js to set document.body.scrollTop to 0. The result is that the page flashes and rolls to the specified location. What we want is a little bit of buffering.

Modern browsers are increasingly aware of this need. ScrollIntoView means to scroll to the visual, CSS provides the scroll behavior property, and JS has the element.scrollintoView () method.

scroll-behavior

Scroll – behaviors attribute value for auto | smooth | inherit | unset

scroll-behavior: smooth; It’s the cushioning we want. On PC browsers, the default page scroll is on the < HTML > tag, and on mobile most scroll on the tag. If we want to smooth “back to the top”, simply add:

html.body {
  scroll-behavior: smooth;
}
Copy the code

Specifically, writing on the container element smoothen the scrolling of the container (not triggered by mouse gestures) beyond the < HTML >, tags.

Using this CSS property, you can switch the original pure CSS tags in one step to a smooth transition effect.

.tab label {
  padding: 10px;
  border: 1px solid #ccc;
  margin-right: -1px;
  text-align: center;
  float: left;
  overflow: hidden;
}

.tab::after {
  content: "";
  display: table;
  clear: both;
}

.box {
  height: 200px;
  border: 1px solid #ccc;
  scroll-behavior: smooth;
  overflow: hidden;
  margin-top: 10px;
}

.item {
  height: 100%;
  position: relative;
  overflow: hidden;
}

.item input {
  position: absolute;
  top: 0;
  height: 100%;
  width: 1px;
  border: 0;
  padding: 0;
  margin: 0;
  clip: rect(0 0 0 0);
}
Copy the code
<h1>Pure CSS TAB</h1>
<div class="tab">
  <label for="tab1">TAB 1</label>
  <label for="tab2">TAB 2</label>
  <label for="tab3">TAB. 3</label>
</div>
<div class="box">
  <div class="item">
    <input type="text" id="tab1">
    <p>TAB 1 content</p>
  </div>
  <div class="item">
    <input type="text" id="tab2">
    <p>TAB 2 content</p>
  </div>
  <div class="item">
    <input type="text" id="tab3">
    <p>TAB 3 content</p>
  </div>
</div>
Copy the code

Implementation effect

You can also poke here

Let’s take a look at the CSS property Scroll behavior support in major browsers

The support is not very good, so a line of CSS code can be applied to the best of course, not degenerate into a flash effect. Now take a look at the API provided by JS.

Element.scrollIntoView()

The element.scrollintoView () method scrolls the current Element into the viewable area of the browser window.

element.scrollIntoView(); // Equivalent to element.scrollinToView (true)

element.scrollIntoView(alignToTop); // Boolean element. ScrollIntoView (scrollIntoViewOptions); // Object parameters

Parameter alignToTop

A Boolean value:

  • If it istrueThe top of the element will be aligned with the top of the visible area of the scroll area in which it is located. The correspondingscrollIntoViewOptions: {block: "start", inline: "nearest"}. This is the default value for this parameter.
  • If it isfalseThe bottom of the element will be aligned with the bottom of the visible area of the scroll area in which it is located. The correspondingscrollIntoViewOptions: {block: "end", inline: "nearest"}.

Parameter scrollIntoViewOptions

An object with options:

{
  behavior: "auto"  | "instant" | "smooth".block:    "start" | "end",}Copy the code
  • Behavior optionally defines one of the slow animations, “auto”, “instant”, or “smooth”. The default is “auto”.

  • Block can be one of “start”, “Center “, “end”, or “nearest”. The default is “Center”.

  • Inline can be one of “start”, “Center “, “end”, or “nearest”. The default is “nearest”.

Browser support

We can also use CSS to set scroll behavior: smooth; Scroll effect, use target.scrollintoView () when performing the scroll to achieve the “perfect scroll” (not so perfect) effect.

Backwards compatible

In order to achieve the same (similar) effect for all browsers, it is necessary to find out the remaining browsers that do not support the Scroll behavior property and use JS to complete the mission.

Determine whether support is supportedscroll-behaviorattribute

Very simple, with the following line of code

if(typeof window.getComputedStyle(document.body).scrollBehavior === 'undefined') {
  // Compatible with js code
} else {
  // Native scroll API
  // Element.scrollIntoView()
}
Copy the code

Check whether the scroll behavior property is supported and use the native element.scrollintoView () to scroll directly; otherwise, it is processed backwards.

Buffer algorithm

The intuitive effect of buffering is to go slower and slower until you stop, that is, moving less and less distance in the same amount of time. This allows you to set a timer that moves to the buffer rate of the distance from the current point to the target point (e.g. 1/2, 1/3…). For example, if the buffer rate is set to 2, the current distance from the target point is 64px, the next second is 32px, then 16px, then 8px… , reaches a certain threshold, namely:

var position = position + (destination - position) / n;
Copy the code

Here’s a simple demo where you click the “back to top” button in the lower right and scroll to the top.

<div class="content">
    <p>A lot of content...</p>.</div>
  <section class="back-to-top">Back to the top</section>
Copy the code
.content {
  height: 3000px;
  border: 1px solid #ccc;
  box-shadow: 0 0 2px solid;
}

.back-to-top {
  width: 18px;
  padding: 10px;
  border: 1px solid #ccc;
  box-shadow: 0 0 2px # 333;
  position: fixed;
  right: 20px;
  bottom: 40px;
}

.back-to-top:hover {
  cursor: pointer;
}
Copy the code
var scrollTopSmooth = function (position) {
  // There is no native 'requestAnimationFrame', use 'setTimeout' simulation instead
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function (cb) {
      return setTimeout(cb, 17);
    };
  }
  // The current scrolling height
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  // step
  var step = function () {
    var distance = position - scrollTop;
    scrollTop = scrollTop + distance / 5;
    if (Math.abs(distance) < 1) {
      window.scrollTo(0, position);
    } else {
      window.scrollTo(0, scrollTop); requestAnimationFrame(step); }}; step(); } $backToTop =document.querySelector('.back-to-top')
$backToTop.addEventListener('click'.function () {
  scrollTopSmooth(0);
}, false);
</script>
Copy the code

rendering

Or poke here

Simple packaging

In the small demo above, the buffering algorithm is coupled with the current rolling business code, so let’s separate out a single function.

/** * buffer function *@param {Number} Position Current scroll position *@param {Number} Destination Indicates the destination location *@param {Number} Rate Slow rate *@param {Function} The current position of the callback function and whether to end */
var easeout = function (position, destination, rate, callback) {
  if (position === destination || typeofdestination ! = ='number') {
    return false;
  }
  destination = destination || 0;
  rate = rate || 2;

  // There is no native 'requestAnimationFrame', use 'setTimeout' simulation instead
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function (fn) {
      return setTimeout(fn, 17); }}var step = function () {
    position = position + (destination - position) / rate;
    if (position < 1) {
      callback(destination, true);
      return;
    }
    callback(position, false);
    requestAnimationFrame(step);
  };
  step();
}
Copy the code

After splitting, the small buffer algorithm can be called repeatedly, and is applicable to scrolling to the specified position (not just to the top) and buffer rate (to control scrolling speed).

var scrollTopSmooth = function (position) {
  // The current scrolling height
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  easeout(scrollTop, 0.5.function (val) {
    window.scrollTo(0, val);
  });
}

$backToTop = document.querySelector('.back-to-top')
$backToTop.addEventListener('click'.function () {
  scrollTopSmooth(0);
}, false);
Copy the code

conclusion

In summary, a simple implementation of a perfect scroll can be noted below

  1. <html>.<body>Tag along withscroll-behavior: smooth;Properties;
  2. Check whether the current browser supports itscrollBehaviorProperties;
  3. Use the native scroll API directly if supportedElement.scrollIntoView();
  4. If not, use JS small buffer algorithm for compatibility processing.

The ~