前言

在做前端開發時,常常會覺得「想做出讓人忍不住想點的按鈕」「想讓使用者能直覺操作」。
這時候就能派上用場的,就是 CSS 動畫。

透過組合 transitiontransform 等 CSS 屬性,可以替 UI 加上各種動態效果。

我把至今使用過的 CSS 動畫,順便也當作整理自己的知識,統整在這篇文章裡。

目錄

本文的適合對象

  • 想學習 HTML/CSS 基礎並應用到實務的人
  • 想學習 transitiontransform 屬性用法的人
  • 想透過 CSS 動畫做出更豐富 UI 表現的人

前提條件・環境

  • 前提知識: 已理解 HTML/CSS 的基本寫法,以及 :hover 的基本概念
  • 使用技術: HTML / CSS

1. CSS 動畫中常用的屬性

這次介紹的 CSS 動畫主要會使用 transitiontransform
先來說明各自的基本效果。

1-1. transition

transition 是用來讓 CSS 變化更平滑的屬性。
當 CSS 值改變時,可以讓它在指定時間內逐漸變化。

例如在按鈕 hover 時改變文字顏色或背景色,只要加上 transition,顏色就會慢慢過渡,看起來更柔和自然。

我們來比較一下有無 transition 時,按鈕顏色變化的速度。

▼有無 transition 的比較

See the Pen transitionの比較 (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<!-- transition あり -->
<div class="item">
  <span>有(平滑變化)</span>
    <div class="btn1">按鈕</div>
</div>

<!-- transition なし -->
<div class="item">
  <span>無(瞬間變化)</span>
  <div class="btn2">按鈕</div>
</div>

CSS

/* -- 有 transition -- */
.btn1 {
  max-width: 120px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 32px;
  font-size: 16px;
  font-weight: bold;
  text-decoration: none;
  border-radius: 6px;
  cursor: pointer;
  color: #ffffff;
  background-color: #D20B08;
  border: 2px solid #D20B08;
  transition: all 0.4s ease; /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.btn1:hover {
  color: #D20B08;
  background-color: #ffffff;
}

/* -- 無 transition -- */
.btn2 {
  max-width: 120px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 32px;
  font-size: 16px;
  font-weight: bold;
  text-decoration: none;
  border-radius: 6px;
  cursor: pointer;
  color: #ffffff;
  background-color: #D20B08;
  border: 2px solid #D20B08;
}

/* hover 時 */
.btn2:hover {
  color: #D20B08;
  background-color: #ffffff;
}

・說明
transition 的按鈕加上了 transition: all 0.4s ease;
這表示讓 CSS 在 0.4 秒內變化。

指定值意義all 將所有會變化的屬性都納入 0.4s 以 0.4 秒進行變化ease 讓變化的開始與結束較為柔和本例中,hover 時 colorbackground-color 會一起變化,因此使用 all 讓所有變化中的屬性都套用過渡效果。
另外,ease 是指定變化方式的值,會讓開始與結束較緩和。
還有很多其他指定值,這裡為了易懂起見使用 allease

.btn1 {
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.btn1:hover {
    color: #D20B08;
    background-color: #ffffff;
}

透過設定 transition,CSS 的變化就能變成平滑的動畫。

1-2. transform

transform用來移動、放大、縮小、旋轉元素的屬性。
可以讓元素從目前位置移動,也能改變大小與角度。

這裡介紹使用 transform 的以下範例:

  • 讓按鈕稍微往上浮起
  • 讓按鈕的箭頭往右移動
  • 讓按鈕放大一圈

transform 使用範例

See the Pen transformの例 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<!-- translateY -->
<div class="item">
    <span>稍微往上浮起(translateY)</span>
    <a class="btn __y">按鈕1</a>
</div>

<!-- translateX -->
<div class="item">
    <span>讓箭頭往右移動(translateX)</span>
    <a class="btn __x">按鈕2<span class="arrow">→</span></a>
</div>

<!-- scale -->
<div class="item">
    <span>放大一圈(scale)</span>
    <a class="btn __scale">按鈕3</a>
</div>

CSS

/* -- 按鈕共用樣式 -- */
.btn {
    max-width: 120px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 32px;
    font-size: 16px;
    font-weight: bold;
    text-decoration: none;
    border-radius: 6px;
    cursor: pointer;
    color: #ffffff;
    background-color: #D20B08;
    border: 2px solid #D20B08;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* -- translateY -- */
/* hover 時 */
.btn.__y:hover {
    transform: translateY(-6px); /* 沿 Y 軸移動 -6px */
}

/* -- translateX -- */
/* 箭頭 */
.btn.__x .arrow {
    padding-left: 16px;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.btn.__x:hover .arrow {
    transform: translateX(6px); /* 沿 X 軸移動 6px */
}

/* -- scale -- */
/* hover 時 */
.btn.__scale:hover {
    transform: scale(1.1); /* 放大為原本的 1.1 倍 */
}

・說明
transform 可以使用 translate()scale() 等,來改變元素的位置與大小。

①移動元素:translate()

translate() 會把元素從目前位置移動指定的距離。
X 軸方向使用 translateX(),Y 軸方向使用 translateY()
如果要同時指定 X 軸與 Y 軸,就使用 translate()

指定值動作translateX(6px) 沿 X 軸移動 6px,向右translateX(-6px) 沿 X 軸移動 -6px,向左translateY(-6px) 沿 Y 軸移動 -6px,向上translateY(6px) 沿 Y 軸移動 6px,向下translate(6px, -6px) 沿 X 軸移動 6px、沿 Y 軸移動 -6px,向右上方▼按鈕1:往上移動

.btn {
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn.__y:hover {
    transform: translateY(-6px); /* 沿 Y 軸移動 -6px */
}

translateY() 是沿 Y 軸(垂直)方向移動。
因為指定的是 -6px,所以會從原本位置往上移動 6px

▼按鈕2:往右移動

/* 箭頭 */
.btn.__x .arrow {
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn.__x:hover .arrow {
    transform: translateX(6px); /* 沿 X 軸移動 6px */
}

translateX() 是沿 X 軸(水平)方向移動。
因為對箭頭指定了 6px,所以會從原本位置往右移動 6px

②放大・縮小元素:scale()

scale() 是以元素原本的大小為基準來放大或縮小。
原本大小視為 1,指定大於 1 的值就是放大,小於 1 的值就是縮小。

▼按鈕3:放大 1.1 倍

.btn.__scale:hover {
    transform: scale(1.1); /* 放大為原本的 1.1 倍 */
}

因為指定了 scale(1.1),所以會從原本大小放大 1.1 倍
若要縮小,可改成 scale(0.9),就能縮小到原本的90%

2. 豐富的動畫範例集

接下來會將 transitiontransform 結合,介紹更豐富的 UI 動畫點子。
這次會以容易活用的按鈕與卡片介面為主來介紹。

2-1. 按鈕動畫

①底線由左向右延伸

滑過時,按鈕底線會從左往右延伸的動畫。
同時也讓箭頭稍微往右移動,讓畫面在簡單中帶有動感。

【使用的 CSS】
transition: all 0.4s ease; 讓底線與箭頭的變化更平滑
transform: translateX(6px); 讓箭頭往右移動

See the Pen btn02 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<div class="item">
    <span>線由左往右延伸</span>
    <a class="btn">
        <span class="btn_text">view more</span>
    </a>
</div>

CSS

.btn {
    position: relative;
    max-width: 120px;
    display: flex;  
    padding: 12px 20px;
    font-size: 16px;
    font-weight: bold;
    text-decoration: none;
    cursor: pointer;
    color: #D20B08;
    text-decoration: none;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn::after {
    content: '';
    position: absolute;
    width: 0;
    height: 2px;
    bottom: 0;
    left: 0;
    background-color: #D20B08;
    transition: all 0.4s ease; /* 0.4 秒內平滑變化 */
}

.btn_text::after {
  content: '→';
  display: inline-block;
    margin-left: 12px;
  transition: transform 0.4s ease; /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.btn:hover::after {
    width: 100%;
}

.btn:hover .btn_text::after {
    transform:translateX(6px); /* 向右移動 6px */
}

②圓形按鈕放大

滑過時,圓形按鈕會放大,同時箭頭也會往右移動的動畫。
透過結合 scale()translateX(),讓按鈕整體擴張的同時,箭頭也跟著移動。

【使用的 CSS】
transition: all 0.4s ease; 讓變化更平滑
transform: translateX(6px); 讓箭頭往右移動
transform: scale(1.1) 讓按鈕放大

See the Pen btn02 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<div class="item">
    <span>圓形按鈕放大</span>
    <a class="btn">
        <span class="btn_text">view more</span>
        <span class="arrow">→</span>
    </a>
</div>

CSS

.btn {
    position: relative;
    max-width: 120px;
    aspect-ratio: 1/1;
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    font-weight: bold;
    box-shadow: 0 2px 10px rgb(153, 153, 153);
    text-decoration: none;
    background-color: #D20B08;
    color: #ffffff;
    text-decoration: none;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn .arrow{
    font-size: 24px;
    font-weight: normal;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.btn:hover {
    opacity: 0.6;
    transform: scale(1.1);
}

.btn:hover .arrow {
    transform:translateX(6px); /* 向右移動 6px */
}

③背景色由左向右變化

滑過時,背景色會由左往右變化。
將背景色設為偽元素 ::before,再使用 transform: scaleX() 讓它在水平方向伸縮來呈現。

【使用的 CSS】
transition: all 0.4s ease; 讓變化更平滑
transform: scaleX(0); 將水平方向尺寸設為 0,隱藏背景色
transform: scaleX(1); 將水平方向尺寸恢復為原本寬度,顯示背景色
transform: translateX(6px); 讓箭頭往右移動
transform: rotate(45deg); 旋轉 45 度
(透過指定 rotate() 旋轉 45 度,來重現箭頭「>」)

See the Pen btn03 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<div class="item">
  <span>背景色由左向右變化</span>
    <a class="btn">
        <span class="btn_text">view more</span>
    </a>
</div>

CSS

.btn {
    position: relative;
    max-width: 120px;
    display: inline-flex;
    align-items: center;
    justify-content: space-around;
    padding: 12px 32px;
    font-size: 16px;
    font-weight: bold;
    text-decoration: none;
    border-radius: 6px;
    cursor: pointer;
    color: #D20B08;
    background-color: #ffffff;
    border: 2px solid #D20B08;
    overflow: hidden;
    text-decoration: none;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 110%;
    height: 110%;
    background-color: #D20B08;
    transform: scaleX(0); /* 將寬度縮小為 0 */
    transform-origin: left;
    transition: transform 0.4s ease;    /* 0.4 秒內平滑變化 */
    z-index: 0;
}

.btn_text {
    position: relative;
    z-index: 1;
}

.btn_text::after {
  content: '';
  display: inline-block;
    margin-left: 6px;
  width: 8px;
  height: 8px;
  border-top: 2px solid;
  border-right: 2px solid;
  transform: rotate(45deg);  /* 旋轉 45 度,做成「>」 */
  transition: transform 0.3s ease-out;
}

/* hover 時 */
.btn:hover {
    color: #ffffff;
}

.btn:hover::before {
    transform: scaleX(1);   /* 將寬度設為 1,完整顯示 */
}

.btn:hover .btn_text::after {
    transform:translateX(6px) rotate(45deg); /* 加上 translateX(6px) 讓箭頭往右移動 */
}

④背景漸層變化

滑過時,背景色的漸層會改變的動畫。
透過結合色彩變化與箭頭移動,可以讓按鈕更有質感。

【使用的 CSS】
transition: all 0.4s ease; 讓變化更平滑
transform: translateX(6px); 讓箭頭往右移動
background: linear-gradient(75deg, #D20B08 0%, #fdff71 35%, #fcff2e 60%, #D20B08 100%); 調整漸層色彩與角度
background-size: 300% 100%; 調整漸層尺寸
background-position: 100% 0; 調整漸層顯示位置
overflow: hidden; 隱藏溢出部分

See the Pen btn04 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<div class="item">      
    <span>漸層變化</span>
    <a class="btn">
        <span class="btn_text">view more</span>
        <span class="arrow">→</span>
    </a>
</div>

CSS

.btn {
    position: relative;
    max-width: 120px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 42px;
    /* 漸層色彩調整 */
    background: linear-gradient(75deg, #D20B08 0%, #fdff71 35%,  #fcff2e 60%, #D20B08 100%);
    background-size: 300% 100%;
    /* 漸層顯示位置調整 */
    background-position: 100% 0;
    border-radius: 50px;
    overflow: hidden;
    font-size: 16px;
    font-weight: bold;
    box-shadow: 0 2px 10px rgb(153, 153, 153);
    text-decoration: none;
    color: #ffffff;
    text-decoration: none;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn .btn_text{
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.btn .arrow{
    font-size: 24px;
    font-weight: normal;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.btn:hover {
    /* 調整漸層顯示位置 */
    background-position: 0% 0;
}

.btn:hover .btn_text{
    transform:translateX(6px); /* 向右移動 6px */
}

.btn:hover .arrow {
    transform:translateX(6px); /* 向右移動 6px */
}

2-2. 卡片動畫

①透過框線與陰影營造立體感

滑過時,卡片會出現框線與陰影的動畫。
透過結合 borderbox-shadow 的變化,可以讓卡片看起來像是浮出前景般,帶有立體感。

【使用的 CSS】
transition: all 0.4s ease; 讓變化更平滑
transform: translateX(6px); 讓箭頭往右移動

See the Pen card01 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<p>透過框線與陰影營造立體感</p>
<div class="card_container">
    <a class="card">
        <div>
            <h4 class="card_head">標題</h4>
            <p class="card_body">文字文字文字文字文字</p>
        </div>
        <div class="view-more">
            <span class="view-more__text">view more</span>
            <span class="view-more__arrow">→</span>
        </div>
    </a>

    <a class="card">
        <div>
            <h4 class="card_head">標題</h4>
            <p class="card_body">文字文字文字文字文字</p>
        </div>
        <div class="view-more">
            <span class="view-more__text">view more</span>
            <span class="view-more__arrow">→</span>
        </div>
    </a>

</div>

CSS

.card {
    background: #ffffff;
    padding: 24px;
    border-radius: 12px;
    text-decoration: none;
    display: flex;
    flex-direction: column;
    gap: 16px;
    border: 2px solid #e2e8f0;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.view-more{
    display: inline-block;
    color: #D20B08;
    font-weight: bold;
    text-align: right;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.card:hover {
    border-color: #D20B08;
    box-shadow: 0 2px 10px rgb(153, 153, 153);  /* hover 時加上陰影 */
}

.card:hover .view-more {
    transform: translateX(6px); /* 向右移動 6px */
}

/* 其他樣式 */
.card_container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    gap: 16px;
}

.card_head{
    font-size: 20px;
    margin-bottom: 6px;
}

.card_body{
    font-size: 12px;
    color: #adadad;
}

②底線由右向左延伸,卡片向上浮起

滑過時,底線會延伸,卡片也會往上移動的動畫。
透過上移能讓卡片有浮起的感覺,再搭配線條、陰影變化與文字移動,可以提升點擊意圖。

【使用的 CSS】
transition: all 0.4s ease; 讓變化更平滑
transform: translateY(-8px); 讓卡片往上移動
transform: translateX(6px); 讓箭頭往右移動

See the Pen card02 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<p>底線與向上浮起</p>
<div class="card_container">
    <a class="card">
        <div>
            <h4 class="card_head">標題</h4>
            <p class="card_body">文字文字文字</p>
        </div>
        <div class="view-more">
            <span class="view-more__text">view more</span>
            <span class="view-more__arrow">→</span>
        </div>
    </a>

    <a class="card">
        <div>
            <h4 class="card_head">標題</h4>
            <p class="card_body">文字文字文字</p>
        </div>
        <div class="view-more">
            <span class="view-more__text">view more</span>
            <span class="view-more__arrow">→</span>
        </div>
    </a>

    <a class="card">
        <div>
            <h4 class="card_head">標題</h4>
            <p class="card_body">文字文字文字</p>
        </div>
        <div class="view-more">
            <span class="view-more__text">view more</span>
            <span class="view-more__arrow">→</span>
        </div>
    </a>
</div>

CSS

.card {
    position: relative;
    overflow: hidden;
    background: #ffffff;
    padding: 24px;
    text-decoration: none;
    display: flex;
    flex-direction: column;
    gap: 16px;
    box-shadow: 0 1px 10px rgba(153, 153, 153, 0.5);
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.card::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: 0;
    height: 3px;
    background-color: #D20B08;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.view-more{
    display: inline-block;
    color: #D20B08;
    font-weight: bold;
    text-align: right;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.card:hover {
    box-shadow: 0 2px 10px rgb(153, 153, 153);  /* 讓陰影更明顯 */
    transform: translateY(-8px); /* 往上移動 8px */
}

.card:hover::after {
    width: 100%; /* 讓底線從 0 變成 100% */
}

.card:hover .view-more {
    transform: translateX(6px); /* 向右移動 6px */
}

/* 其他樣式 */
.card_container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    gap: 16px;
}

.card_head{
    font-size: 20px;
    margin-bottom: 6px;
}

.card_body{
    font-size: 12px;
    color: #adadad;
}

③圖片由單色變成彩色

滑過時,圖片會從單色變成彩色,同時圖片也會稍微放大。
使用 filter 改變圖片色調,再用 scale() 讓圖片在父層內放大。
這種表現很適合用在圖片圖庫或文章列表。

【使用的 CSS】
transition: all 0.4s ease; 讓變化更平滑
transform: scale(1.1); 讓圖片放大
filter: grayscale(0%); 由單色變成彩色
grayscale 100%:完全黑白,0%:恢復原色)

See the Pen card03 by y-maeda (@Maeda-Yoshie) on CodePen.

範例程式如下HTML

<p class="label">單色圖庫</p>
<div class="gallery">
    <a class="gallery-item">
        <img src="https://lh3.googleusercontent.com/d/1_QUDgFv8a3Lund9zRgj233amum3yLMW6" alt="sea">
        <div class="gallery-box">
            <span class="gallery-text">view more</span>
        </div>
    </a>

    <a class="gallery-item">
        <img src="https://lh3.googleusercontent.com/d/1UzvY8iYshkvJx8zcXk_O0fiwoY5zhNb8" alt="mountain">
        <div class="gallery-box">
            <span class="gallery-text">view more</span>
        </div>
    </a>

    <a class="gallery-item">
        <img src="https://lh3.googleusercontent.com/d/1IHiGU8T1DmDV3TAHTWu57X0rSpcnTxyA" alt="forest">
        <div class="gallery-box">
            <span class="gallery-text">view more</span>
        </div>
    </a>
</div>

CSS

.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    gap: 16px;
}

.gallery-item {
    flex: 1;
    position: relative;
    height: 160px;
    border-radius: 12px;
    overflow: hidden;
    cursor: pointer;
    text-decoration: none;
}

.gallery-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: grayscale(100%); /* 轉為黑白 */
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.gallery-item .gallery-box {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.25);
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

.gallery-text {
    color: #D20B08;
    font-size: 0.85rem;
    font-weight: 700;
    border: 2px solid #D20B08;
    padding: 6px 16px;
    border-radius: 6px;
    transition: all 0.4s ease;  /* 0.4 秒內平滑變化 */
}

/* hover 時 */
.gallery-item:hover img {
    filter: grayscale(0%); /* 恢復為標準色彩 */
    transform: scale(1.1);
}

.gallery-item:hover .gallery-box {
    background: transparent;
}

.gallery-item:hover .gallery-text {
    background-color: #ffffff;
    border-color: #ffffff;
}

總結

這次介紹了如何透過組合 transitiontransform 等 CSS 屬性,替按鈕和卡片加入動態效果。

如果你是「知道 transitiontransform,但其實很少用」的人,只要有意識地把它們加進設計中,我想 UI 表現的可能性會大幅提升。

不只是直接套用這次介紹的動畫,也很歡迎你嘗試調整色彩、移動距離、動畫速度等,做出更符合網站或 App 氛圍的表現。

感謝你讀到最後!


原文出處:https://qiita.com/nt_y-maeda112/items/48d124a11623b4f9e7c6


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝9   💬4   ❤️2
255
🥈
我愛JS
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登