☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
前端基礎 初學

🎨 CSS 樣式與排版

📌 什麼是 CSS?

比喻:CSS 就像房子的裝潢設計 🎨

如果 HTML 是房子的骨架(鋼筋水泥),那 CSS 就是室內設計師。 CSS 決定了牆壁要什麼顏色、家具怎麼擺放、窗簾用什麼材質。 同一棟房子(HTML),換一套裝潢(CSS)就能變成完全不同的風格。

CSS(Cascading Style Sheets)用來控制 HTML 元素的外觀和排版方式。


📌 CSS 選擇器(Selectors)

選擇器決定了「你要裝潢哪個房間」。

/* 元素選擇器:選中所有 p 標籤 */
p {
    color: #333; /* 設定文字顏色為深灰色 */
    line-height: 1.6; /* 設定行高為字體大小的 1.6 倍 */
}

/* Class 選擇器:用 . 開頭,可重複使用在多個元素上 */
.highlight {
    background-color: yellow; /* 設定背景顏色為黃色 */
    padding: 4px 8px; /* 設定內距:上下 4px,左右 8px */
}

/* ID 選擇器:用 # 開頭,一個頁面中每個 ID 只能出現一次 */
#main-title {
    font-size: 2rem; /* 設定字體大小為 2rem(相對於根元素) */
    font-weight: bold; /* 設定字體粗細為粗體 */
}

/* 後代選擇器:選中 nav 裡面所有的 a 標籤 */
nav a {
    text-decoration: none; /* 移除底線 */
    color: #0066cc; /* 設定連結顏色為藍色 */
}

/* 子元素選擇器:只選中 ul 的「直接」子元素 li */
ul > li {
    list-style: disc; /* 設定列表樣式為實心圓點 */
    margin-bottom: 8px; /* 設定下方外距為 8px */
}

/* 相鄰兄弟選擇器:選中緊跟在 h2 後面的第一個 p */
h2 + p {
    font-size: 1.1rem; /* 第一段比其他段落稍大 */
    color: #555; /* 設定為較淺的灰色 */
}

/* 偽類選擇器:滑鼠懸停時的樣式 */
a:hover {
    color: #ff6600; /* 懸停時連結變成橘色 */
    text-decoration: underline; /* 懸停時顯示底線 */
}

/* 偽類選擇器:聚焦時的樣式(鍵盤 Tab 或點擊輸入框) */
input:focus {
    border-color: #0066cc; /* 聚焦時邊框變藍色 */
    outline: 2px solid rgba(0, 102, 204, 0.3); /* 加上半透明的外框 */
}

/* 偽元素選擇器:在元素「之前」插入內容 */
.required::before {
    content: "* "; /* 在必填欄位前面加上星號 */
    color: red; /* 星號顯示為紅色 */
}

/* 屬性選擇器:選中所有 type="email" 的 input */
input[type="email"] {
    width: 100%; /* 寬度佔滿父容器 */
    padding: 8px; /* 內距 8px */
}

/* nth-child 選擇器:選中奇數列(表格斑馬紋) */
tr:nth-child(odd) {
    background-color: #f9f9f9; /* 奇數列背景設為淺灰色 */
}

📌 Box Model(盒模型)

每個 HTML 元素都是一個「盒子」,就像每個房間都有牆壁、地板、傢俱的空間配置。

/* Box Model 完整示範 */
.card {
    /* Content:內容區域,放文字和圖片的空間 */
    width: 300px; /* 設定內容寬度為 300px */
    height: auto; /* 高度自動根據內容調整 */

    /* Padding:內距,內容和邊框之間的空間(像房間裡牆壁到傢俱的距離) */
    padding: 20px; /* 四個方向都是 20px */
    padding-top: 10px; /* 也可以單獨設定某一邊的內距 */

    /* Border:邊框,盒子的外框(像房間的牆壁) */
    border: 1px solid #ddd; /* 1px 寬、實線、淺灰色邊框 */
    border-radius: 8px; /* 設定圓角半徑為 8px */

    /* Margin:外距,盒子和其他盒子之間的空間(像房間和房間之間的走廊) */
    margin: 16px; /* 四個方向都是 16px */
    margin-bottom: 24px; /* 下方外距設大一點 */

    /* box-sizing 很重要! */
    box-sizing: border-box; /* 讓 width 包含 padding 和 border,計算更直覺 */
}

/* 建議全域設定 box-sizing */
*, *::before, *::after {
    box-sizing: border-box; /* 所有元素都用 border-box,避免計算寬度時出錯 */
}

📌 Flexbox 完整指南

Flexbox 就像一條彈性的置物架,可以自動調整裡面物品的排列方式。

/* === 容器屬性(Container Properties) === */

.flex-container {
    display: flex; /* 啟用 Flexbox 排版模式 */
    flex-direction: row; /* 主軸方向:row(水平)| column(垂直) */
    flex-wrap: wrap; /* 允許子元素換行(預設 nowrap 不換行) */
    justify-content: space-between; /* 主軸對齊:均勻分布,頭尾貼邊 */
    align-items: center; /* 交叉軸對齊:垂直置中 */
    gap: 16px; /* 子元素之間的間距 */
}

/* justify-content 常用值 */
.demo-justify {
    justify-content: flex-start; /* 靠主軸起點(預設值) */
    justify-content: flex-end; /* 靠主軸終點 */
    justify-content: center; /* 主軸置中 */
    justify-content: space-between; /* 均勻分布,第一和最後一個貼邊 */
    justify-content: space-around; /* 均勻分布,兩側有半個間距 */
    justify-content: space-evenly; /* 完全均勻分布 */
}

/* align-items 常用值 */
.demo-align {
    align-items: stretch; /* 拉伸填滿交叉軸(預設值) */
    align-items: flex-start; /* 靠交叉軸起點(頂部) */
    align-items: flex-end; /* 靠交叉軸終點(底部) */
    align-items: center; /* 交叉軸置中 */
    align-items: baseline; /* 以文字基線對齊 */
}

/* === 子元素屬性(Item Properties) === */

.flex-item {
    flex-grow: 1; /* 允許元素放大,數字越大佔越多空間 */
    flex-shrink: 0; /* 不允許元素縮小(0 表示不縮小) */
    flex-basis: 200px; /* 元素的初始大小 */
    flex: 1 0 200px; /* 簡寫:grow shrink basis */
    align-self: flex-end; /* 覆蓋容器的 align-items,單獨設定對齊 */
    order: 2; /* 改變排列順序,數字越小越前面(預設 0) */
}

/* 實用範例:導覽列 */
.navbar {
    display: flex; /* 啟用 Flex 排版 */
    justify-content: space-between; /* Logo 和選單分散在兩端 */
    align-items: center; /* 垂直置中 */
    padding: 0 24px; /* 左右內距 24px */
    background-color: #1a1a2e; /* 深色背景 */
    height: 60px; /* 固定高度 60px */
}

/* 實用範例:卡片網格 */
.card-grid {
    display: flex; /* 啟用 Flex 排版 */
    flex-wrap: wrap; /* 允許卡片換行 */
    gap: 20px; /* 卡片之間的間距 */
}

.card-grid .card {
    flex: 1 1 300px; /* 可放大、可縮小、基礎寬度 300px */
    max-width: 400px; /* 限制最大寬度 */
}

/* 實用範例:垂直水平完美置中 */
.center-content {
    display: flex; /* 啟用 Flex 排版 */
    justify-content: center; /* 水平置中 */
    align-items: center; /* 垂直置中 */
    min-height: 100vh; /* 最小高度佔滿整個視窗 */
}

📌 CSS Grid 基礎

/* Grid 容器設定 */
.grid-container {
    display: grid; /* 啟用 Grid 排版模式 */
    grid-template-columns: repeat(3, 1fr); /* 建立 3 欄,每欄等寬(1fr = 1 份) */
    grid-template-rows: auto; /* 列高自動根據內容調整 */
    gap: 20px; /* 網格之間的間距 */
    padding: 20px; /* 容器內距 */
}

/* 讓某個子元素跨多欄 */
.full-width {
    grid-column: 1 / -1; /* 從第 1 條線到最後一條線,佔滿所有欄 */
}

/* 讓某個子元素佔兩欄 */
.span-two {
    grid-column: span 2; /* 跨越 2 個欄位 */
}

/* 經典聖杯佈局 */
.holy-grail {
    display: grid; /* 啟用 Grid */
    grid-template-areas: /* 用命名區域定義版面 */
        "header header header" /* 第一列:header 橫跨全部 */
        "nav    main   aside" /* 第二列:左側導覽、中間內容、右側邊欄 */
        "footer footer footer"; /* 第三列:footer 橫跨全部 */
    grid-template-columns: 200px 1fr 200px; /* 三欄:左 200px、中間彈性、右 200px */
    grid-template-rows: 60px 1fr 40px; /* 三列:頂 60px、中間彈性、底 40px */
    min-height: 100vh; /* 最小高度佔滿視窗 */
}

/* 指定子元素到對應區域 */
.holy-grail header { grid-area: header; } /* header 放到 header 區域 */
.holy-grail nav { grid-area: nav; } /* nav 放到 nav 區域 */
.holy-grail main { grid-area: main; } /* main 放到 main 區域 */
.holy-grail aside { grid-area: aside; } /* aside 放到 aside 區域 */
.holy-grail footer { grid-area: footer; } /* footer 放到 footer 區域 */

📌 響應式設計(Responsive Design)

/* 手機優先(Mobile First):先寫手機樣式,再用 media query 擴展 */
.container {
    width: 100%; /* 手機上佔滿寬度 */
    padding: 0 16px; /* 左右留 16px 的呼吸空間 */
}

/* 平板以上(768px 以上)*/
@media (min-width: 768px) { /* 當螢幕寬度 >= 768px 時套用 */
    .container {
        max-width: 720px; /* 限制最大寬度 */
        margin: 0 auto; /* 水平置中 */
    }
    .grid-container {
        grid-template-columns: repeat(2, 1fr); /* 平板上顯示 2 欄 */
    }
}

/* 桌機以上(1024px 以上)*/
@media (min-width: 1024px) { /* 當螢幕寬度 >= 1024px 時套用 */
    .container {
        max-width: 960px; /* 桌機最大寬度 960px */
    }
    .grid-container {
        grid-template-columns: repeat(3, 1fr); /* 桌機上顯示 3 欄 */
    }
}

/* rem 和 em 的差別 */
html {
    font-size: 16px; /* 根元素字體大小(1rem = 16px) */
}

.title {
    font-size: 2rem; /* 2 × 16px = 32px,基於根元素計算 */
    margin-bottom: 1rem; /* 1 × 16px = 16px */
}

.subtitle {
    font-size: 1.5em; /* 1.5 × 父元素字體大小,基於父元素計算 */
}

📌 CSS 變數(Custom Properties)

/* 在 :root 定義全域變數(像是設計系統的調色盤) */
:root {
    --primary-color: #0066cc; /* 主色:藍色 */
    --secondary-color: #ff6600; /* 輔助色:橘色 */
    --text-color: #333333; /* 文字顏色:深灰 */
    --bg-color: #ffffff; /* 背景顏色:白色 */
    --spacing-sm: 8px; /* 小間距 */
    --spacing-md: 16px; /* 中間距 */
    --spacing-lg: 24px; /* 大間距 */
    --border-radius: 8px; /* 統一圓角大小 */
    --font-family: 'Noto Sans TC', sans-serif; /* 設定字體為思源黑體 */
}

/* 使用 var() 引用變數 */
.button {
    background-color: var(--primary-color); /* 使用主色作為按鈕背景 */
    color: white; /* 按鈕文字為白色 */
    padding: var(--spacing-sm) var(--spacing-md); /* 使用間距變數 */
    border: none; /* 移除邊框 */
    border-radius: var(--border-radius); /* 使用統一圓角 */
    font-family: var(--font-family); /* 使用統一字體 */
    cursor: pointer; /* 滑鼠游標變成手指 */
}

/* 深色模式:只需要修改變數值 */
@media (prefers-color-scheme: dark) { /* 偵測系統深色模式 */
    :root {
        --text-color: #e0e0e0; /* 深色模式:文字改為淺灰 */
        --bg-color: #1a1a1a; /* 深色模式:背景改為深色 */
    }
}

🤔 我這樣寫為什麼會錯?

❌ 錯誤 1:忘記設定 box-sizing 導致寬度計算錯誤

/* 錯誤:width 300px + padding 20px×2 + border 1px×2 = 實際佔 342px */
.card {
    width: 300px; /* 以為寬度是 300px */
    padding: 20px; /* 但 padding 會額外增加寬度 */
    border: 1px solid #ccc; /* border 也會額外增加寬度 */
}

/* 正確:加上 box-sizing 讓 width 包含 padding 和 border */
.card {
    width: 300px; /* 設定寬度為 300px */
    padding: 20px; /* padding 包含在 300px 裡面 */
    border: 1px solid #ccc; /* border 也包含在 300px 裡面 */
    box-sizing: border-box; /* 重點!讓 300px 是最終寬度 */
}

❌ 錯誤 2:margin 塌陷(Margin Collapse)

/* 錯誤:以為上下兩個元素的間距是 40px + 30px = 70px */
.box-a {
    margin-bottom: 40px; /* 下方外距 40px */
}
.box-b {
    margin-top: 30px; /* 上方外距 30px */
}
/* 實際間距只有 40px(取較大值),這就是 margin 塌陷 */

/* 解法:只在一個方向設定 margin */
.box-a {
    margin-bottom: 40px; /* 統一只用 margin-bottom */
}
.box-b {
    margin-top: 0; /* 不設定 margin-top,避免塌陷困擾 */
}

❌ 錯誤 3:Flexbox 子元素不換行導致擠壓

/* 錯誤:沒有設定 flex-wrap,子元素擠在一行被壓扁 */
.container {
    display: flex; /* 啟用 Flex 但預設不換行 */
}
.item {
    width: 300px; /* 設定了寬度,但會被壓縮 */
}

/* 正確:設定 flex-wrap 允許換行 */
.container {
    display: flex; /* 啟用 Flex 排版 */
    flex-wrap: wrap; /* 重點!允許子元素換行 */
    gap: 16px; /* 設定間距 */
}
.item {
    flex: 1 1 300px; /* 可放大、可縮小、基礎寬度 300px */
}

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊