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

JavaScript实现flex布局点击盒子调整自身及其他元素宽度

实现方案

核心思路

不用写复杂的JS逻辑判断,优先用CSS处理视觉状态,JS只负责维护选中状态锁,性能更好代码也更易维护:

  • 初始状态、hover状态的宽度变化优先用CSS实现,通过父容器的状态类区分「无选中项」「有选中项」两种场景,避免hover效果干扰点击后的选中态
  • JS只处理点击事件:每次点击先清空所有盒子的选中标记,再给当前点击的盒子加上选中类,同时给父容器加状态标记锁定hover
  • 预留重置方法,后续加关闭按钮直接调用即可

完整代码

CSS部分

/* 父容器基础样式 */
section {
  display: flex;
  width: 100%;
  height: 300px;
  gap: 4px; /* 盒子间距,不需要可删除 */
}

/* 盒子基础样式 */
.box {
  width: 25%; /* 初始宽度 */
  transition: width 0.3s ease; /* 宽度变化加过渡动画,效果更丝滑,不需要可删除 */
  cursor: pointer;
  /* 原有盒子自定义样式比如背景色、圆角等可直接保留 */
}

/* 无选中项时,hover当前盒子宽度 */
section:not(.has-selected) .box:hover {
  width: 40%;
}
/* 无选中项时,hover某个盒子,其余盒子宽度变为20% */
section:not(.has-selected) .box:hover ~ .box,
section:not(.has-selected):has(.box:hover) .box:not(:hover) {
  width: 20%;
}

/* 选中态盒子宽度 */
.box.selected {
  width: 85%;
}
/* 有选中项时,其余非选中盒子宽度 */
section.has-selected .box:not(.selected) {
  width: 5%;
}

JS部分

// 获取页面元素
const boxContainer = document.querySelector('section');
const boxes = document.querySelectorAll('.box');

// 给每个盒子绑定点击事件
boxes.forEach(box => {
  box.addEventListener('click', () => {
    // 先清除所有盒子的选中状态
    boxes.forEach(item => item.classList.remove('selected'));
    // 给当前点击的盒子添加选中类
    box.classList.add('selected');
    // 给父容器加选中标记,禁用hover效果
    boxContainer.classList.add('has-selected');
  })
})

// 预留重置方法,后续给关闭按钮绑定即可
function resetBoxWidth() {
  boxes.forEach(item => item.classList.remove('selected'));
  boxContainer.classList.remove('has-selected');
}

// 后续开发关闭功能时,给按钮绑定上述方法即可,示例:
// document.querySelector('.close-btn').addEventListener('click', resetBoxWidth)

兼容说明

上面的CSS用到了:has()选择器,2023年之后发布的主流浏览器(Chrome 105+、Firefox 121+、Safari 15.4+)都已经原生支持,如果需要兼容更老的浏览器,可以把hover效果改用JS实现,把下面这段代码追加到JS文件里即可:

// 旧浏览器兼容:不支持:has()时用JS实现hover效果
if (!CSS.supports('selector(:has(*))')) {
  boxes.forEach(box => {
    box.addEventListener('mouseenter', () => {
      // 有选中项时不触发hover宽度变化
      if (boxContainer.classList.contains('has-selected')) return;
      boxes.forEach(item => item.style.width = '20%');
      box.style.width = '40%';
    })
    box.addEventListener('mouseleave', () => {
      if (boxContainer.classList.contains('has-selected')) return;
      boxes.forEach(item => item.style.width = '25%');
    })
  })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:33:32