解决css @container容器查询的兼容性不好 ---- 替代方案

253 阅读3分钟

CSS @container 容器查询是一种新兴的 CSS 特性,用于根据容器的尺寸应用样式。然而,由于其兼容性问题,目前并不是所有浏览器都支持这个特性。因此,我们需要寻找兼容性更好的替代方案。

替代方案:使用 JavaScript 实现容器查询

虽然 CSS 本身没有直接的替代方案,但我们可以借助 JavaScript 来实现类似的功能。以下是一个详细的代码示例,演示如何使用 JavaScript 监测容器尺寸并应用相应的样式。

示例:使用 ResizeObserver 和 JavaScript 实现容器查询

  1. HTML 结构

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Container Query Example</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <div class="container">
            <div class="content">
                Resize the container to see the effect.
            </div>
        </div>
        <script src="script.js"></script>
    </body>
    </html>
    
  2. CSS 样式

    /* styles.css */
    .container {
        width: 50%;
        margin: 0 auto;
        padding: 20px;
        border: 2px solid #000;
        resize: both;
        overflow: auto;
    }
    
    .content {
        background-color: lightblue;
        padding: 10px;
        transition: background-color 0.3s;
    }
    
    .content.small {
        background-color: lightcoral;
    }
    
    .content.medium {
        background-color: lightgreen;
    }
    
    .content.large {
        background-color: lightblue;
    }
    
  3. JavaScript 实现

    // script.js
    document.addEventListener('DOMContentLoaded', () => {
        const container = document.querySelector('.container');
        const content = container.querySelector('.content');
    
        const resizeObserver = new ResizeObserver(entries => {
            for (let entry of entries) {
                const width = entry.contentRect.width;
    
                // 移除所有尺寸相关的类
                content.classList.remove('small', 'medium', 'large');
    
                // 根据容器宽度添加相应的类
                if (width < 300) {
                    content.classList.add('small');
                } else if (width >= 300 && width < 600) {
                    content.classList.add('medium');
                } else {
                    content.classList.add('large');
                }
            }
        });
    
        // 观察容器尺寸变化
        resizeObserver.observe(container);
    });
    

代码解释

JavaScript 实现

  • 使用 ResizeObserver 观察 .container 容器的尺寸变化。
  • 根据容器的宽度,动态地为 .content 元素添加或移除相应的类,从而改变其样式。

总结

通过使用 ResizeObserver 和 JavaScript,我们可以实现类似 CSS @container 容器查询的功能。这种方法具有良好的兼容性,可以在大多数现代浏览器中运行。虽然这种方法可能比纯 CSS 实现稍微复杂一些,但它提供了一个有效的解决方案,适用于当前浏览器支持不完全的情况下。

resizeObserver 在较低版本浏览器兼容性也不好,可以使用setInterval 兼容

如果你需要在较低版本的浏览器中实现容器查询,并且 ResizeObserver 兼容性不好,可以使用一个补丁函数来实现类似的功能。我们可以使用 window.onresize 事件监听窗口大小的变化,并结合 setInterval 定时器来监测容器的尺寸变化。

以下是详细的代码示例,演示如何编写一个兼容性更好的补丁:

示例:使用 window.onresize 和定时器实现兼容性补丁

  1. HTML 结构

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Container Query Example</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <div class="container">
            <div class="content">
                Resize the container to see the effect.
            </div>
        </div>
        <script src="script.js"></script>
    </body>
    </html>
    
  2. CSS 样式

    /* styles.css */
    .container {
        width: 50%;
        margin: 0 auto;
        padding: 20px;
        border: 2px solid #000;
        resize: both;
        overflow: auto;
    }
    
    .content {
        background-color: lightblue;
        padding: 10px;
        transition: background-color 0.3s;
    }
    
    .content.small {
        background-color: lightcoral;
    }
    
    .content.medium {
        background-color: lightgreen;
    }
    
    .content.large {
        background-color: lightblue;
    }
    
  3. JavaScript 实现

    // script.js
    document.addEventListener('DOMContentLoaded', () => {
        const container = document.querySelector('.container');
        const content = container.querySelector('.content');
    
        // 初始化容器尺寸
        let lastWidth = container.clientWidth;
        let lastHeight = container.clientHeight;
    
        // 定义一个函数来更新样式
        function updateContentClass() {
            const width = container.clientWidth;
    
            // 移除所有尺寸相关的类
            content.classList.remove('small', 'medium', 'large');
    
            // 根据容器宽度添加相应的类
            if (width < 300) {
                content.classList.add('small');
            } else if (width >= 300 && width < 600) {
                content.classList.add('medium');
            } else {
                content.classList.add('large');
            }
        }
    
        // 使用定时器定期检查容器尺寸变化
        setInterval(() => {
            const currentWidth = container.clientWidth;
            const currentHeight = container.clientHeight;
    
            if (currentWidth !== lastWidth || currentHeight !== lastHeight) {
                lastWidth = currentWidth;
                lastHeight = currentHeight;
                updateContentClass();
            }
        }, 200); // 每200毫秒检查一次
    
        // 初始调用
        updateContentClass();
    
        // 同时监听窗口大小变化
        window.onresize = updateContentClass;
    });
    

总结

通过结合 window.onresize 事件和 setInterval 定时器,我们可以实现一个兼容性更好的解决方案,用于监测容器尺寸变化并应用相应的样式。这种方法虽然不如 ResizeObserver 高效,但在兼容性方面更为广泛,适用于较低版本的浏览器。