跳至主要内容

LESS 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

前言

LESS(Leaner Style Sheets)是一種 CSS 預處理器,它在 CSS 的基礎上加入了變數、嵌套、混合(Mixins)、函式等功能,使樣式表的管理更加靈活且易於維護。LESS 文件最終會被編譯成標準的 CSS,並可在瀏覽器或 Node.js 環境中使用。


1. 安裝與使用

LESS 可以透過以下幾種方式使用:

1.1 透過 LESS.js 在瀏覽器中運行

這種方式適合開發環境,但不建議在正式環境中使用,因為它會在瀏覽器端進行編譯,影響效能。

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LESS 測試</title>
<link rel="stylesheet/less" type="text/css" href="styles.less">
<script src="https://cdnjs.cloudflare.com/ajax/libs/less.js/4.1.1/less.min.js"></script>
</head>
<body>
<h1>Hello LESS!</h1>
</body>
</html>

1.2 透過 Node.js 編譯 LESS

如果你希望在開發環境中預先編譯 LESS,則可以使用 npm 安裝 LESS:

npm install -g less

然後使用以下指令將 .less 文件編譯為 .css

lessc styles.less styles.css

這樣就能夠將 LESS 轉換為 CSS,並直接在 HTML 中引用 styles.css


2. LESS 的基本語法

2.1 變數(Variables)

LESS 允許使用變數來儲存顏色、字型大小、間距等值,方便統一管理樣式。

@primary-color: #3498db;
@font-size: 16px;

body {
color: @primary-color;
font-size: @font-size;
}

2.2 嵌套(Nesting)

LESS 允許使用嵌套的方式來撰寫 CSS,這樣可以清楚地表示層級關係。

nav {
background-color: #333;
ul {
list-style: none;
li {
display: inline-block;
a {
text-decoration: none;
color: white;
}
}
}
}

編譯後的 CSS:

nav {
background-color: #333;
}
nav ul {
list-style: none;
}
nav ul li {
display: inline-block;
}
nav ul li a {
text-decoration: none;
color: white;
}

2.3 混合(Mixins)

混合(Mixin)類似於函式,可以定義一組樣式,並在多個地方重複使用。

.border-radius(@radius) {
border-radius: @radius;
}

.button {
background-color: @primary-color;
.border-radius(5px);
}

編譯後的 CSS:

.button {
background-color: #3498db;
border-radius: 5px;
}

2.4 運算(Operations)

LESS 支援數學運算,可以用來計算尺寸、顏色等。

@base-size: 10px;

.box {
width: @base-size * 5;
height: @base-size * 3;
padding: @base-size + 5px;
}

編譯後的 CSS:

.box {
width: 50px;
height: 30px;
padding: 15px;
}

2.5 繼承(Extend)

LESS 提供 extend 功能,允許一個選擇器繼承另一個選擇器的樣式。

.message {
padding: 10px;
border: 1px solid #ddd;
}

.success {
&:extend(.message);
background-color: #dff0d8;
}

編譯後的 CSS:

.message,
.success {
padding: 10px;
border: 1px solid #ddd;
}
.success {
background-color: #dff0d8;
}

3. 進階功能

3.1 運用函式(Functions)

LESS 提供許多內建函式,例如 lighten()darken()fadeout() 等來調整顏色透明度、亮度等。

@main-color: #3498db;

.button {
background-color: @main-color;
border: 1px solid darken(@main-color, 10%);
color: lighten(@main-color, 20%);
}

編譯後的 CSS:

.button {
background-color: #3498db;
border: 1px solid #217dbb;
color: #5dade2;
}

3.2 迴圈(Loops)

LESS 允許使用 each() 來迭代陣列,或使用 for 來執行迴圈。

@colors: red, green, blue;

.each(@colors, {
.box-@{value} {
background-color: @value;
}
});

編譯後的 CSS:

.box-red {
background-color: red;
}
.box-green {
background-color: green;
}
.box-blue {
background-color: blue;
}

3.3 延遲運算(Lazy Evaluation)

LESS 變數的值在運算時才會解析,因此可以動態變更變數內容。

@theme-color: @primary-color;

.button {
background-color: @theme-color;
}

這樣如果稍後更改 @primary-color@theme-color 也會自動更新。


4. 結論

LESS 透過變數、嵌套、混合、運算等功能,大大提升了 CSS 的可維護性與開發效率。建議開發者透過 Node.js 進行 LESS 編譯,避免在瀏覽器端執行影響效能。透過 LESS,樣式表變得更具結構化,讓前端開發更為靈活高效。

Vue nextTick 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

前言

在使用 Vue 進行開發時,常常會遇到「資料已經更新,但畫面上的 DOM 尚未更新完成」的情況。這是因為 Vue 採用了 非同步更新策略 (asynchronous update strategy),它會先收集多次資料變動,再一次性地進行 DOM 更新,以提升效能。但這也意味著,如果我們想在資料變更後立即操作更新後的 DOM,往往會發現 DOM 還停留在舊的狀態。

為了解決這個問題,Vue 提供了 nextTick 這個 API。它允許我們在 DOM 更新完成後,執行特定的 callback function 或程式碼,確保操作的 DOM 是最新的。本文將介紹 nextTick 的基本概念、使用情境與實際範例,幫助你掌握這個常用的技巧。


重點摘要

  • Vue 更新策略

    • Vue 採用「批次非同步更新」,會延遲 DOM 實際渲染,等所有同步程式碼執行後再統一更新。
    • 好處:避免重複渲染、提升效能。
    • 挑戰:在資料變更後立刻訪問 DOM,可能還是舊狀態。
  • nextTick 的作用

    • 確保在下一次 DOM 更新循環結束後再執行指定 callback。

    • 語法:

      import { nextTick } from 'vue';

      nextTick(() => {
      // DOM 已更新完成
      });
  • 常見使用情境

    1. 操作最新 DOM 元素:例如要取得更新後元素的高度、寬度或位置。
    2. 與第三方函式庫整合:某些 UI 套件需要等 DOM 更新後再初始化。
    3. 強制等待渲染完成再執行程式:避免非同步更新造成的狀態錯誤。
  • 可搭配 async/await

    • nextTick 也能回傳 Promise,讓程式碼更直觀。
    • 適合在 setupmethods 中使用 await nextTick()

實際範例

範例一:取得更新後的 DOM

<template>
<div>
<button @click="addItem">新增項目</button>
<ul ref="list">
<li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>
<p>目前清單高度:{{ listHeight }}px</p>
</div>
</template>

<script setup>
import { ref, nextTick } from 'vue';

const items = ref(['項目 1', '項目 2']);
const list = ref(null);
const listHeight = ref(0);

function addItem() {
items.value.push(`項目 ${items.value.length + 1}`);
// 此時 DOM 尚未更新,listHeight 還是舊的
nextTick(() => {
listHeight.value = list.value.offsetHeight;
});
}
</script>

說明:

  • 點擊按鈕時,會往清單新增項目。
  • items 更新後,Vue 還沒立刻修改 DOM。
  • 使用 nextTick,等到 DOM 重新渲染後,才能正確取得最新高度。

範例二:搭配 async/await 使用

<template>
<div>
<button @click="toggleBox">切換方塊</button>
<div v-if="show" ref="box" class="box"></div>
</div>
</template>

<script setup>
import { ref, nextTick } from 'vue';

const show = ref(false);
const box = ref(null);

async function toggleBox() {
show.value = !show.value;
await nextTick();
if (box.value) {
console.log('方塊尺寸:', box.value.offsetWidth, box.value.offsetHeight);
}
}
</script>

<style scoped>
.box {
width: 200px;
height: 100px;
background-color: lightblue;
}
</style>

說明:

  • 使用 await nextTick(),讓程式碼讀起來更直覺。
  • v-if 切換後,等 DOM 更新完成再訪問 box,避免 null 或舊的狀態。

範例三:計算新增元素更新後高度

<template>
<div>
<button @click="addItem">新增項目</button>
<ul ref="list">
<li v-for="n in items" :key="n">項目 {{ n }}</li>
</ul>
</div>
</template>

<script setup>
import { ref, nextTick } from 'vue';

const items = ref([1, 2]);
const list = ref(null);

async function addItem() {
items.value.push(items.value.length + 1);

console.log('立即讀取高度:', list.value.offsetHeight);

await nextTick();
console.log('nextTick 後高度:', list.value.offsetHeight);
}
</script>

說明:

  • 立即讀取高度 → 還是舊值
  • nextTick 後高度 → 才是更新後的 DOM 高度

範例四:與第三方套件整合

假設要在 Vue 中使用某個需要 DOM 初始化的套件(例如輪播圖 Swiper):

<template>
<div>
<button @click="initSlider">初始化輪播</button>
<div ref="slider">
<div class="slide" v-for="n in 3" :key="n">Slide {{ n }}</div>
</div>
</div>
</template>

<script setup>
import { ref, nextTick } from 'vue';
// 假設已安裝 Swiper
import Swiper from 'swiper';

const slider = ref(null);
let swiperInstance = null;

async function initSlider() {
await nextTick();
if (slider.value && !swiperInstance) {
swiperInstance = new Swiper(slider.value, {
loop: true,
autoplay: true,
});
}
}
</script>

說明:

  • 先確保 DOM 結構已經渲染完成,才交給第三方套件初始化。
  • 若省略 nextTick,可能會因為 DOM 還沒出現而報錯。

總結

  • Vue 採用非同步批次更新策略,能提升效能,但會導致資料更新後 DOM 還未立即反映。
  • nextTick 可用來等待 DOM 更新完成後再執行特定程式。
  • 使用情境包括:取得最新 DOM、整合第三方套件、避免狀態錯誤。
  • 可以透過 callback functionasync/await 使用,後者更直覺。
  • 熟悉 nextTick 能幫助我們更精確掌握 Vue 的渲染時機,寫出更穩定的互動邏輯。

常見軟體工程師/Web 開發技術面試及學習資源整理

· 閱讀時間約 2 分鐘
kdchang

CSS transition 入門教學筆記 | 學習筆記

· 閱讀時間約 3 分鐘
kdchang

前言

CSS transition 屬性允許元素在狀態變化時產生平滑的動畫效果,使 UI 更加流暢和自然。這項技術通常應用於按鈕、圖片、卡片等 UI 元素的互動效果,如懸停、點擊或狀態變更。

1. transition 基礎概念

CSS transition 屬性用於定義當元素的某些 CSS 屬性發生變化時,該變化應如何逐漸呈現,而非立即改變。基本語法如下:

transition: property duration timing-function delay;
  • property:指定要應用過渡效果的 CSS 屬性。
  • duration:設定過渡動畫的時間(如 0.5s200ms)。
  • timing-function:定義動畫的速度曲線(如 easelinear)。
  • delay:動畫開始前的延遲時間(可選,默認為 0s)。

2. transition 常見應用

2.1 過渡單一屬性

.button {
background-color: blue;
color: white;
padding: 10px 20px;
border-radius: 5px;
transition: background-color 0.3s ease;
}

.button:hover {
background-color: darkblue;
}

當滑鼠懸停在 .button 上時,背景顏色將在 0.3s 內從 blue 變為 darkblue

2.2 過渡多個屬性

.card {
width: 200px;
height: 300px;
background-color: lightgray;
transform: scale(1);
transition: background-color 0.3s ease, transform 0.5s ease-in-out;
}

.card:hover {
background-color: gray;
transform: scale(1.1);
}

當滑鼠懸停時,.card 的背景顏色會變深,並且整個卡片會放大 1.1 倍。

3. transition 進階應用

3.1 transition-timing-function(動畫速度曲線)

timing-function 用於定義動畫的速度變化方式,常見的值如下:

  • linear:等速變化。
  • ease(預設值):開始與結束較慢,中間較快。
  • ease-in:開始較慢,之後加速。
  • ease-out:開始較快,最後減速。
  • ease-in-out:開始和結束都較慢。

範例:

.box {
width: 100px;
height: 100px;
background-color: red;
transition: transform 1s ease-in-out;
}

.box:hover {
transform: translateX(200px);
}

當滑鼠懸停時,.box 會平滑地向右移動 200px,並且動畫在開始和結束時較慢。

3.2 transition-delay(延遲時間)

可以設定 transition-delay 來延遲動畫的開始時間。

.box {
width: 100px;
height: 100px;
background-color: green;
transition: background-color 0.5s ease-in 1s;
}

.box:hover {
background-color: darkgreen;
}

當滑鼠懸停時,background-color 會延遲 1s 後才開始變化。

4. transition 實際應用範例

4.1 按鈕的點擊效果

.button {
padding: 12px 24px;
background-color: #ff5733;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: transform 0.2s ease-out;
}

.button:active {
transform: scale(0.95);
}

當按下 .button 時,按鈕會稍微縮小,產生按壓感。

4.2 漸變顯示效果

.fade-box {
width: 100px;
height: 100px;
background-color: blue;
opacity: 0;
transition: opacity 1s ease-in-out;
}

.fade-box.show {
opacity: 1;
}

.show 類別被添加時,.fade-box 會在 1s 內逐漸顯示。

4.3 圖片放大效果

.image-container img {
width: 100px;
transition: width 0.3s ease-in-out;
}

.image-container:hover img {
width: 150px;
}

當滑鼠懸停時,圖片會平滑地放大。

5. transition vs animation

雖然 transitionanimation 都能用來製作動畫,但它們的用途不同:

  • transition:適合用於元素的狀態變更(如 hoverfocus)。
  • animation:適用於更複雜的動畫,如連續循環的動畫。

如果需要更高級的動畫,例如無限重複、按時間順序變化的動畫,則應使用 @keyframesanimation

6. 總結

CSS transition 是製作動畫效果最簡單且高效的方法之一。透過 transition,可以讓 UI 更加生動,使使用者體驗更流暢。掌握 transition 的基本語法與進階應用後,可以靈活運用於各種互動效果,如按鈕動畫、圖片過渡、淡入淡出等,讓網頁更加吸引人。

Responsive Design 響應式設計入門教學筆記 | 學習筆記

· 閱讀時間約 2 分鐘
kdchang

Responsive Design 響應式設計入門教學筆記

一、什麼是響應式設計

響應式設計 (Responsive Design) 是一種網頁設計方法,使網頁能夠根據不同裝置的螢幕尺寸與解析度,自動調整版面配置,以提供最佳的使用體驗。

二、響應式設計的重要概念

1. 視圖 (Viewport)

<meta name="viewport" content="width=device-width, initial-scale=1.0">

這段程式碼放在 <head> 標籤內,能讓網頁根據不同裝置寬度調整顯示比例,是響應式設計的基本設定。

2. 流動網格 (Fluid Grid)

使用百分比 (%) 來設定元素的寬度,而非固定的像素 (px),讓版面能隨螢幕大小調整。

3. 彈性圖片 (Flexible Images)

圖片大小以百分比或 max-width 設定,避免圖片超出容器範圍。

img {
max-width: 100%;
height: auto;
}

4. 媒體查詢 (Media Queries)

根據裝置螢幕大小套用不同的 CSS 樣式。

@media (max-width: 768px) {
body {
background-color: lightgrey;
}
}

三、常見的斷點 (Breakpoints)

以下為常見的螢幕寬度斷點,用來針對不同裝置設定樣式:

裝置類型斷點寬度
手機0 - 576px
平板577px - 768px
小型桌面769px - 992px
大型桌面993px 以上

四、實作範例

HTML

<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>響應式設計範例</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>歡迎來到響應式設計範例</h1>
<p>這是一個簡單的響應式網頁範例。</p>
</body>
</html>

CSS

body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: white;
}

h1 {
text-align: center;
color: #333;
}

p {
text-align: center;
font-size: 16px;
}

@media (max-width: 768px) {
body {
background-color: lightblue;
}
}

@media (max-width: 576px) {
p {
font-size: 14px;
}
}

五、其他工具

  1. Bootstrap:內建響應式網格系統,方便快速開發響應式網頁。
  2. Flexbox:簡化版面排列的工具,適合處理彈性佈局。
  3. CSS Grid:強大的網格系統,用於建立複雜的版面。

六、結語

響應式設計能提升使用者體驗,使網頁能適應不同裝置,有助於 SEO 表現,是現代網頁設計不可忽視的重要技能。

CSS 權重(Specificity)入門教學筆記 | 學習筆記

· 閱讀時間約 3 分鐘
kdchang

1. 什麼是 CSS 權重?

CSS 權重(Specificity)是指當多個選擇器同時作用於同一個元素時,瀏覽器決定應用哪條 CSS 規則的優先級機制。不同選擇器具有不同的權重,權重高的樣式會覆蓋權重低的樣式。


2. CSS 權重的計算方式

CSS 權重由四個部分組成,從高到低分別是:

  1. 行內樣式(Inline Styles)
  2. ID 選擇器(ID Selectors)
  3. 類別、偽類與屬性選擇器(Class, Pseudo-classes, Attribute Selectors)
  4. 元素與偽元素選擇器(Element, Pseudo-elements)

每種類型的選擇器都有固定的權重值,計算時以「數值」方式比較:

選擇器類型權重值
行內樣式(style=""1000
ID 選擇器(#id100
類別選擇器(.class)、偽類(:hover)、屬性選擇器([type="text"]10
元素選擇器(divp)、偽元素(::before::after1

3. 權重計算範例

3.1 元素選擇器 vs. 類別選擇器
p {
color: blue; /* 權重 1 */
}

.text {
color: red; /* 權重 10 */
}
<p class="text">這段文字應該是紅色</p>

結果: .text 的權重為 10,比 p 的權重 1 高,因此文字顯示為紅色。


3.2 類別 vs. ID 選擇器
.text {
color: red; /* 權重 10 */
}

#main {
color: green; /* 權重 100 */
}
<p id="main" class="text">這段文字應該是綠色</p>

結果: #main 的權重 100 高於 .text 的 10,因此文字顯示為綠色。


3.3 屬性選擇器與偽類
p {
color: black; /* 權重 1 */
}

p:hover {
color: blue; /* 權重 10 */
}

p[title] {
color: red; /* 權重 10 */
}
<p title="Example">這段文字會是紅色,滑鼠懸停時變藍色</p>

結果: p[title]p:hover 權重相同(10),但 p:hover 只在滑鼠懸停時生效,因此預設為紅色,懸停時變藍色。


4. 多個選擇器組合計算

當一個 CSS 規則包含多種選擇器時,其權重會累加計算。

4.1 複合選擇器
div p {
color: blue; /* 權重 2 (div=1 + p=1) */
}

div .text {
color: red; /* 權重 11 (div=1 + .text=10) */
}

#container .text {
color: green; /* 權重 110 (#container=100 + .text=10) */
}
<div id="container">
<p class="text">這段文字應該是綠色</p>
</div>

結果: #container .text 的權重 110 高於 div .text(11)和 div p(2),所以文字顯示為綠色。


4.2 !important 覆蓋權重
.text {
color: red !important;
}

#main {
color: green;
}
<p id="main" class="text">這段文字應該是紅色</p>

結果: 即使 #main 的權重較高,!important 仍然強制覆蓋樣式,使文字變紅。


5. 權重衝突的解決策略

  1. 避免使用 !important,除非是必要的
  2. 使用更具體的選擇器
  3. 組織 CSS 層級結構
  4. 使用適當的 CSS 預處理器(如 SCSS、LESS)

6. 總結

理解 CSS 權重是撰寫高效、可維護樣式表的關鍵。透過計算選擇器的權重,可以精確控制樣式的優先級,避免不必要的覆蓋問題,提升開發效率。

JavaScript Hoisting 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

1. 什麼是 Hoisting?

Hoisting(提升)是 JavaScript 中的一種行為,它允許變數與函式在執行時被提升到作用域的頂部,這表示你可以在宣告之前使用它們,而不會發生錯誤。「建立期」(Creation Phase)和「執行期」(Execution Phase),建立期主要為定義變數名稱,執行期為執行程式和指定賦值。

在 JavaScript 中,Hoisting 影響兩種類型的宣告:

  1. 變數宣告(var, let, const)
  2. 函式宣告(Function Declaration)

2. 變數 Hoisting

2.1 使用 var 的 Hoisting

var 宣告的變數會被提升,但不會初始化,這表示變數本身會被提升到作用域頂端,但其值不會。

console.log(a); // undefined
var a = 10;
console.log(a); // 10

上述程式碼等同於:

var a;
console.log(a); // undefined

a = 10;
console.log(a); // 10

在 Hoisting 過程中,變數 a 被提升(Hoist)到了作用域的頂部,但它的值 10 並沒有一起提升,因此第一次 console.log(a); 會輸出 undefined

2.2 使用 letconst 的 Hoisting

letconst 也會被提升,但它們不會自動初始化,因此在變數宣告之前存取會導致 ReferenceError

console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;

等同於:

let b;
console.log(b); // ReferenceError
b = 20;

letconst 變數存在「暫時性死區(Temporal Dead Zone, TDZ)」,這表示變數在初始化之前無法被存取。

console.log(c); // ReferenceError
const c = 30;

2.3 總結變數 Hoisting

宣告方式是否 Hoisting是否初始化TDZ 存在
varundefined
let
const

3. 函式 Hoisting

3.1 Function Declaration(函式宣告)

函式宣告(function foo() {})會完整 Hoisting,因此可以在定義之前調用。

hello(); // Hello, world!

function hello() {
console.log("Hello, world!");
}

在執行時,JavaScript 會將函式整個提升到作用域頂部,因此 hello() 可以在函式宣告前執行。

等同於:

function hello() {
console.log("Hello, world!");
}

hello(); // Hello, world!

3.2 Function Expression(函式表達式)

使用 var 宣告的函式表達式(Function Expression)僅會提升變數,但不會提升函式內容,因此無法在宣告前調用。

console.log(sayHi); // undefined
sayHi(); // TypeError: sayHi is not a function

var sayHi = function() {
console.log("Hi!");
};

上述程式碼等同於:

var sayHi;
console.log(sayHi); // undefined

sayHi = function() {
console.log("Hi!");
};

因為 sayHi 在 Hoisting 時只被提升變數,但未初始化,因此 console.log(sayHi); 顯示 undefined,並且 sayHi(); 會導致 TypeError

3.3 使用 letconst 的 Function Expression

若函式表達式使用 letconst,則變數仍然會被提升,但會受到暫時性死區(TDZ)影響,因此在初始化前使用會導致 ReferenceError

console.log(sayHello); // ReferenceError: Cannot access 'sayHello' before initialization
let sayHello = function() {
console.log("Hello!");
};

4. 結論與最佳實踐

4.1 總結 Hoisting 行為

  1. 變數宣告
    • var 會被提升並初始化為 undefined
    • letconst 會被提升,但不會初始化(存在 TDZ)。
  2. 函式宣告
    • function 會完整提升,可以在宣告前調用。
    • var 宣告的函式表達式只提升變數,無法在宣告前調用。
    • letconst 宣告的函式表達式受 TDZ 影響,無法在宣告前使用。

4.2 最佳實踐

  • 避免使用 var,改用 letconst
  • 函式表達式應在使用前宣告,避免 undefinedReferenceError
  • 將所有變數與函式宣告放在作用域的開頭,可減少 Hoisting 帶來的困惑。

4.3 最佳實踐範例

// 正確做法:將變數與函式宣告放在最上方
function greet() {
console.log("Hello, world!");
}

greet();

const sayHi = function() {
console.log("Hi!");
};

sayHi();

這樣可以確保程式碼易於理解,並避免因 Hoisting 造成的問題。

參考文件

  1. [JavaScript] Javascript 的執行環境 (Execution context) 與堆疊 (Stack)
  2. 初學者指南:深入了解 JavaScript 中的 Event Loop(事件循環)
  3. 初學者指南:深入了解 JavaScript 的 Call Stack(呼叫堆疊)
  4. 初學者指南:深入了解 JavaScript 的執行環境(Execution Context)
  5. 初學者指南:深入了解 JavaScript 的建立期與執行期
  6. 初學者指南:深入了解 JavaScript 中函式與變數的建立期與執行期差異

CSS 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

1. 什麼是 CSS?

CSS(Cascading Style Sheets,層疊樣式表)是一種用來美化 HTML 頁面的樣式語言。透過 CSS,可以設定字體、顏色、間距、佈局等,讓網頁更具吸引力和可讀性。

CSS 透過選擇器(Selectors)來指定 HTML 元素,並套用樣式規則(Rules)。


2. CSS 的使用方式

有三種方式可以在 HTML 文件中使用 CSS:

2.1 內部 CSS(Internal CSS)

將 CSS 直接寫在 HTML 的 <style> 標籤內:

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>內部 CSS 範例</title>
<style>
body {
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
h1 {
color: #007bff;
text-align: center;
}
</style>
</head>
<body>
<h1>這是標題</h1>
<p>這是一段文字。</p>
</body>
</html>
2.2 外部 CSS(External CSS)

將 CSS 放入獨立的 .css 檔案,並透過 <link> 引入:

styles.css

body {
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}

h1 {
color: #007bff;
text-align: center;
}

HTML 文件:

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>外部 CSS 範例</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>這是標題</h1>
<p>這是一段文字。</p>
</body>
</html>
2.3 行內 CSS(Inline CSS)

直接在 HTML 標籤內使用 style 屬性:

<h1 style="color: red; text-align: center;">這是紅色標題</h1>

行內 CSS 只能用於單一元素,不利於維護,因此不建議大量使用。


3. CSS 選擇器(Selectors)

選擇器用於選取 HTML 元素並套用樣式,常見的選擇器有:

3.1 元素選擇器(Element Selector)

直接指定 HTML 標籤:

p {
color: blue;
font-size: 16px;
}
3.2 類別選擇器(Class Selector)

使用 . 選擇類別,適用於多個元素:

.important-text {
color: red;
font-weight: bold;
}

對應的 HTML:

<p class="important-text">這是一段重要的文字。</p>
3.3 ID 選擇器(ID Selector)

使用 # 選擇 ID,適用於單一元素:

#main-title {
font-size: 24px;
color: green;
}

對應的 HTML:

<h1 id="main-title">這是主標題</h1>
3.4 群組選擇器(Group Selector)

同時選取多個元素:

h1, h2, p {
font-family: Arial, sans-serif;
}
3.5 後代選擇器(Descendant Selector)

選取某個元素內的特定元素:

div p {
color: gray;
}

對應的 HTML:

<div>
<p>這段文字會變成灰色。</p>
</div>

4. 盒模型(Box Model)

CSS 中的所有元素都遵循盒模型(Box Model),包含以下部分:

  • Content(內容):元素內部的內容,如文字或圖片。
  • Padding(內邊距):內容與邊框之間的距離。
  • Border(邊框):元素的邊界。
  • Margin(外邊距):元素與其他元素之間的距離。

範例:

.box {
width: 200px;
height: 100px;
padding: 10px;
border: 2px solid black;
margin: 20px;
background-color: lightblue;
}

對應的 HTML:

<div class="box">這是一個盒子</div>

注意:box-sizing 屬性: content-box(預設)、border-box(寬高合計包含 padding 和 border)


5. 常見的 CSS 屬性

5.1 文字樣式
p {
font-size: 18px;
color: #333;
text-align: center;
line-height: 1.5;
}
5.2 背景樣式
body {
background-color: #f8f9fa;
background-image: url("background.jpg");
background-size: cover;
}
5.3 邊框與圓角
.box {
border: 2px solid #000;
border-radius: 10px;
}
5.4 Flexbox 佈局
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}

對應的 HTML:

<div class="container">
<div class="box">置中內容</div>
</div>

6. 響應式設計(Responsive Design)

使用 @media 來適應不同裝置:

@media (max-width: 600px) {
body {
background-color: lightgray;
}
}

當螢幕寬度小於 600px 時,背景變為淺灰色。


7. 總結

本篇筆記介紹了 CSS 的基本概念,包括選擇器、樣式屬性、盒模型與佈局技巧。熟練 CSS 之後,可以進一步學習 Flexbox、Grid、動畫(Animation)等進階技術,並與 JavaScript 結合,打造互動性更高的網頁。實際練習與製作小型專案是學習 CSS 的最佳方式。

CSS Stacking Context 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

前言

在網頁開發中,當多個 HTML 元素重疊時,決定它們顯示順序的機制稱為 Stacking Context(堆疊上下文)。這是一個重要概念,影響 z-index 的行為,並決定元素在畫面上的排列順序。


1. 什麼是 Stacking Context

Stacking Context 是一個獨立的層級空間,內部的元素會依照特定規則進行排序,但不會影響外部的層級。當一個元素建立了 Stacking Context,裡面的元素只會與其內部其他元素比較 z-index,而不會與外部的 z-index 直接互動。


2. Stacking Context 的建立方式

某些 CSS 屬性和條件會觸發 Stacking Context 的建立,以下是常見的觸發方式:

2.1 根元素 (<html>)

HTML 的根元素 (<html>) 本身是一個 Stacking Context,所有的元素都在這個上下文中運作。

2.2 z-indexauto 並且 positionrelativeabsolutefixed

positionrelativeabsolutefixed,且 z-index 設定為非 auto 時,該元素會創建新的 Stacking Context。

.parent {
position: relative;
z-index: 10; /* 創建 Stacking Context */
}

2.3 opacity 小於 1

任何 opacity 設定小於 1(但大於 0)的元素都會建立新的 Stacking Context。

.transparent-box {
opacity: 0.9; /* 創建 Stacking Context */
}

2.4 transformfilterclip-pathperspective 不為 none

只要元素應用了 transform(例如 scalerotate)、filterclip-path,它就會建立新的 Stacking Context。

.transformed-box {
transform: translateX(50px); /* 創建 Stacking Context */
}

2.5 will-change 設定特定值

如果 will-change 被設定為 transformopacityfilter 這類的屬性,該元素會創建新的 Stacking Context。

.optimized-box {
will-change: transform; /* 創建 Stacking Context */
}

3. Stacking Context 的影響

3.1 z-index 影響範圍

如果某個元素在新的 Stacking Context 中,即使它的 z-index 設定得很高,也不會超過它所在的 Stacking Context。這意味著:

  • 內部 z-index 的值 只在該 Stacking Context 內比較
  • 外部的元素如果 z-index 更高,仍然可能覆蓋內部 Stacking Context 內的元素。

範例:z-index 失效的情境

<div class="parent">
<div class="child"></div>
</div>
<div class="outside"></div>
.parent {
position: relative;
z-index: 10; /* 創建 Stacking Context */
}

.child {
position: absolute;
z-index: 9999; /* 只在 .parent 內生效 */
background: red;
width: 100px;
height: 100px;
}

.outside {
position: absolute;
z-index: 20;
background: blue;
width: 100px;
height: 100px;
top: 50px;
left: 50px;
}

結果:

  • .childz-index: 9999 只在 .parent 內生效。
  • .outsidez-index: 20 屬於 html 根 Stacking Context,所以 .outside 會蓋住 .child

4. 如何 Debug Stacking Context

z-index 沒有如預期運作時,可以用以下方式檢查:

4.1 使用開發者工具

  • Chrome 開發者工具(F12)內,檢查 z-index 的層級。
  • 在「Elements」面板檢查 z-index 及是否有 opacitytransform 等影響屬性。

4.2 確保 Stacking Context

如果發現 z-index 設定沒有影響,可以:

  1. 確認父元素是否創建了新的 Stacking Context。
  2. 嘗試移除 transformopacityfilter,看看是否影響 z-index

5. Stacking Context 的應用場景

5.1 固定導覽列與內容遮罩

position: fixed 的導覽列無法覆蓋其他元素時,可以確保它擁有較高 z-index,並避免它被無意創建的 Stacking Context 影響。

.navbar {
position: fixed;
top: 0;
width: 100%;
background: black;
color: white;
z-index: 1000;
}

5.2 Modal(模態視窗)

確保 modalz-index 高於其他元素,並避免 opacitytransform 影響 z-index

.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2000;
background: white;
padding: 20px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}

6. 總結

  • Stacking Context 影響 z-index 的作用範圍,讓 z-index 不總是依照數值大小決定順序。
  • 多種 CSS 屬性(如 opacitytransform)會創建 Stacking Context,可能影響層級渲染結果。
  • 在開發時,應注意哪些元素創建了 Stacking Context,以確保 z-index 如預期運作

透過以上概念與技巧,可以更靈活地管理 HTML 元素的層級關係,確保視覺效果正確。