直接设置根元素(<html>)的宽度(最推荐)

这是最常用且最灵活的方法,我们不直接设置整个页面的宽度,而是设置根元素 <html> 的宽度,然后让页面内的所有其他元素(如 <body>、容器等)通过继承或相对单位(如 , vw, rem)来适应。

js设置网页宽度自适应屏幕
(图片来源网络,侵删)

核心思想:

  1. 监听 windowresize 事件。
  2. 在事件处理函数中,获取当前窗口的宽度 window.innerWidth
  3. 将这个宽度值直接赋给 <html> 元素的 style.width

代码示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">JS 自适应宽度示例</title>
    <style>
        /* 初始样式,让内容居中并显示背景色 */
        body {
            margin: 0;
            font-family: sans-serif;
            background-color: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh; /* 使body至少占满整个视口高度 */
        }
        .content-box {
            background-color: white;
            padding: 20px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
            /* 这个宽度将由JS动态设置,这里给一个初始值 */
            width: 800px; 
            text-align: center;
        }
        /* 当html元素有js-width类时,应用动态宽度 */
        .js-width .content-box {
            /* 使用calc()可以设置最大宽度,防止在大屏幕上过宽 */
            width: calc(100% - 40px); /* 100%是相对于html的宽度,减去padding */
            max-width: 1200px; /* 可选,设置一个最大宽度 */
            margin: 0 auto; /* 确保在小于最大宽度时也能居中 */
        }
    </style>
</head>
<body>
    <div class="content-box">
        <h1>自适应宽度容器</h1>
        <p>调整浏览器窗口大小,观察此容器的变化。</p>
        <p>当前窗口宽度: <span id="window-width">-</span>px</p>
    </div>
    <script>
        // 等待DOM完全加载后执行
        document.addEventListener('DOMContentLoaded', () => {
            const htmlElement = document.documentElement;
            const windowWidthSpan = document.getElementById('window-width');
            // 定义一个函数来更新宽度
            function updateWidth() {
                const width = window.innerWidth;
                // 将宽度设置到html元素的style属性中
                htmlElement.style.width = `${width}px`;
                // 同时更新页面中显示的宽度数值
                windowWidthSpan.textContent = width;
            }
            // 初始调用一次,设置初始宽度
            updateWidth();
            // 监听窗口大小改变事件
            window.addEventListener('resize', updateWidth);
        });
    </script>
</body>
</html>

优点:

  • 集中控制:所有宽度自适应的逻辑都由 <html> 元素统一管理,页面其他元素只需通过CSS继承或相对单位即可适应。
  • 灵活性高:可以结合CSS媒体查询(Media Queries)进行更精细的控制,你可以只在窗口宽度小于某个值时才执行JS自适应逻辑。
  • 性能较好:现代浏览器对 resize 事件的处理已经非常优化,配合防抖(debounce)技术可以轻松应对频繁的窗口调整。

使用相对单位(CSS原生方案,无需JS)

在很多情况下,你甚至不需要 JavaScript 就可以实现完美的自适应,CSS 提供了强大的相对单位,这是现代网页设计的首选方案。

核心单位:

  • vw (Viewport Width):1vw 等于视口宽度的 1%。width: 50vw; 表示元素的宽度是视口宽度的一半。
  • (Percentage):相对于父元素的宽度,如果父元素的宽度是自适应的,子元素使用 也能实现自适应。

示例: 只需要修改上面的 CSS,移除 JS 即可。

/* 移除 JS 相关的类和样式 */
.content-box {
    background-color: white;
    padding: 20px;
    box-shadow: 0 0 10px rgba(0,0,0,0.1);
    /* 直接使用 vw 或 % */
    width: 90vw; /* 宽度为视口宽度的90% */
    max-width: 1200px; /* 依然建议设置最大宽度 */
    margin: 0 auto;
    text-align: center;
}

优点:

  • 性能最佳:无需 JS 计算和重排,由浏览器原生渲染,性能开销最小。
  • 代码简单:纯CSS实现,逻辑清晰,易于维护。
  • 响应式:天然适合响应式设计。

何时使用 JS? 当 CSS 相对单位无法满足复杂需求时,才需要考虑 JS。

  • 的复杂布局:需要根据窗口宽度动态计算并设置多个元素的精确位置和大小。
  • 交互式画布或图表:如 Canvas、SVG 或 ECharts、D3.js 等,需要根据容器尺寸重新绘制。
  • 第三方库的兼容:某些老旧的库可能无法很好地响应CSS的变化,需要手动触发更新。

结合防抖(Debounce)优化性能

当用户拖拽调整窗口大小时,resize 事件会非常频繁地触发,如果每次触发都执行我们的 updateWidth 函数,可能会导致性能问题(卡顿)。

防抖技术可以确保函数在停止触发一段时间后(200ms)才执行一次,从而避免不必要的计算。

代码示例(在方法一的基础上修改):

<script>
    document.addEventListener('DOMContentLoaded', () => {
        const htmlElement = document.documentElement;
        const windowWidthSpan = document.getElementById('window-width');
        // 防抖函数
        function debounce(func, delay) {
            let timeoutId;
            return function(...args) {
                // 清除之前的定时器
                clearTimeout(timeoutId);
                // 设置新的定时器
                timeoutId = setTimeout(() => {
                    func.apply(this, args);
                }, delay);
            };
        }
        function updateWidth() {
            const width = window.innerWidth;
            htmlElement.style.width = `${width}px`;
            windowWidthSpan.textContent = width;
        }
        // 创建一个防抖后的版本,延迟200毫秒
        const debouncedUpdateWidth = debounce(updateWidth, 200);
        // 初始调用
        updateWidth();
        // 使用防抖后的函数监听事件
        window.addEventListener('resize', debouncedUpdateWidth);
    });
</script>

总结与最佳实践

方法 适用场景 优点 缺点
CSS 相对单位 (vw, ) 绝大多数布局场景,特别是响应式设计。 性能最好,代码简单,原生支持。 对于需要精确计算、复杂交互或画布重绘的场景无能为力。
JS 设置根元素宽度 需要JS介入的复杂自适应布局,或与JS库深度交互的场景。 灵活性极高,可以精确控制,方便与JS逻辑联动。 有性能开销,需要手动处理 resize 事件和防抖。
JS 直接设置元素宽度 针对单个特定元素,且该元素无法通过CSS相对单位控制。 直观,易于理解。 破坏了CSS的层叠和继承规则,难以维护,不推荐在全局使用。

最终建议:

  1. 优先使用 CSS:在 95% 的情况下,使用 vw、 或 flexboxgrid 布局就能完美解决自适应问题,这是最专业、最高效的方式。
  2. 谨慎使用 JS:仅在 CSS 无法满足需求时,才考虑使用 JavaScript,如果使用 JS,请务必:
    • 监听 resize 事件
    • 使用防抖技术 优化性能。
    • 操作根元素 (<html>) 或一个明确的容器,而不是直接操作页面上的所有元素,以保持代码的整洁和可维护性。