加载时的CSS3过渡动画?

272

有没有可能在页面加载时使用CSS3过渡动画而不使用JavaScript?

这就是我想要的,但是在页面加载时:

image-slider.html

目前我找到的是


@blesh:几乎任何东西 - 例如,请参见http://www.mysociety.org/2011/08/11/mobile-operators-breaking-content/和http://robertnyman.com/2006/04/25/an-important-lesson-learned-about-ajax-and-accessibility/。 - NickFitz
2
关键帧可以实现这一点,并在不支持CSS3动画时提供最佳回退。你为什么认为它们太慢了? - zachleat
2
嗨!链接已经失效,我不知道它本来应该指向哪里,请有人帮忙修复一下,谢谢! - James Ashwood
13个回答

584

你可以在页面加载时运行一个CSS动画,而不需要使用任何JavaScript;你只需要使用CSS3 Keyframes

让我们看个例子...

这是一个使用CSS3的导航菜单滑入演示:

@keyframes slideInFromLeft {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(0);
  }
}

header {  
  /* This section calls the slideInFromLeft animation we defined above */
  animation: 1s ease-out 0s 1 slideInFromLeft;
  
  background: #333;
  padding: 30px;
}

/* Added for aesthetics */ body {margin: 0;font-family: "Segoe UI", Arial, Helvetica, Sans Serif;} a {text-decoration: none; display: inline-block; margin-right: 10px; color:#fff;}
<header>
  <a href="#">Home</a>
  <a href="#">About</a>
  <a href="#">Products</a>
  <a href="#">Contact</a>
</header>

分解它...

这里重要的部分是我们称之为slideInFromLeft的关键帧动画...

@keyframes slideInFromLeft {
    0% {
        transform: translateX(-100%);
    }
    100% {
        transform: translateX(0);
    }
}

这句话的意思是“一开始,标题将完全超出屏幕左边缘,到最后将在原位”。

第二部分调用了名为slideInFromLeft的动画:

animation: 1s ease-out 0s 1 slideInFromLeft;

以上是简略版本,以下是详细版本以便更清晰:

animation-duration: 1s; /* the duration of the animation */
animation-timing-function: ease-out; /* how the animation will behave */
animation-delay: 0s; /* how long to delay the animation from starting */
animation-iteration-count: 1; /* how many times the animation will play */
animation-name: slideInFromLeft; /* the name of the animation we defined above */

你可以做各种有趣的事情,比如滑动内容或突出显示区域。

这是W3C的说法。


32
什么导致这个在页面加载时运行,而不是任何更早的时间? - Rolf
3
为了回答上面的问题,似乎默认情况下动画在应用后0秒开始,没有延迟。还有一个名为animation-delay的属性可设置以控制此行为。参见:http://www.w3.org/TR/css3-animations/#animation-delay-property - Michael Davis
7
为了确保动画在文档加载后开始播放,请将动画代码放置在样式表中,放在body元素下方或者放在body元素底部的样式标签中。在这里,需要注意不改变原始意思,让翻译更加通俗易懂。 - TaylorMac
2
优秀的答案,帮助了我在2019年! - Gosi
2
不是“onload”,而是可以通过向关键帧添加步骤并增加动画时间来延迟启动:@keyframes slideInFromLeft { 0% { transform: translateX(-100%); } 50% { transform: translateX(-100%); } 100% { transform: translateX(0); } }header {
/* 此部分调用我们上面定义的slideInFromLeft动画 */ animation: 10s ease-out 0s 1 slideInFromLeft; background: #333; padding: 30px; }
- mHenderson
显示剩余3条评论

39

只需要很少的Javascript:

window.onload = function() {
    document.body.className += " loaded";
}

现在是CSS部分:

.fadein {
    opacity: 0;
    -moz-transition: opacity 1.5s;
    -webkit-transition: opacity 1.5s;
    -o-transition: opacity 1.5s;
    transition: opacity 1.5s;
}

body.loaded .fadein {
    opacity: 1;
}

我知道问题中提到了“无需 JavaScript”,但我认为值得指出的是,有一种简单的解决方案只需要一行 JavaScript 代码。

甚至可以是内联 JavaScript,类似于这样:

<body onload="document.body.className += ' loaded';" class="fadein">

那就是所需的全部JavaScript。


2
A little Fix: - Ivan Pirog
1
如果不需要等待页面的onLoad事件,请在</body>标签之前插入以下代码:<script type="text/javascript"> document.body.setAttribute('class', 'loaded'); </script> - Ivan Pirog
谢谢修复,伊万!我在我的帖子中已经修复了它。奇怪,我以为这应该指向 body 元素。 - Rolf
9
为避免覆盖现有的“body”类,请使用以下代码:document.body.classList.add('loaded') - Vyacheslav Cotruta
1
жҲ‘еҸ‘зҺ°document.body.className += " loaded";еңЁеҗ‘зҺ°жңүзұ»ж·»еҠ loadedзұ»ж—¶з•Ҙеҫ®дёҚеӨӘеҶ—й•ҝгҖӮ - Pim Schaaf
1
@PimSchaaf 谢谢你的建议,它完全有道理。我现在会进行编辑。如今,你还可以使用 classList,这样更加优雅一点(但兼容性较差)。 - Rolf

26

我认为我已经找到了某种解决方法来解决原始问题 - 不是通过页面“on.load”开始的转换 - 我发现使用不透明度淡入动画具有相同的效果,(我正在寻找与OP相同的东西)。

所以我想在页面加载时将正文从白色(与站点背景相同)淡入到黑色文本颜色 - 而且我只从星期一开始编码,所以我正在寻找“on.load”样式的代码,但还不知道JS - 所以这是对我很有效的代码。

#main p {
  animation: fadein 2s;
}
@keyframes fadein {
  from { opacity: 0}
  to   { opacity: 1}
}

不管出于什么原因,这对于 .class 不起作用,只对 #id 起作用(至少在我这儿是这样)。

希望这能有所帮助 - 因为我知道这个网站帮了我很多忙!


9

CSS仅使用3秒延迟

需要注意以下几点:

  • 在一次调用中实现多个动画
  • 我们创建一个等待动画,仅延迟实际动画(在我们的例子中为第二个动画)。

代码:

header {
    animation: 3s ease-out 0s 1 wait, 0.21s ease-out 3s 1 slideInFromBottom;
}

@keyframes wait {
    from { transform: translateY(20px); }
    to { transform: translateY(20px); }
}

@keyframes slideInFromBottom {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

6
这个有点棘手。
答案是“不太可能”。
CSS不是一个功能性的层。它没有任何意识到发生了什么或者何时发生的。它只是用来为不同的“标志”(类,ID,状态)添加一个表现层。
默认情况下,CSS/DOM不提供任何“加载完成”状态供CSS使用。如果你想/能够使用JavaScript,你可以分配一个类给或其他元素以激活一些CSS。
话虽如此,你可以为此创建一个hack。我将在这里举个例子,但它可能适用于您的情况。我们假设“接近”就足够了:
<html>
<head>
<!-- Reference your CSS here... -->
</head>
<body>
    <!-- A whole bunch of HTML here... -->
    <div class="onLoad">OMG, I've loaded !</div>
</body>
</html>

这是我们CSS样式表的一部分:
.onLoad
{
    -webkit-animation:bounceIn 2s;
}

我们也假设现代浏览器是逐步渲染的,因此我们的最后一个元素将最后呈现,所以这个CSS将最后被激活。

3

更简单的解决方案(仍然使用[一行内联]JavaScript):

将此作为body标签: 请注意,body.this.对我无效。只有长的;querySelector允许使用classList.remove(Linux Chromium)

<body class="onload" onload="document.querySelector('body').classList.remove('onload')">

在你的其他CSS规则之上添加这一行。
body.onload *{ transform: none !important; }

请注意,这也适用于不透明度(由其他用户请求):只需将不透明度作为过渡触发器即可。(甚至可以以相同方式使用任何其他CSS规则,并且您可以使用多个类来显式延迟触发时间)
逻辑相同。在 body.onload 上强制执行无变换(使用 :none !important 在所有子元素上),一旦文档加载完成,删除该类以触发您在 CSS 中指定的所有元素上的所有过渡效果。
以下是第一个答案(请参见上面的编辑内容以获取更短的答案)
以下是反向解决方案:
1. 制作HTML布局并根据最终结果设置CSS(包括所有所需的转换)。 2. 根据喜好设置过渡属性。 3. 为要在加载后进行转换的元素添加类(例如:waitload)。此处关键字是CSS中的!important。 4. 文档加载完成后,使用JS从元素中删除类,以开始转换(并删除transition:none覆盖)。
适用于多个元素上的多个转换。未尝试跨浏览器兼容性。

div {
  width: fit-content;
}

#rotated {
  transform: rotate(-50deg)/* any other transformation */
  ;
  transition: 6s;
}

#translated {
  transform: translate(90px)/* any other transformation */
  ;
  transition: 6s;
}

.waitload {
  transform: none !important;
}
<div id='rotated' class='waitload'>
  rotate after load
</div>
<div id='translated' class='waitload'>
  trasnlate after load
</div>
<script type="text/javascript">
  document.addEventListener('DOMContentLoaded', init);

  function init() {
    [...document.querySelectorAll('.waitload')]
    .map(e => e.classList.remove('waitload'));
  }
</script>


2

将以下代码添加到您的CSS中以实现淡入动画效果

body{animation: 2s ease-out 0s 1 FadeIn;}
@keyframes FadeIn {
    0% {
      opacity:0;
    }
    100% {
      opacity:1;
    }
}

如果您希望加载速度变慢,可以增加缓慢结束时间。


1

将其以body的hover开始,它将在鼠标第一次移动屏幕时启动,这通常是到达后不到一秒钟的时间,问题在于当鼠标移出屏幕时,它会反向。

html:hover #animateelementid, body:hover #animateelementid {rotate ....}

这是我能想到的最好的东西:http://jsfiddle.net/faVLX/

全屏显示:http://jsfiddle.net/faVLX/embedded/result/

编辑请看下面的评论:
由于没有悬停功能,因此此功能在任何触摸屏设备上都无法使用,因此用户除非点击它,否则将看不到内容。- Rich Bradshaw


是的,我自己想出了这个方法。如果没有其他办法,这是一个可以接受的解决方案。为此点赞。 - Jens Törnell
14
这个想法很糟糕 - 在任何触摸屏设备上都没有悬停功能,因此用户除非点击内容否则看不到它。 - Rich Bradshaw

1
与 @Rolf 的解决方案类似,但跳过引用外部函数或使用 class。如果不希望透明度在加载后改变,请使用内联脚本直接通过 style 更改透明度。例如:
<body class="fadein" onload="this.style.opacity=1">

@Rolf定义了CSS样式"fadein",定义了过渡并将透明度设置为初始状态(即0)。

唯一的问题是,这对SPAN或DIV元素不起作用,因为它们没有可用的onload事件。


0
你可以使用自定义的 CSS 类来替换 CSS 标签。 不需要外部包。
import React, { useState, useEffect } from 'react';
import { css } from '@emotion/css'

const Hello = (props) => {
    const [loaded, setLoaded] = useState(false);

    useEffect(() => {
        // For load
        setTimeout(function () {
            setLoaded(true);
        }, 50); // Browser needs some time to change to unload state/style

        // For unload
        return () => {
            setLoaded(false);
        };
    }, [props.someTrigger]); // Set your trigger

    return (
        <div
            css={[
                css`
                    opacity: 0;
                    transition: opacity 0s;
                `,
                loaded &&
                    css`
                        transition: opacity 2s;
                        opacity: 1;
                    `,
            ]}
        >
            hello
        </div>
    );
};

1
我认为安装React来触发页面加载动画有点过度杀伐。 - Marten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接