如何在多页面应用中为元素出现时添加向下滑动的动画?
我正在使用现代HTML和 CSS构建一个多页面应用(MPA),但不使用任何JavaScript框架。
我有一个表单,在提交时出现错误就会显示一个错误信息。
我想为错误信息添加向下滑动的动画,这样看起来就像把其余表单字段往下推移。
我正在使用跨文档视图转换来尝试实现这个效果。
问题在于,动画在开始过渡前就会显示一个与错误信息同等大小的空白区域。
我想让动画看起来像Svelte的 slide动画:

但实际显示如下:

MRE的代码:
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>View transition MRE</title>
</head>
<body>
<style>
@view-transition {
navigation: auto;
}
:root {
interpolate-size: allow-keywords;
color-scheme: dark light;
}
body {
font-family: system-ui;
}
.incoming {
view-transition-name: --incoming;
}
::view-transition-image-pair(--incoming) {
overflow-y: clip;
}
::view-transition-new(--incoming) {
animation-duration: 3s;
@media (prefers-reduced-motion: no-preference) {
animation-name: --slide-down-in;
}
}
@keyframes --slide-down-in {
from {
block-size: 0;
}
to {
block-size: auto;
}
}
</style>
<main>
<h1>View transition MRE</h1>
<p><a href="/mre/without.html">Toggle</a></p>
<!-- Previous page does not have the .incoming element -->
<p class="incoming">Slides in</p>
<p>Lorem ipsum</p>
</main>
</body>
</html>
如何在不在动画开始前显示空白区域的前提下,让向下滑动的动画正常工作?
解决方案
你可以对 incoming 元素使用 clip-path 动画。
要让文本按你想要的方式向下移动,你需要给它一个 view-transition-name,使它从在 without.html 中的位置过渡到在 index.html 中的位置:
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>View transition MRE</title>
</head>
<body>
<style>
@view-transition {
navigation: auto;
}
:root {
interpolate-size: allow-keywords;
color-scheme: dark light;
}
body {
font-family: system-ui;
}
.incoming {
view-transition-name: --incoming;
}
::view-transition-group(--incoming) {
animation-duration: 3s;
}
::view-transition-new(--incoming) {
animation-name: --slide-in;
}
::view-transition-old(--incoming) {
animation-name: --slide-out;
}
@keyframes --slide-in {
from {
clip-path: inset(0 0 100% 0);
}
to {
clip-path: inset(0 0 0 0);
}
}
@keyframes --slide-out {
from {
clip-path: inset(0 0 0 0);
}
to {
clip-path: inset(0 0 100% 0);
}
}
.text {
view-transition-name: --text;
}
::view-transition-group(--text){
animation-duration: 3s;
}
</style>
<main>
<h1>View transition MRE</h1>
<p><a href="/without.html">Toggle</a></p>
<div class="incoming"><p>Slides in</p></div>
<p class="text">Lorem ipsum</p>
</main>
</body>
</html>
Stackblitz演示
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。