CSS過渡時間
CSS過渡時間
基礎知識
在瞭解CSS過渡時間之前,你應該先了解一下CSS的變形動畫,可以參考之前的一篇部落格。
我們的元素在屬性發生變化時,如果沒有特地的為它設定過渡時間,整個變化過程其實是以毫秒級別進行的,過程非常快,肉眼不易察覺。
故我們要學習CSS過渡時間,來讓它的變化過程更加平滑。
動畫屬性
不是所有css屬性都有過渡效果,檢視支援動畫的CSS屬性 ,一般來講有中間值的屬性都可以設定動畫如寬度、透明度等。
可以看一下下面這個例子,比如邊框就不支援過渡效果,而其他的諸如背景顏色,高度寬度等等都是支援過渡效果的。
可以看到,在滑鼠放上去的瞬間,邊框的樣式就發生變化了,而不是再跟隨過渡時間進行漸變。
而其他的屬性,諸如背景顏色,圓角等都是跟隨過渡時間進行漸變的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;padding: 0;
}
body{
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
div{
height: 50px;
width: 50px;
background: #747d8c;
border: 10px solid #ff6348;
/* 新增過渡時間 1s */
transition: 1s;
}
body:hover div{
background: #5352ed;
border: 10px dotted #ffa502;
width: 100px;
height: 100px;
border-radius: 50%;
transform: translate(100px,100px);
}
</style>
</head>
<body>
<div></div>
</body>
</html>
程式碼示例
元素狀態
初始形態
指當頁面載入後的樣式狀態,下面是表單設定的初始樣式。
變化形態
指元素由初始狀態變化後的狀態,比如滑鼠放上、表單獲得焦點後的形態。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
} body {
background: #2c3e50;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100vw;
height: 100vh;
• padding: 20px;
} input {
border: solid 5px #e67e22;
height: 60px;
width: 400px;
margin-bottom: 20px;
transition: 2s;
} input:hover {
border: solid 5px #000 !important;
} input:focus {
background: #e67e22;
} input:checked {
position: relative;
width: 60px;
height: 60;
border: none;
} input:checked::before {
content: '⩗';
color: white;
display: flex;
justify-content: center;
align-items: center;
font-size: 3em;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
box-sizing: border-box;
background: #3498db;
}
</style>
</head>
<body> <input type="text">
<input type="checkbox" checked> </body>
</html>
程式碼示例
transition-property
用於設定哪些屬性應用過渡效果。
預設值為
all
即所有屬性都發生過渡效果多個屬性使用逗號分隔
當我們使用該選項時,注意要和transition-duration
搭配使用才能生效,這個才是非簡寫的過渡時間。
transition
只是一種簡寫形式,如果使用transition-duration
與transition
進行搭配使用,則不會生效transition-duration
。
屬性設定
注意看,下面的這張圖片裡transition-duration
只設定了圓角與透明度,其他的諸如寬度高度背景顏色等均未設定,所以在滑鼠放上去的一瞬間未設定的屬性立刻產生了變化,而圓角和透明度是隨著過渡時間漸漸變化的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
main{
width: 400px;
height: 400px;
display: flex;
justify-content: center;
align-items: center;
}
div{
width: 100px;
height: 100px;
background: #f39c12;
transition-property:border-radius,opacity;
/* 這個才是真正的設定過渡時間,
transition只是簡寫形式 */
transition-duration: 1s;
opacity: .5; }
main:hover div{
border-radius: 50%;
width: 150px;
height: 150px;
background: #2ecc71;
opacity: 1;
}
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
禁用屬性
當設定transition-property:none;
後,所有的變化形態均不會跟隨過渡時間發生變化。
也就是說全部都是瞬發完成。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
main{
width: 400px;
height: 400px;
display: flex;
justify-content: center;
align-items: center;
}
div{
width: 100px;
height: 100px;
background: #f39c12;
transition-property:none;
/* 這個才是真正的設定過渡時間,
transition只是簡寫形式 */
transition-duration: 1s;
opacity: .5; }
main:hover div{
border-radius: 50%;
width: 150px;
height: 150px;
background: #2ecc71;
opacity: 1;
}
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
transitionend
用於控制過渡結束後執行的JS事件,簡寫屬性會觸發多次如 border-radius
會觸發四次事件,不難理解因為可以為border-bottom-left-radius
等四個屬性獨立設定過渡,所以就會有四次事件。
屬性 | 說明 |
---|---|
propertyName | 結束過渡樣式 |
elapsedTime | 過渡需要的時間 |
pseudoElement | 過渡的偽元素 |
isTrusted | true:使用者觸發,false:指令碼觸發 |
我們只需要有JS來監聽該事件即可,如下圖。
當我們檢測的<div>
標籤過渡時間結束後觸發了transitionend
事件,然後才顯示出了恭候多時的字樣。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh; }
main {
width: 400px;
height: 400px;
display: flex;
justify-content: center;
align-items: center;
}
div {
width: 100px;
height: 100px;
background: #f39c12;
transition-duration: 1s;
position: relative;
}
div:after {
content: "恭候多時";
color: #fff;
width: 100%;
font-size: 1.4em;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: -50px;
transform: scale(0);
transition-duration: 1s;
}
main:hover div {
transform: rotate(360deg);
}
main:hover div.show-after::after {
transform: scale(1) skew(360deg);
}
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
<script>
// 檢測div的 transitionend 事件
document.querySelector('div').addEventListener('transitionend', function (e) {
console.log(e);
// 給div新增class為show-after
document.querySelector('div').className = 'show-after';
})
</script>
</html>
程式碼示例
此時檢視一下瀏覽器控制檯,正好對應上表中的屬性。
transition-duration
用於設定過渡時間,需要注意以下幾點
可使用單位為 ms毫秒、s秒
預設值為0s不產生過渡效果
一個值時,所有屬性使用同樣的時間
二個值時,奇數屬性使用第一個,偶數屬性使用第二個
變化屬性數量大於時間數量時,後面的屬性再從第一個時間開始重複使用
統一時間
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
} body {
background: #2c3e50;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100vw;
height: 100vh;
padding: 80px;
} main {
width: 400px;
height: 400px;
} div {
width: 150px;
height: 150px; border-radius: 50%;
opacity: 0.2;
transition-property: background-color, transform, opacity, border-radius;
transition-duration: 3s;
} div:hover {
opacity: 1;
border-radius: 0;
transform: scale(2) rotate(180deg); }
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
兩個時間
下面共有四個屬性並設定了兩個時間值,1,3屬性使用第一個值,2,4屬性使用第二個值。
...
div {
width: 150px;
height: 150px; border-radius: 50%;
opacity: 0.2;
transition-property: background-color, transform, opacity, border-radius;
transition-duration: 200ms, 5s;
}
...
多個時間
下面共有四個屬性並設定了三個時間值,1,2,3屬性使用1,2,3時間值,第四個屬性再從新使用第一個時間值。
...
div {
width: 150px;
height: 150px; border-radius: 50%;
opacity: 0.2;
transition-property: background-color, transform, opacity, border-radius;
transition-duration: 200ms, 5s, 2s;
}
...
不同時間
可以為初始與變化狀態設定不同的時間。
下面是將hover
設定為3s,當滑鼠放上時變化時間為3s。為初始設定為1s即表示變化到初始狀態需要1s。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
} body {
background: #2c3e50;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100vw;
height: 100vh;
padding: 80px;
} main {
width: 400px;
height: 400px;
} div {
width: 150px;
height: 150px;
background-color: #e67e22;
border-radius: 50%;
transition-property: background-color, transform, opacity, border-radius;
/* 結束時間,變回初始狀態 如果只有該時間,則過渡時間也採用它 */
transition-duration: 1s;
} div:hover {
border-radius: 0;
transform: scale(2) rotate(180deg);
background-color: #e67e22;
/* 過渡時間 */
transition-duration: 3s;
}
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
transition-timing-function
用於設定整體過渡效果的速度,可在 https://cubic-bezier.com 網站線上體驗效果差異。
預設引數
值 | 描述 |
---|---|
linear | 規定以相同速度開始至結束的過渡效果(等於 cubic-bezier(0,0,1,1))。預設值 |
ease | 開始慢,然後快,慢下來,結束時非常慢(cubic-bezier(0.25,0.1,0.25,1)) |
ease-in | 開始慢,結束快(等於 cubic-bezier(0.42,0,1,1)) |
ease-out | 開始快,結束慢(等於 cubic-bezier(0,0,0.58,1)) |
ease-in-out | 中間快,兩邊慢(等於 cubic-bezier(0.42,0,0.58,1)) |
cubic-bezier(n,n,n,n) | 在 cubic-bezier 函式中定義自己的值 |
差異對比
我們用linear
和ease
來做一個對比,左邊是linear
,右邊是ease
。
其實他們的過渡時間都是一模一樣的,只是視覺上有所差異。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 100vh;
width: 100vw; display: flex;
justify-content: center;
align-items: center;
} main{
height: 400px;
width: 400px; display: flex;
justify-content: center;
align-items: center; border:1px solid #ddd;
}
main div{
height: 100px;
width: 100px;
margin: 20px;
transition-duration: 3s;
}
main div:nth-child(1){
background-color: #ff4757;
transition-timing-function:linear;
} main div:nth-child(2){
background-color: #3742fa;
transition-timing-function:ease;
} main:hover div{
width: 150px;
height: 150px;
border-radius: 50%;
} </style> </head>
<body>
<main>
<div></div>
<div></div>
</main>
</body>
</html>
程式碼示例
貝塞爾曲線
其實不管是linear
或者是ease
都是由貝塞爾曲線來完成的。
我們需要設定四個值 cubic-bezier(<x1>, <y1>, <x2>, <y2>)
來控制曲線速度,可在 https://cubic-bezier.com 網站線上體驗效果。
如以下是我自己調的一個數值,右邊的那個,對比的是linear
這個預設的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 100vh;
width: 100vw; display: flex;
justify-content: center;
align-items: center;
} main{
height: 400px;
width: 400px; display: flex;
justify-content: center;
align-items: center; border:1px solid #ddd;
}
main div{
height: 100px;
width: 100px;
margin: 20px;
transition-duration: 3s;
}
main div:nth-child(1){
background-color: #ff4757;
transition-timing-function:linear;
} main div:nth-child(2){
background-color: #3742fa;
transition-timing-function:cubic-bezier(.17,.67,.88,-0.47);
} main:hover div{
width: 150px;
height: 150px;
border-radius: 50%;
} </style> </head>
<body>
<main>
<div></div>
<div></div>
</main>
</body>
</html>
程式碼示例
步進速度
過渡使用階梯化呈現,有點像現實生活中的機械舞,下面是把過渡分3步完成。
選項 | 說明 |
---|---|
steps(n,start) | 設定n個時間點,第一時間點變化狀態 |
steps(n,end) | 設定n個時間點,第一時間點初始狀態 |
step-start | 等於steps(1,start),可以理解為從下一步開始 |
step-end | 等於steps(1,end),可以理解為從當前步開始 |
start
總是先走,end
總是後走。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 100vh;
width: 100vw; display: flex;
justify-content: center;
align-items: center;
} main{
height: 400px;
width: 800px; display: flex;
border:1px solid #ddd; position: relative;
}
main div{
width: 200px;
height: 100%;
border: 1px solid #ddd;
}
main::after{
content: "START";
height: 30%;
width: 25%;
background: #ff4757;
color: #fff;
font-size: 2em;
/* 過渡時間2s */
transition: 2s;
/* 相當於把2s分成三步走 */
transition-timing-function: steps(3, start); position: absolute;
top: 0; display: flex;
justify-content: center;
align-items: center; } main::before{
content: "END";
height: 30%;
width: 25%;
background: #70a1ff;
color: #fff;
font-size: 2em;
/* 過渡時間2s */
transition: 2s;
/* 相當於把2s分成三步走 */
transition-timing-function: steps(3, end); position: absolute;
bottom: 0; display: flex;
justify-content: center;
align-items: center;
} main:hover::before{
transform: translateX(600px);
} main:hover::after{
transform: translateX(600px);
} </style> </head>
<body>
<main>
<div></div>
<div></div>
<div></div>
<div></div>
</main>
</body>
</html>
程式碼示例
時鐘效果
其實步進這樣一幀一幀的來走非常時候做時鐘,那麼這裡就做一個非常簡chou陋的時鐘吧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 100vh;
width: 100vw; display: flex;
justify-content: center;
align-items: center;
} main{
height: 400px;
width: 400px;
display: flex;
position: relative;
background:#ffa502;
box-shadow: 3px 3px 3px #2f3542;
border-radius: 50%;
}
main::after{
content: "";
height: 20px;
width: 20px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform:translate(-50%,-50%);
background: #1e90ff;
}
main::before{
content: "";
height: 48%;
width: 6px;
position: absolute;
left: 50%;
bottom: 50%;
transform:translate(-50%,0);
background: #1e90ff;
transition-duration: 60s;
transition-timing-function:steps(60,start);
transform-origin: bottom;
} main:hover::before{ transform:translateX(-50%) rotate(360deg); } </style> </head>
<body>
<main></main>
</body>
</html>
程式碼示例
transition-delay
用於設定延遲過渡的時間。
預設為0s即立刻開始過渡
值可以為負數
變化屬性數量大於時間數量時,後面的屬性再從第一個時間開始重複使用
基本使用
下面設定了延遲時間為1s,當滑鼠放上時產生變化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
} body {
background: #2c3e50;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100vw;
height: 100vh;
padding: 80px;
} main {
width: 400px;
height: 400px;
} div {
width: 150px;
height: 150px;
background-color: #e67e22;
border-radius: 50%;
transition-property: background-color, transform, opacity, border-radius;
transition-duration: 1s;
transition-delay: 1s;
} div:hover {
border-radius: 0;
transform: scale(2) rotate(180deg);
background-color: #e67e22;
}
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
多值延遲
可以設定不同屬性的延遲時間。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
} body {
background: #2c3e50;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100vw;
height: 100vh;
padding: 80px;
} main {
width: 400px;
height: 400px;
} div {
width: 150px;
height: 150px;
background-color: #fff;
/* 一一對應 */
transition-property: background-color, transform, border-radius;
transition-duration: 1s, 2s, 3s;
transition-delay: 1s, 3s, 5s;
} div:hover {
border-radius: 50%;
transform: scale(2) rotate(180deg);
background-color: #e67e22;
}
</style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
使用負值
下例圓角屬性的過渡時間為4s,設定延遲為 -4s,表示滑鼠放上時直接顯示在4s上的效果。如果設定為-2s顯示圓角變形一半的效果。
即對圓角來說不產生過渡,是瞬發的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
} body {
background: #2c3e50;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100vw;
height: 100vh;
padding: 80px;
} main {
width: 400px;
height: 400px;
} div {
width: 150px;
height: 150px;
background-color: #fff; transition-property: background-color, transform, border-radius;
transition-duration: 1s, 2s, 4s;
transition-delay: 1s, 2s, -4s;
} div:hover {
border-radius: 50%;
transform: scale(2) rotate(180deg);
background-color: #e67e22;
} </style>
</head>
<body>
<main>
<div></div>
</main>
</body>
</html>
程式碼示例
transition
可以使用transition
指令將過渡規則統一設定,需要注意以下幾點。
必須設定過渡時間
延遲時間放在逗號或結束前
如果只設定一個數值,那麼該數值會認為是過渡時間
transition: border-radius linear 2s 0s,
background 2s 2s,
width linear 2s 4s,
height linear 2s 4s;
/* 參與過渡的動畫 貝塞爾曲線 過渡時間 延遲時間 */
點贊案例
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src='https://blog-static.cnblogs.com/files/Yunya-Cnblogs/jQuery.js'></script>
<style>
body {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #ecf0f1;
} div {
position: relative;
width: 100px;
height: 100px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
} div i.fa {
font-size: 100px;
position: absolute;
transition: all .5s;
color: #ddd;
} div.heart i.fa {
font-size: 400px;
color: #e74c3c;
opacity: 0;
} div.heart i.fa:nth-child(2) {
font-size: 80px;
color: #e74c3c;
opacity: 1;
}
</style>
</head> <body> <div onclick="heart()">
<i class="fa fa-heart" aria-hidden="true"></i>
<i class="fa fa-heart" aria-hidden="true"></i>
</div> </body>
<script>
function heart() {
$("div").toggleClass('heart');
}
</script> </html>
程式碼示例