CSS绝对定位和相对定位之间的过渡效果

38

是否可以在 CSS 转换中结合 position: relativeposition: absolute 并实现平滑过渡效果?

我正在创建一个小部件(我称之为 Deck),该部件具有折叠和展开状态。到目前为止,一切都很好,这个功能正常运作。

自然而然地,两种状态之间需要转换动画。虽然当前使用绝对定位和 JavaScript 实现了效果,但我想使用 CSS 转换效果。

当前的情况是:在展开状态下,甲板上的卡牌始终被绝对定位,它们的位置在添加到甲板时即时计算。当折叠时,前四张卡牌以级联方式堆叠,而其他卡牌则位于第四张卡牌之上。视觉上模仿了一堆或一叠。

这种方法的问题在于,我无法依赖于普通的布局流来定位卡牌,这种方法有许多缺点。如果我为展开状态下的卡牌使用 position: relative,它们会很好地一个接一个地排列。但是,从展开状态到折叠状态的转换没有被动画化 - 在瞬间从一个位置切换到另一个位置。当然,这是合乎逻辑的,因为如果一开始没有绝对定位,浏览器就不知道从哪里开始过渡。

在我的完美世界中,将类 collapsed 添加到 div.deck-container 中会将卡牌动画显示为其折叠位置和反之亦然,但似乎这是不可能的。请有人告诉我我错了。

$('button#toggler').click(function() {
  $('div.deck-container').toggleClass('collapsed');
});
div.deck-container {
  position: relative;
}

div.deck-container li {
  display: inline-block;
  position: relative;
  transition: all 0.5s ease-in-out;

  border: 1px solid black;
  padding: 3px;
  background-color: #fff;
}

div.deck-container.collapsed li {
  position: absolute;
  left: 9px;
  top: 6px;
}

div.deck-container.collapsed li:first-child {
  left: 0;
  top: 0px;
}

div.deck-container.collapsed li:nth-child(2) {
  left: 3px;
  top: 2px;
}

div.deck-container.collapsed li:nth-child(3) {
  left: 6px;
  top: 4px;
}

button {
  position: absolute;
  top: 50px;
  left: 50px;
}
<div class="deck-container">
  <ul>
    <li>Card 1</li>
    <li>Card 2</li>
    <li>Card 3</li>
    <li>Card 4</li>
    <li>Card 5</li>
  </ul>
</div>

<button id="toggler">Toggle state</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

2个回答

45
不,您不能对“position”属性进行动画处理。只有一些CSS属性可以进行动画处理,其中大多数具有数字或颜色值(有一些例外)。您可以在w3c css transitions especification中查看此列表。
无论如何,由于您可以对“top”和“left”属性进行动画处理,因此您可以稍微更改标记以实现效果。
我只是将原始位置设置为绝对位置并定位了这些元素。然后,在切换类时,只有“top”和“left”属性发生变化,因此过渡有效。

$('button#toggler').click(function() {
  $('div.deck-container').toggleClass('collapsed');
});
div.deck-container {
  position: relative;
}

div.deck-container li {
  background-color: #fff;
  position: absolute;
  border: 1px solid black;
  padding: 3px;
  display: inline-block;
  transition: all 0.5s ease-in-out;
}

div.deck-container li {
  left: 160px;
  top: 0px;
}

div.deck-container li:first-child {
  left: 0px;
  top: 0px;
}

div.deck-container li:nth-child(2) {
  left: 40px;
  top: 0px;
}

div.deck-container li:nth-child(3) {
  left: 80px;
  top: 0px;
}

div.deck-container li:nth-child(4) {
  left: 120px;
  top: 0px;
}

div.deck-container.collapsed li {
  left: 12px;
  top: 8px;
}

div.deck-container.collapsed li:first-child {
  left: 0;
  top: 0px;
}

div.deck-container.collapsed li:nth-child(2) {
  left: 3px;
  top: 2px;
}

div.deck-container.collapsed li:nth-child(3) {
  left: 6px;
  top: 4px;
}

div.deck-container.collapsed li:nth-child(4) {
  left: 9px;
  top: 6px;
}

button {
  position: absolute;
  top: 50px;
  left: 50px;
}
<div class="deck-container">
  <ul>
    <li>Card 1</li>
    <li>Card 2</li>
    <li>Card 3</li>
    <li>Card 4</li>
    <li>Card 5</li>
  </ul>
</div>

<button id="toggler">Toggle state</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


18
也许你可以使用translate替代:

$('button#toggler').click(function() {
  $('div.deck-container').toggleClass('collapsed');
});
div.deck-container li {
  background-color: #fff;
  border: 1px solid black;
  padding: 3px;
  display: inline-block;
  transition: all 0.5s ease-in-out;
}

div.deck-container.collapsed li:first-child {
  transform: translate(0, 0);
}

div.deck-container.collapsed li:nth-child(2) {
  transform: translate(-100%, 2px);
}

div.deck-container.collapsed li:nth-child(3) {
  transform: translate(-200%, 4px);
}

button {
  position: absolute;
  top: 50px;
  left: 50px;
}
<div class="deck-container">
  <ul>
    <li>Card 1</li>
    <li>Card 2</li>
    <li>Card 3</li>
  </ul>
</div>

<button id="toggler">Toggle state</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接