在浏览器环境中,获取屏幕信息和控制窗口滚动是常见的交互需求。这些能力分别通过 screen 对象和 window 对象上的滚动相关 API 实现。本节将介绍它们的核心用法、常见场景以及需要注意的细节。
14.6.1 获取屏幕信息:screen 对象
screen 是 window 上的一个只读属性,它提供了用户显示器的相关信息。注意,这些信息反映的是物理屏幕,而不是浏览器窗口。常用属性如下:
| 属性 | 含义 | 典型用途 |
|------|------|----------|
| screen.width | 屏幕总宽度(像素) | 判断设备分辨率 |
| screen.height | 屏幕总高度(像素) | 判断设备分辨率 |
| screen.availWidth | 可用宽度(排除系统任务栏等) | 确定窗口最大宽度 |
| screen.availHeight | 可用高度(排除系统任务栏等) | 确定窗口最大高度 |
| screen.colorDepth | 颜色深度(位数) | 极少用到 |
| screen.pixelDepth | 像素深度,通常与 colorDepth 相同 | 极少用到 |
| screen.orientation | 屏幕方向(需 Web API 支持) | 判断横竖屏 |
实用示例:判断是否为低分辨率屏幕
if (screen.width < 1024) {
console.log('当前屏幕宽度较小,可能需要适配窄屏布局');
}
实用示例:窗口居中打开
const popupWidth = 600;
const popupHeight = 400;
const left = (screen.availWidth - popupWidth) / 2;
const top = (screen.availHeight - popupHeight) / 2;
window.open(
'https://example.com',
'popup',
`width=${popupWidth},height=${popupHeight},left=${left},top=${top}`
);
注意事项:
screen.width/height是物理像素,在高分辨率屏(Retina)上可能不等于 CSS 像素。例如,一台 2x 缩放的 MacBook,screen.width可能为 1440,但 CSS 像素宽度实际对应的是 1440 / 2 = 720。我们通常使用 CSS 像素进行布局,所以screen信息更适用于弹窗定位或设备特征检测,而不是布局计算。screen.availHeight在移动端浏览器中会频繁变化(如键盘弹起、地址栏显隐),不宜用作固定尺寸逻辑。
14.6.2 窗口滚动操作
页面滚动是用户交互中最常见的动作之一,JavaScript 提供了多种方式获取和设置滚动位置。
获取滚动位置
传统上使用 window.pageXOffset 和 window.pageYOffset(或简写为 scrollX、scrollY)。也可以通过 document.documentElement.scrollTop(标准模式)或 document.body.scrollTop(怪异模式)获取,但前者更简单可靠。
// 获取垂直滚动距离(推荐)
const scrollY = window.scrollY || window.pageYOffset;
// 获取水平滚动距离
const scrollX = window.scrollX || window.pageXOffset;
对于某个可滚动的元素(如 overflow: auto 的容器),直接使用其 scrollTop 和 scrollLeft 属性。
const container = document.querySelector('.scroll-area');
console.log(container.scrollTop); // 元素内部滚动了多少像素
设置滚动位置
window 对象提供了三种方法:
window.scrollTo(x, y)或window.scrollTo(options)
将页面滚动到指定的绝对坐标。
// 滚动到顶部
window.scrollTo(0, 0);
// 滚动到底部(假设页面总高度 5000)
window.scrollTo(0, document.body.scrollHeight);
// 使用 options 对象,平滑滚动
window.scrollTo({
top: 500,
left: 0,
behavior: 'smooth' // 平滑过渡
});
window.scrollBy(x, y)或window.scrollBy(options)
相对于当前位置进行滚动(累加)。
// 向下滚动 500px
window.scrollBy(0, 500);
// 平滑向左滚动 200px
window.scrollBy({
left: -200,
behavior: 'smooth'
});
element.scrollIntoView()
将某个元素滚动到可视区域,这是最符合直觉的方式。
const target = document.getElementById('section-3');
target.scrollIntoView(); // 默认对齐到顶部
// 传入参数调整对齐方式和动画
target.scrollIntoView({
behavior: 'smooth', // 平滑动画
block: 'center' // 滚动后元素出现在视口中心
});
block 可选值:'start'(默认,对齐顶边)、'center'、'end'、'nearest'。
实用场景
- 回到顶部按钮
document.getElementById('back-to-top').addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
- 锚点导航平滑滚动
可以劫持锚点链接的点击,使用 scrollIntoView 替代默认的暴力跳转。
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
}
});
});
- 无限滚动加载
监听窗口滚动位置,当接近底部时触发数据加载。
window.addEventListener('scroll', () => {
const scrollTop = window.scrollY;
const windowHeight = window.innerHeight;
const docHeight = document.documentElement.scrollHeight;
if (scrollTop + windowHeight >= docHeight - 200) {
loadMoreContent();
}
});
性能优化提醒
滚动事件会以极高的频率触发(每秒几十次),因此在 scroll 回调中应避免执行高开销操作(如大量 DOM 读取或修改),否则会造成卡顿。通常结合防抖或节流来优化。
// 节流示例:每 200ms 最多执行一次
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
// 在这里执行滚动相关的逻辑
console.log('滚动位置:', window.scrollY);
ticking = false;
});
ticking = true;
}
});
14.6.3 判断元素是否在视口内
通过滚动位置配合元素的位置信息,可以判断元素是否进入视口,常用于懒加载图片或动画触发。
传统方式需要手动计算:
const rect = element.getBoundingClientRect();
const isInView = (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= window.innerHeight &&
rect.right <= window.innerWidth
);
更现代的方式是使用 Intersection Observer API(详见第 30 章),它更高效,不会引起大量重复计算:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('元素进入视口', entry.target);
observer.unobserve(entry.target);
}
});
});
observer.observe(document.querySelector('.lazy-image'));
14.6.4 浏览器窗口大小与视口尺寸
操作滚动时,理解窗口尺寸至关重要。window.innerWidth 和 window.innerHeight 返回包含滚动条在内的视口尺寸(CSS 像素),是布局和滚动逻辑的常用基准。而 document.documentElement.clientWidth / clientHeight 则是不包含滚动条的视口尺寸。两者的区别在某些场景下(如移动端软键盘弹出)会影响判断,实际开发中应根据需要选择。
小结:掌握 screen 可以完成与屏幕相关的设备检测和窗口定位;而滚动 API 则让你能够精细控制页面滚动行为,提升用户体验。在实现过程中,始终记得性能优化,避免在高频事件中执行高成本操作。