CSS转换混合了绝对和相对的定位

时间:2022-11-18 17:31:21

Short and sweet version:

简单明了的版本:

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

是否可能将位置:相对位置和绝对位置与平滑的css转换结合起来?

Verbose version:

详细版:

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

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

Switching between the two states, naturally warrants a transition animation. This is working too, but not the way I would like it to be realized. What I would like to do, is use CSS-transitioning, instead of using absolute positioning using JavaScript, like I am now.

在两种状态之间切换,自然需要转换动画。这也在起作用,但不是我希望它被实现的方式。我想做的是使用css转换,而不是像现在这样使用JavaScript的绝对定位。

Alas, 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 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 ofcourse logical since without absolute positioning in the first place, the browser clearly doesn't know from where to transition from.

这种方法的问题在于,我不能依靠正常的布局流来定位卡片,这很糟糕,原因有很多。如果我使用位置:相对于扩展状态下的卡片,它们一个接一个地流动得很好。但向崩溃状态的过渡并不是动态的——只是瞬间从一个位置切换到另一个位置。这当然是理所当然的,因为没有绝对的定位,浏览器显然不知道从哪里过渡。

What I have so far is this (Fiddle):

到目前为止我所掌握的是(小提琴)

CSS (relevant rules only):

CSS(相关规则只):

div.deck-container {
    position: relative;
}
div.deck-container li {
    display: inline-block;
    position: relative;

    -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
    -o-transition: all 0.5s ease-in-out;
    -ms-transition: all 0.5s ease-in-out;
    transition: all 0.5s ease-in-out;
}
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;
}

HTML (relevant markup only):

HTML(仅相关标记):

<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>

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.

在我的完美世界中,将类合并到div.deck-container中会使卡片动画到它们的折叠位置,反之亦然,但这似乎是不可能的。请别人告诉我我错了。

2 个解决方案

#1


36  

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.

不,你不能对位置属性进行动画处理。可以动画化的css属性只有很多,而且大多数都有数字或颜色作为值(除了一些例外)。您可以在w3c css转换术语中看到这个列表。

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

无论如何,既然您可以对top和left属性进行动画处理,那么您可以稍微修改一下标记,以达到效果,就像在这个小提琴中一样。

div.deck-container {
    position: relative;
}
div.deck-container li {
    background-color: #fff;
    position: absolute;
    border: 1px solid black;
    padding: 3px;
    display: inline-block;
    -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
    -o-transition: all 0.5s ease-in-out;
    -ms-transition: all 0.5s ease-in-out;
    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;
}

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

我只是将原始位置设置为绝对位置,并将这些元素定位。然后,在切换类时,只有topand left属性发生变化,因此转换工作正常。

#2


15  

@nikc.org Maybe you could use translate instead:

@nikc.org也许你可以用translate来代替:

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

    div.deck-container.collapsed li:first-child {
      -webkit-transform: translate(0, 0);
         -moz-transform: translate(0, 0);
          -ms-transform: translate(0, 0);
           -o-transform: translate(0, 0);
              transform: translate(0, 0);
    }
    div.deck-container.collapsed li:nth-child(2) {
        -webkit-transform: translate(-100%, 2px);
         -moz-transform: translate(-100%, 2px);
          -ms-transform: translate(-100%, 2px);
           -o-transform: translate(-100%, 2px);
              transform: translate(-100%, 2px);
    }
    div.deck-container.collapsed li:nth-child(3) {
        -webkit-transform: translate(-200%, 4px);
         -moz-transform: translate(-200%, 4px);
          -ms-transform: translate(-200%, 4px);
           -o-transform: translate(-200%, 4px);
              transform: translate(-200%, 4px);
    }

working example

工作示例

#1


36  

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.

不,你不能对位置属性进行动画处理。可以动画化的css属性只有很多,而且大多数都有数字或颜色作为值(除了一些例外)。您可以在w3c css转换术语中看到这个列表。

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

无论如何,既然您可以对top和left属性进行动画处理,那么您可以稍微修改一下标记,以达到效果,就像在这个小提琴中一样。

div.deck-container {
    position: relative;
}
div.deck-container li {
    background-color: #fff;
    position: absolute;
    border: 1px solid black;
    padding: 3px;
    display: inline-block;
    -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
    -o-transition: all 0.5s ease-in-out;
    -ms-transition: all 0.5s ease-in-out;
    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;
}

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

我只是将原始位置设置为绝对位置,并将这些元素定位。然后,在切换类时,只有topand left属性发生变化,因此转换工作正常。

#2


15  

@nikc.org Maybe you could use translate instead:

@nikc.org也许你可以用translate来代替:

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

    div.deck-container.collapsed li:first-child {
      -webkit-transform: translate(0, 0);
         -moz-transform: translate(0, 0);
          -ms-transform: translate(0, 0);
           -o-transform: translate(0, 0);
              transform: translate(0, 0);
    }
    div.deck-container.collapsed li:nth-child(2) {
        -webkit-transform: translate(-100%, 2px);
         -moz-transform: translate(-100%, 2px);
          -ms-transform: translate(-100%, 2px);
           -o-transform: translate(-100%, 2px);
              transform: translate(-100%, 2px);
    }
    div.deck-container.collapsed li:nth-child(3) {
        -webkit-transform: translate(-200%, 4px);
         -moz-transform: translate(-200%, 4px);
          -ms-transform: translate(-200%, 4px);
           -o-transform: translate(-200%, 4px);
              transform: translate(-200%, 4px);
    }

working example

工作示例