H5 手风琴式UI
标签搜索
侧边栏壁纸
  • 累计撰写 36 篇文章
  • 累计收到 59 条评论

H5 手风琴式UI

shthah
2024-06-07 / 2 评论 / 139 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年12月05日,已超过140天没有更新,若内容或图片失效,请留言反馈。

Elements 和Elements 非常适合实现手风琴 UI

创建手风琴 UI 时使用
元素和元素

HTML 结构很简单。可以看到,从标签名称就可以理解其结构。
如果您想创建手风琴所需的最小打开/关闭动作,则不需要 CSS;HTML 就足够了。

<details>
  <summary>概要</summary>
  详细内容
</details>

添加CSS 样式优化

接下来,我们将使用 CSS 更改外观。我们将使用以下图标创建一个手风琴 UI。
手风琴01.gif

<details class="js-details">
  <summary class="js-summary">
    <span class="summary_inner">
      标题标题 <span class="icon"></span>
    </span>
  </summary>
  <div class="content js-content">
    <div class="content_inner">
      内容部分内容部分内容部分内容部分内容部分内容部分
    </div>
  </div>
</details>
details {
  margin: 0 auto;
  width: 70%;
  summary {
    /* display: list-item;清除默认三角图标样式 */
    display: block;
    .summary_inner {
      cursor: pointer;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      align-items: center;
      padding: 16px 24px;
      border: 1px solid #d2beff;
      font-weight: bold;
      color: #002255;
      .icon {
        display: block;
        position: relative;
        width: 24px;
        margin-left: 6px;
        flex-shrink: 0;
        transform-origin: center 43%;
        transition: transform 0.4s;
        &::before,
        &::after {
          content: "";
          position: absolute;
          display: block;
          width: 15px;
          height: 3px;
          background-color: #7050ff;
        }
        &::before {
          left: 0;
          transform: rotate(45deg);
        }

        &::after {
          right: 0;
          transform: rotate(-45deg);
        }
      }
    }
  }
  summary::-webkit-details-marker {
    /* Safari中修改相应的值 */
    display: none;
  }

  /* details 内不直接指定padding */
  .content { 
    overflow: hidden;
    background-color: #f0f2ff;

    &_inner {
     padding: 24px 48px;
      display: flex;
      flex-direction: column;
      gap: 16px;
    }
  }
}

/* 打开内容展示时  旋转三角哦图标 */
details[open] .icon {
  transform: rotate(180deg);
}

使用JS添加动画 优化展示效果

通过单击或使用键盘来打开和关闭手风琴。这次,我们将使用标准浏览器功能Web Animations API来为手风琴的内容制作动画。
手风琴02.gif

<details class="js-details">
  <summary class="js-summary">
    <span class="summary_inner">
      标题标题标题标 <span class="icon"></span>
    </span>
  </summary>
  <div class="content js-content">
    <div class="content_inner">
      内容部分内容部分内容部分内容部分内容部分内容部分
    </div>
  </div>
</details>
details {
  margin: 10px auto;
  width: 70%;
  summary {
    /* display: list-item;清除默认三角图标样式 */
    display: block;
    .summary_inner {
      cursor: pointer;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      align-items: center;
      padding: 16px 24px;
      border: 1px solid #d2beff;
      font-weight: bold;
      color: #002255;
      .icon {
        display: block;
        position: relative;
        width: 24px;
        margin-left: 6px;
        flex-shrink: 0;
        transform-origin: center 43%;
        transition: transform 0.4s;
        &::before,
        &::after {
          content: "";
          position: absolute;
          display: block;
          width: 15px;
          height: 3px;
          background-color: #7050ff;
        }
        &::before {
          left: 0;
          transform: rotate(45deg);
        }

        &::after {
          right: 0;
          transform: rotate(-45deg);
        }
      }
    }
  }
  summary::-webkit-details-marker {
    /* Safari中修改相应的值 */
    display: none;
  }

  /* details 内不直接指定padding */
  .content { 
    overflow: hidden;
    background-color: #f0f2ff;

    &_inner {
     padding: 24px 48px;
      display: flex;
      flex-direction: column;
      gap: 16px;
    }
  }
}


/* is-opened js控制类添加时展示 */
details.is-opened .icon {
  transform: rotate(180deg);
}
document.addEventListener("DOMContentLoaded", () => {
  setUpAccordion();
});

/** 
 * JS 原生 (Web Animations API) animate()
 */
const setUpAccordion = () => {
  const details = document.querySelectorAll(".js-details");
  const RUNNING_VALUE = "running"; // 动画运行添加属性值
  const IS_OPENED_CLASS = "is-opened";

  details.forEach((element) => {
    const summary = element.querySelector(".js-summary");
    const content = element.querySelector(".js-content");

    summary.addEventListener("click", (event) => {
      // 禁用默认行为
      event.preventDefault();

      // 防止连点, 动画执行时 点击无效
      if (element.dataset.animStatus === RUNNING_VALUE) {
        return;
      }

      // 判断当前 details 的 open 属性
      if (element.open) {
        // 关闭时操作
        // 切换图标操作类
        element.classList.toggle(IS_OPENED_CLASS);

        // 运行动画
        const closingAnim = content.animate(
          closingAnimKeyframes(content),
          animTiming
        );
        // 指定动画运行时 使用的值
        element.dataset.animStatus = RUNNING_VALUE;

        //  手风琴 关闭后
        closingAnim.onfinish = () => {
          // 删除自定义属性 open
          element.removeAttribute("open");
          // 删除动画运行时的值
          element.dataset.animStatus = "";
        };
      } else {
        //打开手风琴时的处理
        //添加自定义 open属性
        element.setAttribute("open", "true");

        // 添加样式
        element.classList.toggle(IS_OPENED_CLASS);

        // 执行打开动画
        const openingAnim = content.animate(
          openingAnimKeyframes(content),
          animTiming
        );
        // 赋值动画运行时 状态
        element.dataset.animStatus = RUNNING_VALUE;

        // 动画运行完成后  置空
        openingAnim.onfinish = () => {
          element.dataset.animStatus = "";
        };
      }
    });
  });
};

/**
 * 动画 配置
 */
const animTiming = {
  duration: 400,
  easing: "ease-out"
};

/**
 * 关闭时的 关键帧 
 */
const closingAnimKeyframes = (content) => [
  {
    height: content.offsetHeight + 'px', // height: "auto" 设置auto时 不能很好的计算
    opacity: 1,
  }, {
    height: 0,
    opacity: 0,
  }
];

/**
 * 打开时 关键帧
 */
const openingAnimKeyframes = (content) => [
  {
    height: 0,
    opacity: 0,
  }, {
    height: content.offsetHeight + 'px',
    opacity: 1,
  }
];
参考示例
0

评论 (2)

取消
  1. 头像
    gumdopperm
    Windows 10 · Google Chrome

    首尾呼应,主题鲜明,收束有力。

    回复
  2. 头像
    nodupawoaa
    Windows 10 · Google Chrome

    ?批判性评语?

    回复