CSS 绝对定位和相对定位之间的转换

发布于 2024-12-14 01:39:34 字数 1969 浏览 2 评论 0原文

是否可以将 position:relativeposition:absolute 与平滑的 CSS 转换结合起来?

我正在创建一个小部件(我称之为 Deck),我不希望它具有折叠和展开状态。到目前为止一切都很好,一切正常。

两种状态之间的切换自然需要过渡动画。这也有效,但不是我想要的方式。我想使用 CSS 转换,而不是像我现在那样使用绝对定位和 JavaScript。

当前的情况是:在展开状态下,牌组中的牌总是绝对定位的,它们的位置是在添加到牌组时动态计算的。折叠时,前四张卡以层叠方式堆叠,其余的位于第四张卡的顶部。在视觉上模仿一堆或一堆。

这种方法的问题是,我不能依赖正常的布局流程来定位卡片,这由于多种原因而很糟糕。如果我对处于展开状态的卡片使用 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>

Is it possible to combine position: relative and position: absolute with smooth CSS-transitions?

I'm creating a small widget (I call it a Deck), which I wan't to have a collapsed and expanded state. All well so far, this is working fine.

Switching between the two states naturally warrants a transition animation. This is working too, but not the way I would like it to. I Want to use CSS-transitions, instead of using absolute positioning and JavaScript, like I am currently.

The current scenario is: in expanded state the cards in the deck are always positioned absolutely, their position being calculated on the fly as they are added to the deck. When collapsing, the first four are stacked in a cascading manner and the rest on top of the fourth card. Visually mimicking a pile or stack.

The problem with this approach, is that I can't rely on normal layout flow for positioning the cards, which sucks for many reasons. If I use position: relative for the cards in expanded state, they flow nicely one after another. But the transition to collapsed state is not being animated - simply snapping from one position to the other in an instant. This is of course logical since without absolute positioning in the first place, the browser doesn't know whence from the transition should start.

In my perfect world, adding the class collapsed to div.deck-container would animate the cards into their collapsed positions and vice versa, but it seems this isn't possible. Please someone tell me I'm wrong.

$('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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

被你宠の有点坏 2024-12-21 01:39:34

不,您无法为 position 属性设置动画。您只能为一些 css 属性设置动画,并且大多数都将数字或颜色作为值(有一些例外)。您可以在 w3c css 过渡规范中查看此列表。

无论如何,由于您可以为 topleft 属性设置动画,因此您可以稍微更改标记以实现效果。

我只是将原始位置设置为绝对位置并定位这些元素。然后,当切换类时,只有 topleft 属性发生变化,因此转换有效。

$('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>

No, you can't animate the position property. There are only a number of css properties you can animate, and most of them have numbers or colors as values (With some exceptions). You can see this list in the w3c css transitions especification.

Anyway, since you can animate top and left properties, you could change your markup a little to achieve the effect.

I just set the original position to absolute and positioned those elements. Then, when toggling the class, only top and left attributes change, so the transition works.

$('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>

等数载,海棠开 2024-12-21 01:39:34

也许你可以使用 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>

Maybe you could use translate instead:

$('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>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文