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

如何实现带分组悬停展示子项的多选嵌套列表?

实现optgroup悬停展示子选项的方案

原生<select>标签的<optgroup>元素受浏览器默认样式与行为限制,很难直接实现悬停时右侧展示子选项的交互,因此我们可以通过自定义UI结构来模拟该功能,具体实现方案如下:

实现步骤

  • 用自定义HTML结构模拟原生select的分组与选项,原生控件可隐藏以保留表单提交功能
  • 为每个分组项绑定mouseover事件,触发时生成对应子选项的悬浮列表并定位到分组右侧
  • 为分组项及悬浮列表绑定mouseout事件,控制列表的隐藏逻辑
  • 通过CSS调整悬浮列表的样式与定位,保证交互体验

完整代码示例

HTML 结构

<!-- 隐藏原生select,用于表单提交时保留选中值 -->
<select id='optSelect' multiple style="display: none;">
  <optgroup label='Option1'>
    <option value='Option1'>Option1</option>
    <option value='Option12'>Option12</option>
    <option value='Option13'>Option13</option>
  </optgroup>
                        
  <optgroup label='Option2'>
    <option value='Option21'>Option21</option>
    <option value='Option22'>Option22</option>
    <option value='Option23'>Option23</option>
  </optgroup>
                        
  <optgroup label='Option3'>
    <option value='Option31'>Option31</option>
    <option value='Option32'>Option32</option>
    <option value='Option33'>Option33</option>
  </optgroup>
</select>

<!-- 自定义模拟UI -->
<div class="custom-select-container">
  <div class="custom-optgroup" data-group="Option1">
    <span class="group-label">Option1</span>
  </div>
  <div class="custom-optgroup" data-group="Option2">
    <span class="group-label">Option2</span>
  </div>
  <div class="custom-optgroup" data-group="Option3">
    <span class="group-label">Option3</span>
  </div>
</div>

<!-- 悬浮列表容器 -->
<div id="hover-options" class="hover-options"></div>

CSS 样式

.custom-select-container {
  width: 200px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.custom-optgroup {
  padding: 8px 12px;
  background-color: #f8f8f8;
  border-bottom: 1px solid #eee;
  cursor: pointer;
  position: relative;
}

.custom-optgroup:last-child {
  border-bottom: none;
}

.custom-optgroup:hover {
  background-color: #e8e8e8;
}

.hover-options {
  position: absolute;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  padding: 0;
  margin: 0;
  list-style: none;
  display: none;
  z-index: 100;
}

.hover-options li {
  padding: 8px 12px;
  min-width: 150px;
  font-size: 15px;
}

.hover-options li:hover {
  background-color: #e8e8e8;
}

JavaScript 逻辑

const customOptgroups = document.querySelectorAll('.custom-optgroup');
const hoverOptions = document.getElementById('hover-options');
const nativeSelect = document.getElementById('optSelect');

// 绑定分组悬停事件
customOptgroups.forEach(group => {
  group.addEventListener('mouseover', function() {
    const groupLabel = this.dataset.group;
    // 匹配原生select中对应的分组
    const nativeOptgroup = nativeSelect.querySelector(`optgroup[label="${groupLabel}"]`);
    const options = nativeOptgroup.querySelectorAll('option');
    
    // 生成悬浮列表内容
    hoverOptions.innerHTML = '';
    options.forEach(opt => {
      const li = document.createElement('li');
      li.textContent = opt.textContent;
      li.dataset.value = opt.value;
      // 点击悬浮选项时同步原生select的选中状态
      li.addEventListener('click', function() {
        opt.selected = !opt.selected;
      });
      hoverOptions.appendChild(li);
    });
    
    // 定位悬浮列表并显示
    const rect = this.getBoundingClientRect();
    hoverOptions.style.top = `${rect.top + window.scrollY}px`;
    hoverOptions.style.left = `${rect.right + 10}px`;
    hoverOptions.style.display = 'block';
  });
  
  group.addEventListener('mouseout', function() {
    hoverOptions.style.display = 'none';
  });
  
  // 鼠标移入悬浮列表时保持显示
  hoverOptions.addEventListener('mouseover', function() {
    this.style.display = 'block';
  });
  
  hoverOptions.addEventListener('mouseout', function() {
    this.style.display = 'none';
  });
});

方案说明

  • 原生<select>仅用于表单提交时传递选中值,不影响前端交互逻辑
  • 自定义UI完全可控,可根据需求调整样式与交互细节
  • 悬浮选项的点击操作同步原生select状态,保证数据一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:25:27