【前端】使用JavaScript实现类似sticky的布局

实现原理

当元素滑动到一个容器阈值时将其定位变为fixed。由于我的项目要适配很多浏览器,因此用代码实现了,css的sticky暂时不适用,大家可以根据项目来调整

效果

请添加图片描述

直接上代码

html

<div id="sticky-container">
	<div id="sticky-box">
         <div id="sticky-top">
             <div class="">
                 xxx
             </div>
             <div class="">
                 xxx
             </div>
             <div class="">
                xxx
             </div>
         </div>
     </div>
</div>

javascript

// this.$nextTick是vue的方法,如果是原生代码可以去除掉,这里展示的vue内的写法
{
	mounted() {
		this.$nextTick(() => {
		    this.stickyLayout()
		    window.onresize = () => {
		        this.stickyLayout()
		    }
		})
	},
	destroyed() {
		 document.removeEventListener("scroll", this.scrollHandler);
	},
	methods: {
		// 实现粘性布局
        stickyLayout() {
            let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
            // 获取要粘性布局的父容器
            let stickyContainer = document.getElementById("sticky-container");
            // 初始化吸顶距离
            let stickyDis = stickyContainer.getBoundingClientRect().top + scrollTop;
            // 粘性布局后这个容器position:fixed
            let stickyTop = document.getElementById("sticky-top");
            let stickyHeight = stickyTop.clientHeight
            // 初始化top的值
            let topDir = stickyTop.offsetTop
            //一般这个footer大家看情况来加上可以去掉,我这个处理是为了让容器不能碰到最下面的元素
            let footer = document.getElementById('footer')
            let footerTop = footer.offsetTop
            // end
            if(scrollTop < stickyDis) {
                // stickyTop该容器的position改为fixed
                stickyTop.style = ""
            }
            else {
                stickyTop.style.position = "fixed";
                // 大家根据实际情况来,一般用来避免这个容器超出显示
                if(scrollTop + stickyHeight + topDir > footerTop) {
                    console.log("超过了底部容器")
                    // 超过了这个容器
                    stickyTop.style.top = footerTop - (scrollTop + stickyHeight + topDir) + 'px'
                }
                else {
                    stickyTop.style.top = topDir + 'px'  
                }
            }
            document.removeEventListener("scroll", this.scrollHandler);
            document.addEventListener("scroll", this.scrollHandler);
        },
        scrollHandler() {
            let top = document.body.scrollTop || document.documentElement.scrollTop;
             // 获取要粘性布局的父容器
            let stickyContainer = document.getElementById("sticky-container");
            // 初始化吸顶距离
            let stickyDis = stickyContainer.getBoundingClientRect().top + top;
            // 粘性布局后这个容器position:fixed
            let stickyTop = document.getElementById("sticky-top");
            let stickyHeight = stickyTop.clientHeight
            // 初始化top的值
            let topDir = stickyTop.offsetTop
            let footer = document.getElementById('footer')
            let footerTop = footer.offsetTop
            // 如果超过了这个距离
            if(top < stickyDis) {
                // stickyTop该容器的position改为fixed
                stickyTop.style = ""
            }
            else {
                stickyTop.style.position = "fixed";
                if(top + stickyHeight + topDir > footerTop) {
                    // 超过了这个容器
                    stickyTop.style.top = footerTop - (top + stickyHeight + topDir) + 'px'
                }
                else {
                    stickyTop.style.top = topDir + 'px'  
                }
            }
        },
	}
}

css

/* 并非完整样式,但主要的样式是这样的 */
#sticky-container {
		 display: flex;
        flex-direction: row;
        position: relative;
        width: 1200px;
}

#sticky-box {
	flex: 1;
    background-color: white;
    padding: 149px 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 400px;
}

#sticky-top {
    display: flex;
    flex-direction: column;
    align-items: center;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值