重新向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>
问题原因分析
- 重复监听与逻辑冲突:同时绑定
test和adjustDivOnScreenSize两个resize处理函数,执行顺序不确定,导致DOM操作逻辑混乱。 - DOM还原不完整:
test函数仅将第一个图片div(带test类)重新包裹进myDiv,遗漏了第二个图片div,切回大屏时myDiv子元素数量和初始结构不一致。 - 空指针报错:
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
相关产品推荐
相关产品推荐

