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

如何实现可点击的垂直Accordion(JS)及列表项无限自动滚动?

问题描述

我正在为硕士课程制作网站,想要实现可点击的垂直Accordion组件,点击每个<li>即可展开显示更多信息。目前仅通过CSS实现了hover触发的展开效果,请问如何用JavaScript改为点击触发?另外能否为每个<li>添加无限自动滚动功能?恳请技术帮助。


解决方案

一、改为点击触发的Accordion组件

1. 修改CSS规则

将原有的li:hover样式替换为自定义类.active,通过JS控制类的添加/移除来触发展开/收起:

/* 替换原li:hover样式 */
li.active {
  -webkit-box-flex : 30vw;
  -webkit-flex     : 30vw;
  -ms-flex         : 30vw;
  flex             : 30vw;
}

2. 添加JavaScript交互逻辑

在HTML的</body>标签前插入以下代码,实现点击切换展开状态,支持点击已展开项收起:

document.addEventListener('DOMContentLoaded', function() {
  const items = document.querySelectorAll('ul li');
  
  items.forEach(item => {
    item.addEventListener('click', function() {
      const isActive = this.classList.contains('active');
      // 先关闭所有已展开的项
      items.forEach(i => i.classList.remove('active'));
      // 若当前项未激活则展开,否则保持收起
      if (!isActive) this.classList.add('active');
    });
  });
});

二、添加无限自动滚动功能

无限滚动的核心是复制一份内容到容器尾部,滚动到原始内容高度时重置位置,实现无缝循环。

1. 调整HTML结构

给每个<li>内的内容包裹一个统一的容器,方便滚动控制:

<li>
  <div class="scroll-content">
    <!-- 原有的projects内容 -->
    <div class="projects">...</div>
    <div class="projects">...</div>
  </div>
</li>

2. 补充CSS样式

确保滚动容器的高度和溢出规则:

.scroll-content {
  height: 100%;
  overflow-y: scroll;
  scrollbar-width: none; /* 可选:隐藏滚动条 */
}
/* 针对webkit内核浏览器隐藏滚动条 */
.scroll-content::-webkit-scrollbar {
  display: none;
}

3. 实现自动滚动逻辑

在之前的JS代码中追加以下内容:

// 无限自动滚动逻辑
const scrollContainers = document.querySelectorAll('.scroll-content');

scrollContainers.forEach(container => {
  // 复制一份内容到容器末尾
  const content = container.innerHTML;
  container.innerHTML += content;
  
  let scrollPosition = 0;
  const scrollSpeed = 1; // 滚动速度,值越大越快
  let animationId;

  function autoScroll() {
    scrollPosition += scrollSpeed;
    // 滚动到原始内容高度时重置位置,实现无缝循环
    if (scrollPosition >= container.scrollHeight / 2) {
      scrollPosition = 0;
    }
    container.scrollTop = scrollPosition;
    animationId = requestAnimationFrame(autoScroll);
  }

  // 启动自动滚动
  autoScroll();

  // 鼠标悬停暂停滚动,离开后继续
  container.addEventListener('mouseover', () => cancelAnimationFrame(animationId));
  container.addEventListener('mouseout', () => autoScroll());
});

完整修改后代码示例

CSS(styles.css)

body {
  width  : 100vw;
  height : 100vh;
  margin : 0;
}
ul,
li {
  margin     : 0;
  padding    : 0;
  list-style : none;
}
ul {
  display  : flex;
  overflow : hidden;
  height   : 100vh;
  width    : 100vw;
}
li {
  overflow           : hidden;
  -webkit-box-flex   : 1;
  -webkit-flex       : 1;
  -ms-flex           : 1;
  flex               : 1;
  width              : 8.3vw;
  height             : calc(100% - 1%);
  -webkit-transition : -webkit-box-flex 500ms ease-out;
  -webkit-transition : -webkit-flex 500ms ease-out;
  transition         : -webkit-box-flex 500ms ease-out;
  transition         : -ms-flex 500ms ease-out;
  transition         : flex 500ms ease-out;
  padding            : 20px;
  -webkit-box-shadow : 2px 0px 4px -1px rgba(0, 0, 0, 0.66);
  -moz-box-shadow    : 2px 0px 4px -1px rgba(0, 0, 0, 0.66);
  box-shadow         : 2px 0px 4px -1px rgba(0, 0, 0, 0.66);
}
li.active {
  -webkit-box-flex : 30vw;
  -webkit-flex     : 30vw;
  -ms-flex         : 30vw;
  flex             : 30vw;
}
.projects {
  width         : 30vw;
  height        : auto;
  margin-bottom : 5vh;
}
.scroll-content {
  height: 100%;
  overflow-y: scroll;
  scrollbar-width: none;
}
.scroll-content::-webkit-scrollbar {
  display: none;
}
/* ------- 文本样式 ------- */
a {
  text-decoration : none;
  color           : black;
}
a:hover {
  opacity : 0.5;
}
.maintitle {
  width          : 100%;
  font-size      : 30px;
  text-transform : uppercase;
  font-family    : Arial, Helvetica, sans-serif;
}
.subtitle {
  width       : 150vw;
  font-size   : 20px;
  font-family : Arial, Helvetica, sans-serif;
}
img {
  padding-top : 20px;
  width       : 25vh;
  height      : auto;
}

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <title> MDC 22-23 </title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <ul>
    <!-- MICRO-1-->
    <li>
      <div class="scroll-content">
        <div class="projects">
          <a href="matilde/matilde.html">
            <div class="maintitle"> Networked Infrastructures</div>
            <div class="subtitle"> Three geographies (environmental, economic, political)</div>
            <img src="gif5.gif">
          </a>
        </div>
        <div class="projects">
          <a href="matilde/matilde.html">
            <div class="maintitle"> Networked Infrastructures</div>
            <div class="subtitle"> Three geographies (environmental, economic, political)</div>
            <img src="gif5.gif">
          </a>
        </div>
        <div class="projects">
          <a href="matilde/matilde.html">
            <div class="maintitle"> Networked Infrastructures</div>
            <div class="subtitle"> Three geographies (environmental, economic, political)</div>
            <img src="gif5.gif">
          </a>
        </div>
      </div>
    </li>
    <!-- PROJECT 2-->
    <li>
      <div class="scroll-content">
        <div class="projects">
          <a href="matilde/matilde.html">
            <div class="maintitle"> Networked Infrastructures</div>
            <div class="subtitle"> Three geographies (environmental, economic, political)</div>
            <img src="gif5.gif">
          </a>
        </div>
        <div class="projects">
          <a href="matilde/matilde.html">
            <div class="maintitle"> Networked Infrastructures</div>
            <div class="subtitle"> Three geographies (environmental, economic, political)</div>
            <img src="gif5.gif">
          </a>
        </div>
        <div class="projects">
          <a href="matilde/matilde.html">
            <div class="maintitle"> Networked Infrastructures</div>
            <div class="subtitle"> Three geographies (environmental, economic, political)</div>
            <img src="gif5.gif">
          </a>
        </div>
      </div>
    </li>
    <!-- PROJECT 3 -->
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
    <li>11</li>
    <li>12</li>
  </ul>
  <script>
    document.addEventListener('DOMContentLoaded', function() {
      // 点击切换展开/收起
      const items = document.querySelectorAll('ul li');
      
      items.forEach(item => {
        item.addEventListener('click', function() {
          const isActive = this.classList.contains('active');
          items.forEach(i => i.classList.remove('active'));
          if (!isActive) this.classList.add('active');
        });
      });

      // 无限自动滚动
      const scrollContainers = document.querySelectorAll('.scroll-content');
      
      scrollContainers.forEach(container => {
        const content = container.innerHTML;
        container.innerHTML += content;
        
        let scrollPosition = 0;
        const scrollSpeed = 1;
        let animationId;
        
        function autoScroll() {
          scrollPosition += scrollSpeed;
          if (scrollPosition >= container.scrollHeight / 2) {
            scrollPosition = 0;
          }
          container.scrollTop = scrollPosition;
          animationId = requestAnimationFrame(autoScroll);
        }
        
        autoScroll();
        
        container.addEventListener('mouseover', () => cancelAnimationFrame(animationId));
        container.addEventListener('mouseout', () => autoScroll());
      });
    });
  </script>
</body>
</html>

内容的提问来源于stack exchange,提问作者Maria Bastos Proença

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:49:59