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