解决点击展示子分类时父分类导航上移,维持水平布局问题
解决方案
问题根源
当前父分类列表.switcher使用align-items: center布局,当子分类列表显示时,包含子分类的父<li>高度增加,flex布局会重新对齐所有列表项,导致整个父分类区块向上偏移。同时子分类默认流式布局会撑开父<li>高度,干扰同行元素位置。
修改步骤
1. 调整父分类列表的Flex对齐规则
修改.switcher的CSS,将垂直对齐方式改为顶部对齐,确保所有父分类始终从顶部对齐,不受子元素高度变化影响:
.switcher { margin: 0 auto; display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; /* 替换原有的center */ list-style: none; width: fit-content; padding: 10px 10px; }
2. 让子分类绝对定位在父分类下方
给包含子分类的父<li>设置相对定位,子分类列表设置绝对定位,避免子分类撑开父元素高度:
.switcher li { border-radius: 4px; padding: 10px 10px; background-color: white; cursor: pointer; transition: 0.2s linear; font-size: 12px; user-select: none; margin: 5px; position: relative; /* 添加相对定位 */ display: inline-block; cursor: pointer; } /* 子分类列表样式 */ .switcher li .switcher { position: absolute; top: 100%; /* 紧贴父元素底部 */ left: 0; margin-top: 5px; flex-direction: column; /* 子分类垂直排列 */ background-color: white; padding: 5px 0; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); /* 可选:增强层级感 */ } /* 子分类列表项样式优化 */ .switcher li .switcher li { margin: 2px 10px; padding: 8px 12px; border-radius: 4px; } .switcher li .switcher li:hover { background-color: #f5f5f5; /* 可选:hover高亮 */ }
3. 修复事件冲突问题
原代码中父分类点击会触发图片筛选,现在调整为:点击父分类仅展开/收起子分类,点击子分类才执行筛选逻辑:
const imgs = Array.from(document.images); // 区分顶级父分类和子分类 const parentCategories = document.querySelectorAll('.switcher > li:not(.switcher li li)'); const subCategories = document.querySelectorAll('.switcher li li'); // 子分类绑定筛选事件 subCategories.forEach(li => { li.addEventListener('click', removeActive); li.addEventListener('click', filter); }); // 父分类绑定展开/收起事件 parentCategories.forEach(li => { const subMenu = li.querySelector('.switcher'); if (subMenu) { li.addEventListener('click', function(e) { e.stopPropagation(); // 关闭其他父分类的子菜单 document.querySelectorAll('.switcher li .switcher').forEach(menu => { if (menu !== subMenu) menu.style.display = 'none'; }); // 切换当前子菜单显示状态 subMenu.style.display = subMenu.style.display === 'block' ? 'none' : 'block'; // 激活当前父分类(可选) if (this.dataset.cat !== '.all') { removeActive.call(this); } }); } else { // All分类点击逻辑 li.addEventListener('click', function(e) { e.stopPropagation(); removeActive.call(this); filter.call(this); // 关闭所有子菜单 document.querySelectorAll('.switcher li .switcher').forEach(menu => { menu.style.display = 'none'; }); }); } }); // 保留原有核心函数 function removeActive() { document.querySelectorAll('.switcher li').forEach(li => { li.classList.remove('active'); }); this.classList.add('active'); } function filter() { imgs.forEach(img => { if (!img.classList.contains('logo')) { img.style.display = 'none'; } }); document.querySelectorAll(this.dataset.cat).forEach(el => { el.style.display = 'block'; }); }
4. 优化HTML结构(可选)
给子分类列表单独添加类名sub-switcher,避免和父列表样式冲突:
<li data-cat=".urb" id="show"> Urbanism <ul class="sub-switcher" id="content" style="display: none"> <li data-cat=".cityscale">City Scale</li> <li data-cat=".residential">Residential</li> <li data-cat=".entertainment">Entertainment</li> </ul> </li>
对应CSS修改为:
.switcher li .sub-switcher { position: absolute; top: 100%; left: 0; margin-top: 5px; flex-direction: column; background-color: white; padding: 5px 0; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); list-style: none; } .switcher li .sub-switcher li { margin: 2px 10px; padding: 8px 12px; border-radius: 4px; }
最终效果
- 所有父分类始终保持同一水平线,不会因子分类展开偏移
- 子分类显示在对应父分类正下方,不干扰其他父分类位置
- 父分类仅负责展开/收起子菜单,子分类执行图片筛选逻辑
内容的提问来源于stack exchange,提问作者Farah Anany
相关产品推荐
相关产品推荐

