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

技术咨询:采用<ul><li>替代<select>实现网站导航与筛选

嘿,这事儿我熟!把传统的<select>类别选择改成<ul><li>的导航/筛选样式,既能提升视觉体验,又能保持原有的功能完整性,我给你捋捋具体实现方案和要注意的细节~

一、核心实现方案

1. 基础结构与JS交互

首先用<ul>作为容器,每个<li>对应原来的一个<option>。为了和原有的JS跳转逻辑对齐,我们可以给每个<li>绑定点击事件,触发页面跳转;同时用<a>标签做兜底,无JS时也能正常工作。

示例代码:

<!-- 容器加上类名方便样式和JS操作,aria-label提升可访问性 -->
<ul class="category-nav" aria-label="类别导航">
  <!-- 初始选中项加上active类 -->
  <li class="active">
    <a href="/category/tech">科技</a>
  </li>
  <li>
    <a href="/category/life">生活</a>
  </li>
  <li>
    <a href="/category/entertainment">娱乐</a>
  </li>
</ul>

<script>
const categoryItems = document.querySelectorAll('.category-nav li');

categoryItems.forEach(item => {
  item.addEventListener('click', (e) => {
    // 先移除所有active类
    categoryItems.forEach(i => i.classList.remove('active'));
    // 给当前点击项加上active类
    item.classList.add('active');
    // 触发跳转(这里直接用a标签的href,也可以自定义逻辑)
    const targetUrl = item.querySelector('a').getAttribute('href');
    window.location.href = targetUrl;
  });
});
</script>

2. 无JS降级方案

原来的<select>依赖<submit>按钮降级,改成<ul><li>后,我们用原生<a>标签就能实现更自然的无JS体验——用户点击直接跳转,完全不需要额外的按钮,比原来的方案更友好!

上面的示例代码已经包含了这个逻辑:当JS禁用时,<a>标签会直接触发页面跳转,完全不影响核心功能。

3. 初始选中与回发状态保持

和原有的<select>逻辑一致,后端渲染页面时,判断当前页面对应的类别,给对应的<li>加上active类即可。比如用后端模板(以PHP为例):

<ul class="category-nav" aria-label="类别导航">
  <?php 
  // 后端获取类别列表和当前选中的类别slug
  $categories = [
    ['slug' => 'tech', 'name' => '科技'],
    ['slug' => 'life', 'name' => '生活'],
    ['slug' => 'entertainment', 'name' => '娱乐'],
  ];
  $currentCategory = 'tech'; // 假设当前页面是科技类别
  ?>
  
  <?php foreach($categories as $cat): ?>
    <li class="<?php echo ($currentCategory === $cat['slug']) ? 'active' : ''; ?>">
      <a href="/category/<?php echo $cat['slug']; ?>"><?php echo $cat['name']; ?></a>
    </li>
  <?php endforeach; ?>
</ul>

这样不管是首次加载还是回发跳转后,页面都会自动高亮当前选中的类别。

二、关键注意事项
  • 可访问性(重中之重):原生<select>自带键盘导航(上下键选择、回车触发),改成<ul><li>后需要手动补全这部分功能,确保屏幕阅读器和键盘用户能正常使用:

    • 给<ul>添加aria-label或aria-labelledby,让屏幕阅读器识别这是类别导航;
    • 实现键盘交互:支持Tab键聚焦到导航容器,上下箭头切换选中项,Enter/Space键触发跳转,示例逻辑如下:
      const navList = document.querySelector('.category-nav');
      const items = Array.from(navList.querySelectorAll('li'));
      let currentIndex = items.findIndex(item => item.classList.contains('active')) || 0;
      
      navList.addEventListener('keydown', (e) => {
        switch(e.key) {
          case 'ArrowDown':
            e.preventDefault();
            currentIndex = (currentIndex + 1) % items.length;
            items[currentIndex].querySelector('a').focus();
            break;
          case 'ArrowUp':
            e.preventDefault();
            currentIndex = (currentIndex - 1 + items.length) % items.length;
            items[currentIndex].querySelector('a').focus();
            break;
          case 'Enter':
          case ' ':
            e.preventDefault();
            items[currentIndex].querySelector('a').click();
            break;
        }
      });
      
    • 确保<a>标签的焦点样式可见,不要用outline: none去掉默认焦点,除非自定义了清晰的焦点样式。
  • 样式一致性:

    • 给.active类设置明显的视觉标识(比如背景色、下划线、字体加粗),和原<select>的选中状态体验对齐;
    • 给<li>添加hover和focus状态的样式,提升交互反馈;
    • 注意排版:桌面端可以横向排列,移动端可以根据空间调整为纵向或折叠下拉。
  • 响应式适配:原生<select>在移动端是紧凑的下拉控件,改成<ul><li>后,小屏幕下可能会占用过多空间。可以用媒体查询配合JS实现折叠菜单:小屏幕下只显示当前选中的类别,点击后展开所有选项,兼顾体验和空间效率。

  • 维护性:尽量用后端模板循环生成<li>项,不要硬写每个类别,后续新增或修改类别时只需更新后端数据即可,减少重复代码。

  • 性能考量:如果是单页应用(SPA),可以改成无刷新跳转(比如用history.pushState),但如果是传统多页应用,保持原有的页面跳转逻辑就足够,不需要额外优化。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:57:08