CSS-переходы, смешивающие абсолютное и относительное позиционирование - PullRequest
27 голосов
/ 08 ноября 2011

Короткая и сладкая версия:

Можно ли объединить 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 оживило бы карты в их свернутые позиции и наоборот, но, похоже, это невозможно. Пожалуйста, кто-нибудь, скажите мне, что я неправ.

Ответы [ 2 ]

40 голосов
/ 08 ноября 2011

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

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

15 голосов
/ 15 марта 2013

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

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

...