Объяснение
К сожалению, CSS не может знать, какие значения transform
имеют элементы ранее, без явного указания. Тем не менее, есть решение для вашей проблемы: просто скажите CSS явно начальные значения transform
.
Чтобы достичь того, что вы хотите, используя чистый CSS, мы можем использовать calc
функция для выполнения расчетов. Наряду с calc
мы также будем использовать CSS пользовательских свойств , чтобы объявить начальное значение преобразования явно . Затем также сообщите CSS значение translateY
(например, 30px
), необходимое для анимации затухания. Поскольку calc
можно использовать для работы с пользовательскими свойствами CSS, теперь мы можем вычислить желаемое конечное значение translate
(например, translate: 0px calc(var(--initial-transformY) + var(--added-transformY))
). Поместив все эти операции в класс (например, .fadeOutDown
), теперь мы можем просто добавить этот класс к любым элементам, которые вы хотите исчезнуть.
Solution # 1
Вот пример, показывающий, как использовать пользовательские свойства CSS и calc
вместе для достижения желаемого. В этом примере вы можете просто добавить класс fadeOutDown
(без использования атрибута animation
) к элементам, которые хотите исчезнуть. Класс добавит значение translateY
к фиксированному значению 30px
(вы также можете использовать пользовательское свойство CSS, если хотите).
const foo = document.querySelector('.foo')
const bar = document.querySelector('.bar')
bar.addEventListener('click', e => {
foo.classList.toggle('fadeOutDown')
})
* {
box-sizing: border-box;
font-family: Helvetica;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
.foo {
--initial-transformY: -10px;
position: absolute;
bottom: 0;
left: 50%;
width: 40%;
background: #121212;
color: white;
border-radius: 5px;
padding: 16px;
text-align: center;
transform: translate(-50%, var(--initial-transformY));
/* or for Firefox, you can also use this -> translate: -50% var(--initial-transformY);*/
transition:
transform .5s ease,
opacity .5s ease;
}
.fadeOutDown {
opacity: 0;
transform: translate(-50%, calc(var(--initial-transformY) + 30px));
/* or for Firefox, you can also use this -> translate: -50% calc(var(--initial-transformY) + 30px) */
/* Or you can use a CSS custom property like this (Firefox)
--fadeOutDown-value: 30px;
translate: -50% calc(var(--initial-transformY) + var(--fadeOutDown-value)); */
}
.bar {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 16px;
background: #ad17fd;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
transition: all .2s ease;
text-transform: uppercase;
}
<div class="foo">Hello there, I am foo</div>
<button class="bar">Click me to move foo</button>
Вот пример использования свойства animation
. Я не рекомендую использовать это, потому что обратная анимация мгновенная (вы можете сделать так, чтобы она появлялась постепенно, но это лишняя работа). Проще использовать transition
и transform
вместе (вышеуказанный подход).
const foo = document.querySelector('.foo')
const bar = document.querySelector('.bar')
bar.addEventListener('click', e => {
foo.classList.toggle('fadeOutDown')
})
@keyframes fadeOutDown {
from {}
to {
opacity: 0;
translate: var(--initial-transformX) calc(var(--initial-transformY) + 30px);
}
}
* {
box-sizing: border-box;
font-family: Helvetica;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
.foo {
--initial-transformX: -50%;
--initial-transformY: -10px;
position: absolute;
bottom: 0;
left: 50%;
width: 40%;
background: #121212;
color: white;
border-radius: 5px;
padding: 16px;
text-align: center;
translate: var(--initial-transformX) var(--initial-transformY);
}
.fadeOutDown {
animation: .5s ease 0s fadeOutDown forwards;
}
.bar {
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
padding: 16px;
background: #ad17fd;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
transition: all .2s ease;
text-transform: uppercase;
}
<div class="foo">Hello there, I am foo</div>
<button class="bar">Click me to move foo</button>
Решение # 2
Или, как предлагается в комментариях к вашему вопросу, вы можете добавить еще одну оболочку так что вы можете применить два значения преобразования.
const foo = document.querySelector('.foo')
const bar = document.querySelector('.bar')
bar.addEventListener('click', e => {
foo.classList.toggle('fadeOutDown')
})
* {
box-sizing: border-box;
font-family: Helvetica;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
.wrapper {
--initial-transformY: -10px;
position: absolute;
bottom: 0;
left: 50%;
width: 40%;
color: white;
text-align: center;
translate: -50% -10px;
}
.foo {
width: 100%;
background: #121212;
padding: 16px;
border-radius: 5px;
transition: translate .5s ease, opacity .5s ease;
}
.fadeOutDown {
opacity: 0;
translate: 0px 30px;
}
.bar {
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
padding: 16px;
background: #ad17fd;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
transition: all .2s ease;
text-transform: uppercase;
}
<div class="wrapper">
<div class="foo">Hello there, I am foo</div>
</div>
<button class="bar">Click me to move foo</button>