Подтвердить что ты не робот

Переходы CSS с абсолютным и относительным позиционированием

Короткий и сладкий вариант:

Можно ли комбинировать position: relative и position: absolute с плавными переходами CSS?

Расширенная версия:

Я создаю небольшой виджет (я называю его палубой), и я не смогу иметь свернутое и расширенное состояние. Все хорошо, пока это нормально работает.

Переключение между двумя состояниями, естественно, требует переходной анимации. Это тоже работает, но не так, как хотелось бы. То, что я хотел бы сделать, - это использование CSS-перехода вместо использования абсолютного позиционирования с использованием JavaScript, как и сейчас.

Увы, нынешний сценарий заключается в том, что в расширенном состоянии карты в колоде всегда позиционируются абсолютно, их позиция вычисляется "на лету", поскольку они добавляются в колоду. Когда рушится, первые четыре складываются каскадным образом, а остальные - на четвертую. Визуальный имитирующий стек.

Проблема с этим подходом заключается в том, что я не могу полагаться на нормальный поток макета для размещения карт, что отстойно по многим причинам. Если я использую position: relative для карт в расширенном состоянии, они отлично меняются один за другим. Но переход к свернутому состоянию не анимируется - просто мгновение привязывается к одной позиции в другую. Это, конечно, логично, так как без абсолютного позиционирования в первую очередь браузер явно не знает, с чего перейти.

То, что у меня есть до сих пор (Fiddle):

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 (только соответствующая разметка):

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

В моем прекрасном мире добавление класса collapsed в div.deck-container будет анимировать карты в их рухнувшие позиции и наоборот, но, похоже, это невозможно. Пожалуйста, скажите мне, что я не прав.

4b9b3361

Ответ 1

Нет, вы не можете анимировать свойство position. Есть только несколько свойств css, которые вы можете оживить, и большинство из них имеют числа или цвета в качестве значений (за некоторыми исключениями). Вы можете увидеть этот список в w3c css переходов especification.

В любом случае, поскольку вы можете анимировать свойства 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;
}

Я просто установил исходное положение в абсолютное положение и разместил эти элементы. Затем при переключении класса изменяются только атрибуты top и left, поэтому переход работает.

Ответ 2

@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);
    }

рабочий пример