html 时间、价格筛选样式处理

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .sort {
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      gap: 2px;
    }
    .sort-caret {
      border: 5px solid transparent;
      border-bottom-color: #003dff;
      cursor: pointer;
    }

    .sort-bot {
      border: 5px solid transparent;
      border-top-color: #d6d6e7;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <div class="sort">
    <div class="sort-caret"></div>
    <div class="sort-bot"></div>
  </div>
</body>
</html>

表格案例

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML 筛选箭头点击交互示例</title>
  <style>
    /* 基础样式重置 */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: system-ui, -apple-system, sans-serif;
    }

    body {
      padding: 40px;
      background-color: #f5f7fa;
    }

    /* 表格容器 */
    .sort-table {
      width: 100%;
      max-width: 800px;
      margin: 0 auto;
      border-collapse: collapse;
      background: white;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 2px 12px rgba(0,0,0,0.08);
    }

    /* 表头样式 */
    .sort-table th {
      position: relative;
      padding: 16px 20px;
      background-color: #fafafa;
      color: #333;
      font-weight: 500;
      cursor: pointer;
      user-select: none;
      text-align: left;
      border-bottom: 1px solid #eee;
      transition: background-color 0.2s;
    }

    .sort-table th:hover {
      background-color: #f0f0f0;
    }

    /* 箭头容器 */
    .sort-arrow {
      display: inline-block;
      margin-left: 8px;
      vertical-align: middle;
      width: 0;
      height: 0;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      border-top: 6px solid #999;
      transition: transform 0.3s ease, border-color 0.3s ease;
    }

    /* 升序(箭头向上)状态 */
    .sort-table th[data-sort="asc"] .sort-arrow {
      transform: rotate(180deg);
      border-top-color: #4080ff;
    }

    /* 降序(箭头向下)状态 */
    .sort-table th[data-sort="desc"] .sort-arrow {
      border-top-color: #4080ff;
    }

    /* 表格内容 */
    .sort-table td {
      padding: 14px 20px;
      border-bottom: 1px solid #f0f0f0;
      color: #666;
    }

    .sort-table tr:last-child td {
      border-bottom: none;
    }

    .sort-table tbody tr:hover {
      background-color: #f9fafc;
    }
  </style>
</head>
<body>
  <table class="sort-table">
    <thead>
      <tr>
        <th data-column="name">
          名称 <span class="sort-arrow"></span>
        </th>
        <th data-column="price">
          价格 <span class="sort-arrow"></span>
        </th>
        <th data-column="sales">
          销量 <span class="sort-arrow"></span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>商品A</td>
        <td>99</td>
        <td>1200</td>
      </tr>
      <tr>
        <td>商品B</td>
        <td>199</td>
        <td>800</td>
      </tr>
      <tr>
        <td>商品C</td>
        <td>59</td>
        <td>2100</td>
      </tr>
      <tr>
        <td>商品D</td>
        <td>299</td>
        <td>500</td>
      </tr>
    </tbody>
  </table>

  <script>
    // 获取所有表头
    const headers = document.querySelectorAll('.sort-table th');
    const tableBody = document.querySelector('.sort-table tbody');

    // 表头点击事件
    headers.forEach(header => {
      header.addEventListener('click', () => {
        const column = header.dataset.column;
        let direction = header.dataset.sort;

        // 切换排序方向:无状态/降序 → 升序;升序 → 降序
        if (!direction || direction === 'desc') {
          direction = 'asc';
        } else {
          direction = 'desc';
        }

        // 重置所有表头状态
        headers.forEach(h => {
          delete h.dataset.sort;
        });

        // 设置当前表头状态
        header.dataset.sort = direction;

        // 执行排序
        sortTable(column, direction);
      });
    });

    // 排序函数
    function sortTable(column, direction) {
      const rows = Array.from(tableBody.querySelectorAll('tr'));
      const isAsc = direction === 'asc';

      // 按列值排序
      const sortedRows = rows.sort((a, b) => {
        let aVal = a.querySelector(`td:nth-child(${getIndex(column)})`).textContent.trim();
        let bVal = b.querySelector(`td:nth-child(${getIndex(column)})`).textContent.trim();

        // 数字类型特殊处理
        if (!isNaN(Number(aVal)) && !isNaN(Number(bVal))) {
          aVal = Number(aVal);
          bVal = Number(bVal);
        }

        if (aVal < bVal) return isAsc ? -1 : 1;
        if (aVal > bVal) return isAsc ? 1 : -1;
        return 0;
      });

      // 重新插入排序后的行
      tableBody.innerHTML = '';
      sortedRows.forEach(row => tableBody.appendChild(row));
    }

    // 获取列的索引(对应nth-child)
    function getIndex(column) {
      const columns = ['name', 'price', 'sales'];
      return columns.indexOf(column) + 1;
    }
  </script>
</body>
</html>

完整案例

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>双箭头筛选点击交互示例</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: system-ui, -apple-system, sans-serif;
    }

    body {
      padding: 40px;
      background-color: #f5f7fa;
    }

    /* 表格容器 */
    .sort-table {
      width: 100%;
      max-width: 800px;
      margin: 0 auto;
      border-collapse: collapse;
      background: white;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 2px 12px rgba(0,0,0,0.08);
    }

    /* 表头样式 */
    .sort-table th {
      position: relative;
      padding: 16px 20px;
      background-color: #fafafa;
      color: #333;
      font-weight: 500;
      text-align: left;
      border-bottom: 1px solid #eee;
    }

    /* 箭头容器 */
    .sort-buttons {
      display: inline-flex;
      flex-direction: column;
      margin-left: 8px;
      vertical-align: middle;
      gap: 2px;
    }

    /* 箭头基础样式(用CSS绘制三角形) */
    .sort-btn {
      width: 0;
      height: 0;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      cursor: pointer;
      transition: border-color 0.2s ease;
    }

    /* 上箭头(升序) */
    .sort-btn.up {
      border-bottom: 6px solid #999;
    }
    .sort-btn.up.active {
      border-bottom-color: #4080ff;
    }

    /* 下箭头(降序) */
    .sort-btn.down {
      border-top: 6px solid #999;
    }
    .sort-btn.down.active {
      border-top-color: #4080ff;
    }

    /* 表格内容 */
    .sort-table td {
      padding: 14px 20px;
      border-bottom: 1px solid #f0f0f0;
      color: #666;
    }

    .sort-table tr:last-child td {
      border-bottom: none;
    }

    .sort-table tbody tr:hover {
      background-color: #f9fafc;
    }
  </style>
</head>
<body>
  <table class="sort-table">
    <thead>
      <tr>
        <th data-column="name">
          名称
          <span class="sort-buttons">
            <span class="sort-btn up" data-direction="asc"></span>
            <span class="sort-btn down" data-direction="desc"></span>
          </span>
        </th>
        <th data-column="price">
          价格
          <span class="sort-buttons">
            <span class="sort-btn up" data-direction="asc"></span>
            <span class="sort-btn down" data-direction="desc"></span>
          </span>
        </th>
        <th data-column="sales">
          销量
          <span class="sort-buttons">
            <span class="sort-btn up" data-direction="asc"></span>
            <span class="sort-btn down" data-direction="desc"></span>
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>商品A</td>
        <td>99</td>
        <td>1200</td>
      </tr>
      <tr>
        <td>商品B</td>
        <td>199</td>
        <td>800</td>
      </tr>
      <tr>
        <td>商品C</td>
        <td>59</td>
        <td>2100</td>
      </tr>
      <tr>
        <td>商品D</td>
        <td>299</td>
        <td>500</td>
      </tr>
    </tbody>
  </table>

  <script>
    // 获取所有排序按钮
    const sortButtons = document.querySelectorAll('.sort-btn');
    const tableBody = document.querySelector('.sort-table tbody');

    // 排序按钮点击事件
    sortButtons.forEach(btn => {
      btn.addEventListener('click', (e) => {
        // 阻止冒泡,避免影响表头其他事件
        e.stopPropagation();

        // 获取当前按钮的列和方向
        const direction = btn.dataset.direction;
        const header = btn.closest('th');
        const column = header.dataset.column;

        // 重置所有按钮的激活状态
        sortButtons.forEach(b => b.classList.remove('active'));

        // 激活当前点击的按钮
        btn.classList.add('active');

        // 执行排序
        sortTable(column, direction);
      });
    });

    // 排序函数
    function sortTable(column, direction) {
      const rows = Array.from(tableBody.querySelectorAll('tr'));
      const isAsc = direction === 'asc';

      // 按列值排序
      const sortedRows = rows.sort((a, b) => {
        let aVal = a.querySelector(`td:nth-child(${getIndex(column)})`).textContent.trim();
        let bVal = b.querySelector(`td:nth-child(${getIndex(column)})`).textContent.trim();

        // 数字类型特殊处理
        if (!isNaN(Number(aVal)) && !isNaN(Number(bVal))) {
          aVal = Number(aVal);
          bVal = Number(bVal);
        }

        if (aVal < bVal) return isAsc ? -1 : 1;
        if (aVal > bVal) return isAsc ? 1 : -1;
        return 0;
      });

      // 重新插入排序后的行
      tableBody.innerHTML = '';
      sortedRows.forEach(row => tableBody.appendChild(row));
    }

    // 获取列的索引(对应nth-child)
    function getIndex(column) {
      const columns = ['name', 'price', 'sales'];
      return columns.indexOf(column) + 1;
    }

  </script>

</body>
</html>
相关推荐
陈随易3 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart4 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒6 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰6 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
竹林8187 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花7 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12278 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪9 小时前
Vue3-生命周期
前端
莪_幻尘9 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4539 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端