iT邦幫忙

1

跟著AI一起:從零打造一個互動式網站 Day26

  • 分享至 

  • xImage
  •  
  1. 正確載入 Google Fonts(效能友善)
HTML <head> 建議寫法
<!-- 提前連線,減少 DNS/SSL 延遲 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- 載入字體(以 Noto Sans TC 為例);display=swap 避免字體閃爍 -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;600;800&display=swap" rel="stylesheet">

CSS 字體堆疊(含後援)

body {
  font-family: "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", system-ui, -apple-system, Arial, sans-serif;
}

重點

preconnect:瀏覽器先建立 TCP/SSL,縮短字體載入時間。

display=swap:在自訂字體尚未載入時先用系統字體,載入後再替換,避免空白閃爍(FOIT)。

後援字體:確保沒網路或載入失敗時仍可讀。

  1. CSS 動畫兩大核心
    (A) transition(狀態切換時平滑過渡)

適合 hover、focus、開闔等 UI 微動效。

.btn {
  padding: 10px 16px;
  background: #4f46e5;
  color: #fff;
  border-radius: 10px;
  border: none;
  cursor: pointer;
  /* 只動畫 transform/box-shadow(避免 layout 抖動) */
  transition: transform .2s ease, box-shadow .2s ease, background-color .2s ease;
}

.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0,0,0,.12);
  background: #4338ca;
}

(B) @keyframes(時間軸驅動的連續動畫)

適合 Loading、進場、注意力聚焦等完整節奏。

@keyframes spin {
  to { transform: rotate(360deg); }
}
.loader {
  width: 28px; height: 28px; border-radius: 50%;
  border: 3px solid #e5e7eb;           /* 淺色外圈 */
  border-top-color: #4f46e5;            /* 亮色進度 */
  animation: spin 1s linear infinite;   /* 無限旋轉 */
}
  1. 範例:美化組件(可直接貼用)
    (1) 卡片浮起(Card Hover Lift)
<div class="card">卡片內容</div>

.card {
  background: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 2px 10px rgba(0,0,0,.06);
  transition: transform .18s ease, box-shadow .18s ease;
  will-change: transform; /* 提示瀏覽器做圖層加速 */
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 24px rgba(0,0,0,.12);
}

(2) 主要按鈕(Primary Button)

<button class="btn">送出</button>

.btn { /* 見上方 transition 範例 */ }
.btn:active { transform: translateY(-1px) scale(.99); }

(3) 進場淡入(Scroll Reveal)

<section class="reveal">這一段會在滾動到時淡入顯示</section>

.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .5s ease, transform .5s ease;
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

<script>
  // 用 IntersectionObserver 增加 .is-visible
  const els = document.querySelectorAll('.reveal');
  const io = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        e.target.classList.add('is-visible');
        // 若只需要一次,可取消觀察
        io.unobserve(e.target);
      }
    });
  }, { threshold: 0.15 }); // 露出 15% 觸發
  els.forEach(el => io.observe(el));
</script>

(4) Loading 旋轉(等待 API 或寫入)

<div class="loader" aria-label="載入中" role="status"></div>
/* 見 @keyframes spin 與 .loader 定義 */
  1. 無障礙與效能
    (a) 尊重「減少動效」偏好
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

(b) 盡量用 transform opacity

避免用 top/left/width/height 做動畫,會觸發 reflow,成本較高。

transformopacity 幾乎只需合成層,較順暢。

(c) 針對會動的元素加 will-change

但不要到處亂加(會耗記憶體),僅在常動的元素使用。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言