人人都会AI编程

14.6 屏幕信息、窗口滚动操作

更新时间:2026-07-11

在浏览器环境中,获取屏幕信息和控制窗口滚动是常见的交互需求。这些能力分别通过 screen 对象和 window 对象上的滚动相关 API 实现。本节将介绍它们的核心用法、常见场景以及需要注意的细节。

14.6.1 获取屏幕信息:screen 对象

screenwindow 上的一个只读属性,它提供了用户显示器的相关信息。注意,这些信息反映的是物理屏幕,而不是浏览器窗口。常用属性如下:

| 属性 | 含义 | 典型用途 |
|------|------|----------|
| 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.pageXOffsetwindow.pageYOffset(或简写为 scrollXscrollY)。也可以通过 document.documentElement.scrollTop(标准模式)或 document.body.scrollTop(怪异模式)获取,但前者更简单可靠。

// 获取垂直滚动距离(推荐)
const scrollY = window.scrollY || window.pageYOffset;

// 获取水平滚动距离
const scrollX = window.scrollX || window.pageXOffset;

对于某个可滚动的元素(如 overflow: auto 的容器),直接使用其 scrollTopscrollLeft 属性。

const container = document.querySelector('.scroll-area');
console.log(container.scrollTop);  // 元素内部滚动了多少像素

设置滚动位置

window 对象提供了三种方法:

  1. 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'   // 平滑过渡
   });
   
  1. window.scrollBy(x, y)window.scrollBy(options)

相对于当前位置进行滚动(累加)。

   // 向下滚动 500px
   window.scrollBy(0, 500);

   // 平滑向左滚动 200px
   window.scrollBy({
     left: -200,
     behavior: 'smooth'
   });
   
  1. 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.innerWidthwindow.innerHeight 返回包含滚动条在内的视口尺寸(CSS 像素),是布局和滚动逻辑的常用基准。而 document.documentElement.clientWidth / clientHeight 则是不包含滚动条的视口尺寸。两者的区别在某些场景下(如移动端软键盘弹出)会影响判断,实际开发中应根据需要选择。

小结:掌握 screen 可以完成与屏幕相关的设备检测和窗口定位;而滚动 API 则让你能够精细控制页面滚动行为,提升用户体验。在实现过程中,始终记得性能优化,避免在高频事件中执行高成本操作。