混合绝对定位和相对定位的 CSS 过渡

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8049855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 02:07:00  来源:igfitidea点击:

CSS transitions mixing absolute and relative positioning

css-transitionscss

提问by nikc.org

Short and sweet version:

简短而甜蜜的版本:

Is it possible to combine position: relativeand position: absolutewith smooth CSS-transitions?

是否有可能结合起来position: relative,并position: absolute与流畅的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: relativefor 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.

这种方法的问题是我不能依靠正常的布局流程来定位卡片,这很糟糕,原因有很多。如果我position: relative用于展开状态的卡片,它们会一张一张地流畅地流动。但是到折叠状态的过渡并不是动画——只是在瞬间从一个位置捕捉到另一个位置。这当然是合乎逻辑的,因为首先没有绝对定位,浏览器显然不知道从哪里过渡。

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 collapsedto div.deck-containerwould animate the cards into their collapsed positions and vice versa, but it seems this isn't possible. Please someone tell me I'm wrong.

在我的完美世界中,将类添加collapseddiv.deck-container可以将卡片动画到折叠位置,反之亦然,但这似乎是不可能的。请有人告诉我我错了。

回答by scumah

No, you can't animate the positionproperty. 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.

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

Anyway, since you can animate topand leftproperties, you could change your markup a little to achieve the effect, as in this fiddle.

无论如何,由于您可以设置动画topleft属性,因此您可以稍微更改您的标记以达到效果,就像在这个 fiddle 中一样

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 leftattributes change, so the transition works.

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

回答by nd_macias

@nikc.org Maybe you could use translateinstead:

@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

工作示例