2026年11月13日 星期五

JavaScript 入門教學(十五):用 JavaScript 控制樣式與動畫(classList、CSS 變數、animate)

網頁的外觀主要由 CSS 決定,而 JavaScript 負責在適當的時機「切換」樣式或啟動動畫。本篇介紹最推薦的做法:用 classList 切換 CSS 類別、用 CSS 變數改變主題色,並用瀏覽器內建的動畫功能製作簡單的動態效果。

一、直接修改 style(適合單一、臨時的變化)

const box = document.getElementById('box');
box.style.backgroundColor = '#ffe9a8';   // CSS 的 background-color 要改成駝峰式
box.style.width = '200px';
box.style.display = 'none';              // 隱藏

直接寫 style 的缺點是樣式散落在程式裡,不容易維護,而且 box.style 只能讀到「行內樣式」,讀不到 CSS 檔案裡設定的值。要讀取實際套用的樣式,請用 getComputedStyle(box).width。

二、classList:切換 CSS 類別(建議做法)

把樣式寫在 CSS,JavaScript 只負責「加上或移除類別」,兩邊各管各的,最好維護。

方法說明
classList.add('on')加上類別
classList.remove('on')移除類別
classList.toggle('on')有就移除,沒有就加上
classList.contains('on')檢查是否有此類別(回傳 true/false)

範例:展開與收合

<style>
  .panel { overflow: hidden; max-height: 0; transition: max-height 0.3s ease; }
  .panel.open { max-height: 200px; }
</style>

<button id="toggleBtn">顯示/隱藏說明</button>
<div id="panel" class="panel">
  <p>這是可以展開與收合的說明文字。</p>
</div>

<script>
const panel = document.getElementById('panel');
document.getElementById('toggleBtn').addEventListener('click', () => {
  panel.classList.toggle('open');
});
</script>

CSS 的 transition 會讓 max-height 的變化變成平滑的動畫,JavaScript 完全不需要處理動畫細節。

三、CSS 變數:一次改變整個主題

<style>
  :root { --bg: #ffffff; --fg: #222222; }
  body  { background: var(--bg); color: var(--fg); transition: background 0.3s; }
  body.dark { --bg: #1e1e1e; --fg: #eeeeee; }
</style>

<button id="themeBtn">切換深色/淺色</button>

<script>
document.getElementById('themeBtn').addEventListener('click', () => {
  document.body.classList.toggle('dark');
});

// 也可以直接用程式修改變數
document.documentElement.style.setProperty('--bg', '#fff7e6');
</script>

需要讓使用者自己挑顏色時,用 setProperty('--變數名稱', 值) 即可立刻影響所有使用該變數的地方。

四、濾鏡:舊式寫法已淘汰,改用 CSS filter

早期的教材會用 Internet Explorer 專屬的濾鏡語法做模糊、透明等效果。這些寫法現在的瀏覽器都不支援,請改用標準的 CSS filter 屬性:

img.style.filter = 'grayscale(100%)';        // 黑白
img.style.filter = 'blur(3px)';              // 模糊
img.style.filter = 'brightness(1.2) contrast(1.1)';   // 可組合多個效果
img.style.filter = 'none';                   // 還原

半透明用 opacity(0 是全透明,1 是不透明)即可。

五、Web Animations API:用程式做動畫

需要由程式決定「何時、怎麼動」時,可以直接呼叫元素的 animate():

const ball = document.getElementById('ball');

document.getElementById('goBtn').addEventListener('click', () => {
  ball.animate(
    [
      { transform: 'translateX(0)' },
      { transform: 'translateX(200px)' }
    ],
    { duration: 600, easing: 'ease-in-out', fill: 'forwards' }
  );
});
  • 第一個參數是「關鍵影格」陣列,描述起點與終點的樣式。
  • duration 是時間(毫秒),fill: 'forwards' 表示動畫結束後停在最後的樣子。
  • 效能考量:動畫盡量改變 transform 與 opacity,比改變 left、width 更順暢。

範例:輸入錯誤時的抖動提示

function shake(el) {
  el.animate(
    [
      { transform: 'translateX(0)' },
      { transform: 'translateX(-8px)' },
      { transform: 'translateX(8px)' },
      { transform: 'translateX(0)' }
    ],
    { duration: 300 }
  );
}

六、尊重使用者的「減少動態效果」設定

有些使用者會因為動畫感到不適,而在系統中開啟「減少動態效果」。程式應該尊重這個設定:

const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

if (!reduce) {
  ball.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 400 });
}

在 CSS 裡也可以寫 @media (prefers-reduced-motion: reduce),把動畫時間縮短或關閉。

七、練習題

  1. 做一個「字體放大」按鈕,每按一次加上 big 類別,再按一次移除。
  2. 用 CSS 變數做一個顏色挑選器:<input type="color"> 改變頁面的主色。
  3. 替第八篇的表單,在欄位不合格時呼叫 shake() 提示使用者。

結語

原則很簡單:樣式寫在 CSS,JavaScript 負責切換類別與觸發動畫;動畫優先使用 transform 與 opacity,並尊重使用者的偏好設定。最後一篇,我們要把前面學到的東西整合成一個完整的小專案。

沒有留言:

張貼留言