Why write this article

Sticky is not a new knowledge, the reason for writing this article is that RECENTLY in the process of implementing the effect, I found that MY understanding of Sticky has a deviation, and the code execution result is not as good as expected. Decided to write an article to study again.

What is a Sticky

Sticky (MDN translates to Sticky effect) is an optional value in the CSS property Position. Static, fixed, relative and absolute are used to describe the positioning of elements.

In terms of effect, Sticky looks like a mixture, which is described as relative before the page slides to the “critical point” and fixed when it reaches the “critical point”.

How to use

Only two conditions are required to use CSS Sticky.

position: sticky;
top: 0; // right/bottom/leftAny valid value can even be a negative pixel valueCopy the code

Top: 0 means that when the element slides to the distance from the viewport 0px and then slides again, the element pulls to the top. You can see the effect here (try changing the top value)

Compare the implementation of JS

Without CSS Sticky before, similar effects are implemented using JS. The general steps are as follows:

  1. Listen for the scroll event to calculate the distance of the target element from the viewport.
  2. When the distance is not satisfied, stay put.
  3. When the distance meets the condition, create a placeholder element and modify the positioning mode of the target element asfixed.
window.addEventListener('scroll'.() = > {
    const rect = elem.getBoundingClientRect();
    // Calculate the distance between the target element and the viewport
})
Copy the code

Search for the sticky keyword on NPM, there are also plenty of good packages to use. In order toreact-stickyFor example, it is created when conditions are metplaceholderElement (to prevent page jitter) while lettingheaderAs afixed.

On the right is theChrome Dev-ToolslayersPanel, the blue part is generatedplaceholder.

A comparison of the two schemes (I slowed down the CPU by 6x for magnification)

CSS scheme

Use CSS Sticky, the work is handed over to the GPU, does not occupy JS main thread resources, extremely smooth on the mobile terminal.

React Sticky

Since getBoundingClientRect needs to be repeatedly called in the Scroll Event callback, and getBoundingClientRect will trigger the page rearrangement and redraw, so the frame will get stuck if you are not careful. Just trying to achieve this effect (with no other content on the page) is not cost-effective.

The conclusion is: To achieve the Sticky effect, select the CSS Sticky first

A deviation in understanding

1. It is valid only in Containing Block.

> < div style = “text-indent: 22px;

.<div class="wrapper">
    <header>Sticky Header</header>
  </div>.Copy the code

According to the documentation, the Sticky effect only works within the Containing Block. When the Containing Block slides off the screen, Stickey Element slides off with it.

Modify the height of the Wrapper to see the effect.

.wrapper {
  height: 100px;
  background-color: #e6e6e6;
}
Copy the code

If multiple Sticky elements are put together, the first one will be pushed out by the next. In fact, it is not really pushed out, but Containing blocks will drag it away.

So here’s the code

2. Overflow is Sticky

Modify the code in the example to add overflow: auto to #root

#root {
  overflow: auto; 
}
Copy the code

The Sticky effect is lost again (the same is true for valid values that overflow is set to other non-visible values.)

After reading many relevant documents, I came to the following conclusion:

The offset value of the Sticky Element is calculated according to the nearest scrolling ancestor. If there is no matching ancestor Element, the viewport is used as the reference.

The problem is that if either overflow-x or overflow-y is not visible, it is considered to be the target Element to find. During the scrolling of the window, the offset value of the Sticky Element and the target ancestor Element it finds does not change. So Sticky doesn’t work.

The Sticky Effect can be restored if rolling occurs in the ancestral element that is “mismatched”.

#root {
  overflow: auto; 
  height: 100vh;
}
Copy the code

compatibility

Counting prefixed, the current COMPATIBILITY of CSS sticky mobile phone reaches 94.14%. If you need to take care of the remaining 5.86% users in your business, you can also use Polyfill or position: fixed.

A link to the

  • Uxdesign. Cc/position – st…
  • Codyhouse. Co/ds/componen…
  • medium.com/@elad/css-p…
  • Developer.mozilla.org/zh-CN/docs/…
  • Stackoverflow.com/questions/4…