【问题标题】:Animating horizontal menu (overlapping menu items without positioning them absolutely)动画水平菜单(重叠菜单项而不绝对定位它们)
【发布时间】:2022-01-12 15:18:43
【问题描述】:

所以一个客户要求我实现一个菜单动画。它最初是由设计师使用 InvisionApp 创建的。而且该应用程序只是获取菜单项并将它们绝对定位,这在网站上应该不是一个好主意(响应能力等)。

我已经用绝对定位的 jsfiddle 复制了 html/css 中的设计:

ul {
  list-style: none;
  display: flex;
  position: relative;
}

li {
  padding: 5px 15px;
  position: absolute;
  animation-name: menu-fold;
  animation-duration: 3s;
  animation-iteration-count: infinite;
}

li:nth-child(1) { right: 0; }
li:nth-child(2) { right: 119px; }
li:nth-child(3) { right: 238px; }
li:nth-child(4) { right: 357px; }
li:nth-child(5) { right: 476px; }

@keyframes menu-fold {
  from {
    opacity: 1;
  }
  
  to {
    opacity: 0;
    right: 0
  }
}
<ul>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
</ul>

您将如何在保持响应能力的同时制作这种动画?

(我知道 JavaScript 会有一些方法——虽然我还没有尝试过——但如果可能的话,我想避免使用 JavaScript。如果你说只有 JS 才有可​​能,我仍然会想听听你的建议:P)

// 编辑 1:我想出了一个快速的 jQuery 解决方案,但是,我不知道,我还是想避免它。至少感觉不是很好的解决方案:

var lastItemX = $('ul li').last().position().left;

$('ul li').each(function() {
    var currentItemX = $(this).position().left;
    $(this).css('transform', `translateX(${lastItemX - currentItemX}px)`)
})
html, body {
  margin: 0;
  padding: 0;
}

ul {
  padding: 0;
  list-style: none;
  display: flex;
  position: relative;
}

li {
  padding: 5px 15px;
  transition: transform 3s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
  <li>Menu Item 1</li>
</ul>

【问题讨论】:

  • 不要使用绝对单位,即px,您应该尝试使用相对单位,如%
  • @pete 肯定会提高响应能力。但是我仍然不喜欢这种解决方案,因为如果您更改菜单中的单词,它仍然会中断。

标签: javascript css css-animations


【解决方案1】:

这是一种方式,使用 flex,转换 width,并使用 :hover,其中只有第一个元素可见,直到您将鼠标悬停在它上面:

.my-list {
  list-style: none;
  padding: 0;
  display: flex;
  margin-left: auto;
  background: yellow;
  width: 20%;
  transition: width 0.5s ease;
  overflow: hidden
}

.my-list:hover {
  width: 100%;
}

.my-list li {
  display: none;
  flex: auto;
  background: orange
}

.my-list li:first-child,
.my-list:hover li {
  display: block;
  width: 20%;
  margin: 5px;
  padding: 5px;
}
<div>
  <ul class="my-list">
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
  </ul>
</div>

设计本身并不是最好的响应能力,任何超过 15 个字符的菜单项在较小的显示器上都不会很好看,因为没有足够的可用宽度。

JavaScript 的一个常见用途是通过一些去抖动/节流机制来防止动画抖动,并且可以通过切换 CSS 类名将动画本身留给 CSS。

这是另一种方式,其中每个项目占据整个宽度并具有固定高度:(并且 JS 仅切换 CSS 类)

function myListOpen() {
  document.querySelector(".my-list").classList.add("open")
}

function myListClose() {
  document.querySelector(".my-list").classList.remove("open")
}
.my-list {
  list-style: none;
  margin-left: auto;
  background: yellow;
  padding: 5px;
  width: 20%;
  overflow: hidden;
  transition: width 0.5s ease;
}

.my-list.open {
  width: 100%;
}

.my-list li {
  background: orange;
  margin: 0;
  padding: 0;
  padding-left: 1em;
  height: 0;
  line-height: 2em;
  transition: height 0.5s ease;
}

.my-list li:first-child,
.my-list.open li {
  height: 2em;
  visibility: visible;
}
<button type="button" onclick="myListOpen()">open</button>
<button type="button" onclick="myListClose()">close</button>
<hr />

<div>

  <ul class="my-list">
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
    <li>Menu Item 1</li>
  </ul>

</div>

【讨论】:

    猜你喜欢
    • 2016-04-08
    • 2018-09-06
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2012-09-08
    相关资源
    最近更新 更多