使用 CSS 过渡
**CSS 过渡**提供了一种在更改 CSS 属性时控制动画速度的方法。您可以使属性更改在一段时间内发生,而不是立即生效。例如,如果您将元素的颜色从白色更改为黑色,通常更改是即时的。启用 CSS 过渡后,更改会以遵循加速度曲线的时段发生,所有这些都可以自定义。
涉及在两种状态之间过渡的动画通常称为隐式过渡,因为起始状态和最终状态之间的状态由浏览器隐式定义。
CSS 过渡允许您决定要动画化的属性(通过显式列出它们),动画何时开始(通过设置延迟),动画持续多长时间(通过设置持续时间),以及动画如何运行(通过定义缓动函数,例如,线性或开始时快,结束时慢)。
哪些 CSS 属性可以进行过渡?
网页作者可以定义必须动画化的属性以及动画方式。这允许创建复杂的过渡。但是,某些属性不可动画化,因为动画化它们没有意义。
**注意:**auto
值通常是一个非常复杂的情况。规范建议不要从 auto
到 auto
进行动画。一些用户代理,例如基于 Gecko 的用户代理,实现了此要求,而其他用户代理,例如基于 WebKit 的用户代理,则不太严格。使用带有 auto
的动画可能会导致不可预测的结果,具体取决于浏览器及其版本,应避免。
定义过渡
CSS 过渡使用简写transition
属性进行控制。这是配置过渡的最佳方法,因为它可以更容易地避免参数不同步,而不同步的参数可能会让人非常沮丧,导致在 CSS 中花费大量时间调试。
您可以使用以下子属性控制过渡的各个组成部分
transition-property
-
指定应将过渡应用到的 CSS 属性的名称或名称列表。只有此处列出的属性在过渡期间会进行动画;对所有其他属性的更改通常会像往常一样立即发生。
transition-duration
-
指定过渡持续时间。您可以指定一个适用于所有属性的持续时间,也可以指定多个值,以便每个属性以不同的时间段进行过渡。
transition-timing-function
-
指定一个函数来定义如何计算属性的中间值。缓动函数确定如何计算过渡的中间值。大多数缓动函数可以通过提供相应函数的图形来指定,该图形由定义三次贝塞尔曲线的四个点定义。您也可以从缓动函数速查表中选择缓动。
transition-delay
-
定义在属性更改与过渡实际开始之间等待的时间。
transition
简写 CSS 语法如下所示
div {
transition: <property> <duration> <timing-function> <delay>;
}
示例
基本示例
此示例执行一个持续 4 秒的字体大小过渡,在用户将鼠标悬停在元素上与动画效果开始之间存在 2 秒的延迟。
#delay {
font-size: 14px;
transition-property: font-size;
transition-duration: 4s;
transition-delay: 2s;
}
#delay:hover {
font-size: 36px;
}
多个动画属性示例
CSS
.box {
border-style: solid;
border-width: 1px;
display: block;
width: 100px;
height: 100px;
background-color: #0000ff;
transition:
width 2s,
height 2s,
background-color 2s,
rotate 2s;
}
.box:hover {
background-color: #ffcccc;
width: 200px;
height: 200px;
rotate: 180deg;
}
当属性值列表长度不同时
如果任何属性的值列表短于其他属性,则会重复其值以使其匹配。例如
div {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s;
}
这被视为
div {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s, 3s, 5s;
}
类似地,如果任何属性的值列表长于transition-property
的值列表,则会将其截断,因此如果您有以下 CSS
div {
transition-property: opacity, left;
transition-duration: 3s, 5s, 2s, 1s;
}
这将被解释为
div {
transition-property: opacity, left;
transition-duration: 3s, 5s;
}
在突出显示菜单时使用过渡
CSS 的常见用法是在用户将鼠标光标悬停在菜单项上时突出显示它们。使用过渡使效果更具吸引力非常容易。
首先,我们使用 HTML 设置菜单
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact Us</a>
<a href="#">Links</a>
</nav>
然后我们构建 CSS 来实现菜单的外观和感觉
nav {
display: flex;
gap: 0.5rem;
}
a {
flex: 1;
background-color: #333;
color: #fff;
border: 1px solid;
padding: 0.5rem;
text-align: center;
text-decoration: none;
transition: all 0.5s ease-out;
}
a:hover,
a:focus {
background-color: #fff;
color: #333;
}
此 CSS 确定了菜单的外观,当元素处于其:hover
和:focus
状态时,背景和文本颜色都会发生变化。
过渡显示和内容可见性
此示例演示了如何对display
和content-visibility
进行过渡。此行为对于创建入口/退出动画很有用,例如,您希望使用display: none
从 DOM 中删除容器,但希望它使用opacity
淡出,而不是立即消失。
支持的浏览器使用离散动画类型的变体来过渡display
和content-visibility
。这通常意味着属性将在动画在两者之间动画的 50% 时在两个值之间切换。
但是,有一个例外,即在对display: none
或content-visibility: hidden
进行动画处理时。在这种情况下,浏览器将在两个值之间切换,以便在整个动画持续时间内显示过渡内容。
例如
- 当对
display
从none
动画到block
(或其他可见的display
值)时,该值将在动画持续时间的0%
处切换到block
,以便在整个过程中可见。 - 当对
display
从block
(或其他可见的display
值)动画到none
时,该值将在动画持续时间的100%
处切换到none
,以便在整个过程中可见。
在过渡这些属性时,需要在过渡上设置transition-behavior: allow-discrete
。这有效地启用了display
/content-visibility
过渡。
在过渡display
时,需要@starting-style
来为在元素上设置的属性提供一组起始值,当元素收到其第一个样式更新时,您希望从该值过渡。这是为了避免意外行为。默认情况下,CSS 过渡不会在元素的第一个样式更新时触发(当它们首次出现在 DOM 中时),包括当display
从none
更改为其他状态时。content-visibility
动画不需要在@starting-style
块中指定起始值。这是因为content-visibility
不会像display
那样将元素隐藏在 DOM 中:它只是跳过渲染元素的内容。
HTML
HTML 包含两个<p>
元素,它们之间有一个<div>
,我们将对其进行动画处理,使其从display
none
变为block
。
<p>
Click anywhere on the screen or press any key to toggle the
<code><div></code> between hidden and showing.
</p>
<div>
This is a <code><div></code> element that transitions between
<code>display: none; opacity: 0</code> and
<code>display: block; opacity: 1</code>. Neat, huh?
</div>
<p>
This is another paragraph to show that <code>display: none;</code> is being
applied and removed on the above <code><div> </code>. If only its
<code>opacity</code> was being changed, it would always take up the space in
the DOM.
</p>
CSS
html {
height: 100vh;
}
div {
font-size: 1.6rem;
padding: 20px;
border: 3px solid red;
border-radius: 20px;
width: 480px;
display: none;
opacity: 0;
transition:
opacity 1s,
display 1s allow-discrete;
/* Equivalent to
transition: all 1s allow-discrete; */
}
.showing {
opacity: 1;
display: block;
}
@starting-style {
.showing {
opacity: 0;
}
}
请注意用于指定过渡起始样式的@starting-style
块,以及过渡列表中包含的display
属性,以及在其上设置的allow-discrete
。
JavaScript
最后,我们包含一些 JavaScript 代码来设置事件侦听器以触发过渡(通过showing
类)。
const divElem = document.querySelector("div");
const htmlElem = document.querySelector(":root");
htmlElem.addEventListener("click", showHide);
document.addEventListener("keydown", showHide);
function showHide() {
divElem.classList.toggle("showing");
}
结果
代码呈现如下
JavaScript 示例
注意:在以下情况立即使用过渡时应小心
- 使用
.appendChild()
将元素添加到 DOM 中 - 删除元素的
display: none;
属性。
这被视为初始状态从未发生过,并且元素始终处于其最终状态。克服此限制的简便方法是在更改要过渡到的 CSS 属性之前应用几毫秒的setTimeout()
。
使用过渡使 JavaScript 功能平滑
过渡是一个很棒的工具,可以使事物看起来更平滑,而无需对 JavaScript 功能进行任何操作。以以下示例为例。
<p>Click anywhere to move the ball</p>
<div id="foo" class="ball"></div>
使用 JavaScript,您可以使将球移动到特定位置的效果发生
const f = document.getElementById("foo");
document.addEventListener(
"click",
(ev) => {
f.style.transform = `translateY(${ev.clientY - 25}px)`;
f.style.transform += `translateX(${ev.clientX - 25}px)`;
},
false,
);
使用 CSS,您可以使其在没有任何额外努力的情况下变得平滑。向元素添加过渡,任何更改都将平滑发生。
.ball {
border-radius: 25px;
width: 50px;
height: 50px;
background: #c00;
position: absolute;
top: 0;
left: 0;
transition: transform 1s;
}
检测过渡的开始和完成
您可以使用transitionend
事件来检测动画是否已完成运行。这是一个TransitionEvent
对象,除了典型的Event
对象之外,它还有两个附加属性。
propertyName
-
一个字符串,指示已完成过渡的 CSS 属性的名称。
elapsedTime
-
一个浮点数,指示事件触发时过渡已运行的秒数。此值不受
transition-delay
的值影响。
像往常一样,您可以使用addEventListener()
方法来监视此事件。
el.addEventListener("transitionend", updateTransition, true);
您可以使用transitionrun
(在任何延迟之前触发)和transitionstart
(在任何延迟之后触发)以相同的方式检测过渡的开始。
el.addEventListener("transitionrun", signalStart, true);
el.addEventListener("transitionstart", signalStart, true);
注意:如果过渡在完成之前被中止,则transitionend
事件不会触发,因为元素被设置为display: none
或动画属性的值已更改。
规范
规范 |
---|
CSS 过渡 |