You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重新向DOM添加Div引发响应式布局样式异常问题

响应式布局切换后DOM结构一致但布局异常问题

我正在实现网页UI在大屏幕(lg,>1024px)与中等屏幕(md,≤1024px)间的平滑适配,初始大屏布局正常。为适配中屏,通过JS在屏幕宽度缩小到1024px时移除包裹图片的myDiv,放大回1024px以上时重新添加该div。首次加载布局正常,但从lg切换到md再切回lg后,布局和初始大屏不一致,尽管看起来DOM结构相同。

相关代码如下:

<div class="mx-auto mt-16 max-w-2xl lg:max-w-none">
    <div class="mx-auto bg-white mt-6 lg:h-[40rem] overflow-hidden">
        <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-6 gap-12">
            <div class="lg:col-span-2" id="myDiv">
                <div class="col-span-1 test">
                    <!-- Image 1 -->
                    <div class="flex justify-center">
                        <x-curator-glider
                            class="h-full"
                            media="{{ $keyHighlightSection2Images[0]['image'] }}"
                            format="webp"
                            loading="lazy"
                            quality="80"
                            width="800"
                        />
                    </div>
                </div>
                <div class="col-span-1">
                    <!-- Image 2 -->
                    <div class="flex justify-center">
                        <x-curator-glider
                            class="h-full"
                            media="{{ $keyHighlightSection2Images[1]['image'] }}"
                            format="webp"
                            loading="lazy"
                            quality="80"
                            width="800"
                        />
                    </div>
                </div>
            </div>
            <div class="col-span-1 lg:col-span-2">
                <!-- Image 3 (middle) -->
                <div class="flex justify-center lg:mt-48">
                    Image goes here
                </div>
            </div>
            <div class="col-span-1">
                <!-- Image 4 -->
                <div class="flex justify-center">
                    Image goes here
                </div>
            </div>
            <div class="col-span-1">
                <!-- Image 5 -->
                <div class="flex justify-center mb-16 lg:mb-0">
                    Image goes here
                </div>
            </div>
        </div>
    </div>
</div>
<script>
    // Function to add/remove the div based on screen size
    function adjustDivOnScreenSize() {
        var screenWidth = window.innerWidth || document.documentElement.clientWidth;
        var div = document.getElementById('myDiv');

        if (screenWidth <= 1024) {
            if (div) {
                var parent = div.parentNode;
                while (div.firstChild) {
                    parent.insertBefore(div.firstChild, div);
                }
                parent.removeChild(div);
            }
        } else {
            var parent = div.parentNode;
            var innerHtml = div.innerHTML;
            var newDiv = document.createElement('div');
            newDiv.id = 'myDiv';
            newDiv.className = 'lg:col-span-2'; // Set the appropriate CSS grid class
            newDiv.innerHTML = innerHtml;
            parent.insertBefore(newDiv, div);
            div.remove();
        }
    }


    function test() {
        var screenWidth = window.innerWidth || document.documentElement.clientWidth;

        if (screenWidth > 1024) {
            // Check if the div with id "myDiv" already exists
            var myDiv = document.getElementById('myDiv');

            if (!myDiv) {
                // Get a reference to the div with class "test"
                var testDiv = document.querySelector('.test');

                // Create a new div element for the wrapper
                myDiv = document.createElement('div');
                myDiv.id = 'myDiv';

                // Append the wrapper div to the parent element of the div with class "test"
                testDiv.parentElement.insertBefore(myDiv, testDiv);

                // Move the div with class "test" inside the wrapper div
                myDiv.appendChild(testDiv);
            }
        }
    }

    // Call the function on page load and window resize
    window.addEventListener('load', adjustDivOnScreenSize);
    window.addEventListener('resize', test);
    window.addEventListener('resize', adjustDivOnScreenSize);
</script>

问题原因分析

  1. 重复监听与逻辑冲突:同时绑定test和adjustDivOnScreenSize两个resize处理函数,执行顺序不确定,导致DOM操作逻辑混乱。
  2. DOM还原不完整:test函数仅将第一个图片div(带test类)重新包裹进myDiv,遗漏了第二个图片div,切回大屏时myDiv子元素数量和初始结构不一致。
  3. 空指针报错:adjustDivOnScreenSize的else分支中,若myDiv已被移除,div会是null,此时访问div.parentNode直接报错,后续逻辑无法执行。

解决方案

合并逻辑为单一处理函数,确保大屏状态下完整还原初始DOM结构,添加防抖避免频繁触发:

<div class="mx-auto mt-16 max-w-2xl lg:max-w-none">
    <div class="mx-auto bg-white mt-6 lg:h-[40rem] overflow-hidden">
        <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-6 gap-12" id="gridContainer">
            <div class="lg:col-span-2" id="myDiv">
                <div class="col-span-1 test">
                    <!-- Image 1 -->
                    <div class="flex justify-center">
                        <x-curator-glider
                            class="h-full"
                            media="{{ $keyHighlightSection2Images[0]['image'] }}"
                            format="webp"
                            loading="lazy"
                            quality="80"
                            width="800"
                        />
                    </div>
                </div>
                <div class="col-span-1" id="secondImageDiv">
                    <!-- Image 2 -->
                    <div class="flex justify-center">
                        <x-curator-glider
                            class="h-full"
                            media="{{ $keyHighlightSection2Images[1]['image'] }}"
                            format="webp"
                            loading="lazy"
                            quality="80"
                            width="800"
                        />
                    </div>
                </div>
            </div>
            <div class="col-span-1 lg:col-span-2">
                <!-- Image 3 (middle) -->
                <div class="flex justify-center lg:mt-48">
                    Image goes here
                </div>
            </div>
            <div class="col-span-1">
                <!-- Image 4 -->
                <div class="flex justify-center">
                    Image goes here
                </div>
            </div>
            <div class="col-span-1">
                <!-- Image 5 -->
                <div class="flex justify-center mb-16 lg:mb-0">
                    Image goes here
                </div>
            </div>
        </div>
    </div>
</div>
<script>
    let resizeTimeout;
    const gridContainer = document.getElementById('gridContainer');
    const firstImageDiv = document.querySelector('.test');
    const secondImageDiv = document.getElementById('secondImageDiv');

    function adjustLayout() {
        const screenWidth = window.innerWidth || document.documentElement.clientWidth;
        const myDiv = document.getElementById('myDiv');

        if (screenWidth <= 1024) {
            if (myDiv) {
                // 将两个图片div移到父容器,移除myDiv
                gridContainer.insertBefore(firstImageDiv, myDiv);
                gridContainer.insertBefore(secondImageDiv, myDiv);
                gridContainer.removeChild(myDiv);
            }
        } else {
            if (!myDiv) {
                // 创建新的myDiv并添加类名
                const newMyDiv = document.createElement('div');
                newMyDiv.id = 'myDiv';
                newMyDiv.className = 'lg:col-span-2';
                // 将两个图片div放入myDiv,再插入到正确位置
                newMyDiv.appendChild(firstImageDiv);
                newMyDiv.appendChild(secondImageDiv);
                gridContainer.insertBefore(newMyDiv, gridContainer.children[1]);
            }
        }
    }

    // 防抖处理,避免resize频繁触发
    function debouncedAdjustLayout() {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(adjustLayout, 100);
    }

    // 初始化与监听
    window.addEventListener('load', adjustLayout);
    window.addEventListener('resize', debouncedAdjustLayout);
</script>

优化点说明

  • 给第二个图片div添加id,方便精准定位
  • 防抖函数减少resize事件触发频率,提升性能
  • 单一函数处理所有布局切换逻辑,避免冲突
  • 确保大屏状态下myDiv包含两个图片div,完全还原初始DOM结构
  • 明确DOM插入位置,保证元素顺序和初始一致

内容的提问来源于stack exchange,提问作者Nathan Bayne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 05:08:10