sticky
css属性position为sticky的元素,根据正常的文档流(flow of the document)进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和 containing block (最近块级祖先 nearest block-level ancestor),包括table-related元素,基于top
, right
, bottom
, 和 left
的值进行偏移。该偏移量不会影响任何其他元素的位置。
sticky元素总是创建一个新的层叠上下文(stacking context) ,一个sticky元素会“固定”在离它最近的一个拥有“滚动机制”的祖先上(当该祖先的overflow 是 hidden, scroll, auto, 或 overlay时),即便这个祖先不是最近的真实可滚动祖先。(Github issue on W3C CSSWG )
[css3 positioning] support position:sticky inside an overflow:hidden|auto on general parents · Issue #865 · w3c/csswg-drafts
参考链接:MDN-position
实际效果展示
下面看一个关于粘性定位元素滑动时的效果图。
可以看到list在向上滑动时,当 list item 17 stickyTop
滑到在滚动块的顶部时,便粘在顶部不在跟着滑动,其余元素继续滑动,该元素的偏移量 top
为0。当list向下滑动式 list item 24 stickyBottom
滑到底部时便粘在底部,其余元素继续滑动,该元素的偏移量 bottom
为0。
list item 17 stickyTop
和 list item 24 stickyBottom
的css属性如下:
// list item 17 stickyTop
{
position : sticky ;
top : 0 ;
background : aqua ;
}
// list item 24 stickyBottom
{
position : sticky ;
bottom : 0 ;
background : aqua ;
}
修改偏移量后再次尝试
list item 17 stickyTop
和 list item 24 stickyBottom
的css属性如下:
// list item 17 stickyTop
{
position : sticky ;
top : 30px ;
background : aqua ;
}
// list item 24 stickyBottom
{
position : sticky ;
bottom : 40px ;
background : aqua ;
}
修改之后,17
在滑动时粘在距离顶部30px的位置,24
粘在距离底部40px的位置。
应用场景
长列表滑动时,最近子标题固定(粘在)顶部
表格的表头、首行、首列、末列滑动时分别固定顶部、顶部、左侧、右侧
页面滑动时,重要信息块粘在顶部
页面滑动时,特定元素始终保持在页面之内。
Note
注意分清粘性定位的作用域,层叠上下文,避免因多个滚动块或者滚动块层级有误造成未达到目标效果
案例代码
jsx
import React from 'react' ;
import classnames from 'classnames' ;
import styles from './dashboard.less' ;
const arr = new Array ( 40 ). fill ({});
const list = arr . map (( val , idx ) => {
if ( idx === 17 ) {
return {
... val ,
key : idx ,
title : 'stickyTop' ,
sticky : true ,
className : styles . stickyTop ,
};
}
if ( idx === 24 ) {
return {
... val ,
key : idx ,
title : 'stickyBottom' ,
sticky : true ,
className : styles . stickyBottom ,
};
}
return { ... val , key : idx };
});
export default () => {
return (
< div className = { styles . container } >
< div className = { styles . wrap } >
< div className = { styles . list } >
{ list . map (( v , index ) => (
< div
className = { classnames (
styles . item ,
v . sticky && v . className + ` ${ styles . sticky } ` ,
) }
key = { index }
>
{ `list item ${ index } ${ v . title || '' } ` }
</ div >
)) }
</ div >
</ div >
</ div >
);
};
less
.container {
width : 400px ;
height : 500px ;
margin : auto ;
overflow : auto ;
background : aquamarine ;
.wrap {
display : flex ;
height : 1000px ;
.list {
width : 240px ;
height : 360px ;
margin : auto ;
overflow : auto ;
background : #fff ;
.item {
color : #333 ;
font-size : 16px ;
}
.sticky {
background : aqua ;
}
.stickyTop {
position : sticky ;
top : 0 ;
}
.stickyBottom {
position : sticky ;
bottom : 0 ;
}
}
}
}