Files
PC-Light-Forum/1.html
A1300399510 aa5a7058ad no message
2025-11-08 22:22:44 +08:00

205 lines
9.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>滚动触底固定</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 父容器:弹性布局,左右分栏 */
.matter {
display: flex;
width: 1200px;
margin: 0 auto;
gap: 20px; /* 左右间距 */
padding: 20px 0;
}
/* 左侧容器:高度较短(示例) */
.left {
width: 30%;
background: #f0f8fb;
padding: 20px;
border-radius: 8px;
/* 默认静态定位,滚动触底后改为 fixed */
position: static;
top: auto; /* 初始重置 */
bottom: 20px; /* 固定时距离底部的间距 */
}
/* 右侧容器:高度较长(示例) */
.right {
width: 70%;
background: #fef7fb;
padding: 20px;
border-radius: 8px;
position: static;
top: auto;
bottom: 20px;
}
/* 触底固定的样式 */
.fixed-bottom {
position: fixed;
/* 固定宽度(与默认布局一致) */
width: calc(30% - 10px); /* 30%宽度 - 一半gap避免布局偏移 */
max-height: calc(100vh - 40px); /* 最大高度不超过视口(可选) */
overflow: hidden; /* 固定后不再滚动 */
}
/* 右侧固定时的宽度修正与默认70%一致) */
.right.fixed-bottom {
width: calc(70% - 10px);
}
/* 页面足够长,确保能滚动 */
body {
min-height: 200vh;
background: #f8f9fa;
}
/* 示例内容样式 */
.content-item {
margin-bottom: 16px;
line-height: 1.6;
color: #333;
}
</style>
</head>
<body>
<div class="matter">
<div class="left" id="leftContainer">
<!-- 左侧内容:较短高度 -->
<h3>左侧内容(较短)</h3>
<div class="content-item">这是左侧内容的第一行。</div>
<div class="content-item">左侧内容相对较短,所以在滚动时会先触底。</div>
<div class="content-item">当滚动到一定程度时,左侧会固定在底部。</div>
<div class="content-item">此时右侧内容可以继续正常滚动。</div>
<div class="content-item">固定后,左侧内容不再随页面滚动。</div>
<div class="content-item">这是左侧的最后一行内容。</div>
</div>
<div class="right" id="rightContainer">
<!-- 右侧内容:较长高度 -->
<h3>右侧内容(较长)</h3>
<div class="content-item">这是右侧内容的第一行。</div>
<div class="content-item">右侧内容相对较长,可以滚动更多内容。</div>
<div class="content-item">右侧内容继续...这是第3行。</div>
<div class="content-item">右侧内容继续...这是第4行。</div>
<div class="content-item">右侧内容继续...这是第5行。</div>
<div class="content-item">右侧内容继续...这是第6行。</div>
<div class="content-item">右侧内容继续...这是第7行。</div>
<div class="content-item">右侧内容继续...这是第8行。</div>
<div class="content-item">右侧内容继续...这是第9行。</div>
<div class="content-item">右侧内容继续...这是第10行。</div>
<div class="content-item">右侧内容继续...这是第11行。</div>
<div class="content-item">右侧内容继续...这是第12行。</div>
<div class="content-item">右侧内容继续...这是第13行。</div>
<div class="content-item">右侧内容继续...这是第14行。</div>
<div class="content-item">右侧内容继续...这是第15行。</div>
<div class="content-item">右侧内容继续...这是第16行。</div>
<div class="content-item">右侧内容继续...这是第17行。</div>
<div class="content-item">右侧内容继续...这是第18行。</div>
<div class="content-item">右侧内容继续...这是第19行。</div>
<div class="content-item">右侧内容继续...这是第20行。</div>
</div>
</div>
<script>
// 获取DOM元素
const leftContainer = document.getElementById('leftContainer');
const rightContainer = document.getElementById('rightContainer');
const matter = document.querySelector('.matter');
// 记录容器原始样式
const originalLeftStyles = {
position: leftContainer.style.position,
width: leftContainer.style.width,
marginLeft: leftContainer.style.marginLeft
};
const originalRightStyles = {
position: rightContainer.style.position,
width: rightContainer.style.width,
marginRight: rightContainer.style.marginRight
};
// 处理滚动事件的核心函数
function handleScroll() {
// 获取matter容器的位置和尺寸
const matterRect = matter.getBoundingClientRect();
const matterLeft = matterRect.left;
const windowHeight = window.innerHeight;
// 获取左右容器的位置信息
const leftRect = leftContainer.getBoundingClientRect();
const rightRect = rightContainer.getBoundingClientRect();
// 计算左侧容器底部与视口底部的距离
const leftBottomToViewportBottom = windowHeight - leftRect.bottom;
// 计算右侧容器底部与视口底部的距离
const rightBottomToViewportBottom = windowHeight - rightRect.bottom;
// 左侧容器触底检测当左侧底部即将离开视口小于0且容器完全可见时固定左侧
if (leftBottomToViewportBottom < 20 && leftRect.top <= 0 && !leftContainer.classList.contains('fixed-bottom')) {
// 固定左侧,保持原位置水平对齐
leftContainer.classList.add('fixed-bottom');
leftContainer.style.left = `${matterLeft}px`;
leftContainer.style.bottom = '20px';
} else if (leftRect.top > 0 && leftContainer.classList.contains('fixed-bottom')) {
// 当左侧容器顶部重新进入视口时,取消固定
leftContainer.classList.remove('fixed-bottom');
// 恢复原始样式
Object.assign(leftContainer.style, originalLeftStyles);
}
// 右侧容器触底检测当右侧底部即将离开视口小于0且容器完全可见时固定右侧
if (rightBottomToViewportBottom < 20 && rightRect.top <= 0 && !rightContainer.classList.contains('fixed-bottom')) {
// 固定右侧,保持原位置水平对齐
rightContainer.classList.add('fixed-bottom');
rightContainer.style.right = `${window.innerWidth - (matterLeft + matterRect.width)}px`;
rightContainer.style.bottom = '20px';
} else if (rightRect.top > 0 && rightContainer.classList.contains('fixed-bottom')) {
// 当右侧容器顶部重新进入视口时,取消固定
rightContainer.classList.remove('fixed-bottom');
// 恢复原始样式
Object.assign(rightContainer.style, originalRightStyles);
}
}
// 窗口大小变化时的处理
function handleResize() {
// 重置所有固定状态
if (leftContainer.classList.contains('fixed-bottom')) {
leftContainer.classList.remove('fixed-bottom');
Object.assign(leftContainer.style, originalLeftStyles);
}
if (rightContainer.classList.contains('fixed-bottom')) {
rightContainer.classList.remove('fixed-bottom');
Object.assign(rightContainer.style, originalRightStyles);
}
// 重新触发滚动处理
handleScroll();
}
// 初始化
window.addEventListener('DOMContentLoaded', () => {
// 立即执行一次以初始化
handleScroll();
// 监听滚动事件
window.addEventListener('scroll', handleScroll);
// 监听窗口大小变化事件
window.addEventListener('resize', handleResize);
});
</script>
</body>
</html>