線上課程觀課進度管理小工具開發日誌
Day 6:JavaScript 程式碼執行排序:遞迴函數、Call Stack、Task Queue
Call Stack;遞迴函數與 call stack 的關係;Task Queue(非同步的概念再釐清)
Day 9:「修煉圈圈 Practice Rings」Web app 開發日誌 - 2025 六角 AI Vibe Coding 體驗營期末大魔王作業
這份筆記旨在記錄 2025 六角 Vibe Coding 體驗營每日作業 Day 21 的期末專案成果,從一個簡單的個人痛點出發,透過與 AI(在我這個情境中是 Perplexity)協作,在一天內完成了一個包含前後端的全端網頁小工具:「修煉圈圈 Practice Rings」。
記錄雞蛋糕的每一步前端煉成過程,從小白到(也許是)前端工程師的學習與分享。

Subscribe to 雞蛋糕的前端修煉屋
線上課程觀課進度管理小工具開發日誌
Day 6:JavaScript 程式碼執行排序:遞迴函數、Call Stack、Task Queue
Call Stack;遞迴函數與 call stack 的關係;Task Queue(非同步的概念再釐清)
Day 9:「修煉圈圈 Practice Rings」Web app 開發日誌 - 2025 六角 AI Vibe Coding 體驗營期末大魔王作業
這份筆記旨在記錄 2025 六角 Vibe Coding 體驗營每日作業 Day 21 的期末專案成果,從一個簡單的個人痛點出發,透過與 AI(在我這個情境中是 Perplexity)協作,在一天內完成了一個包含前後端的全端網頁小工具:「修煉圈圈 Practice Rings」。
<100 subscribers
<100 subscribers
📅 2026-02-24 | 🏷 CSS · BEM · Layout · Positioning
電商首頁的切版練習,目標是不使用 flex/grid,僅用傳統 CSS 佈局完成設計稿還原。
由上而下拆成四個水平區塊:Header、Hero、Products、Footer。傳統佈局的三個核心工具分工明確:
Block 元素:四大區塊天生垂直堆疊,不需要額外設定
inline-block:讓選單項目、產品卡片水平並排(需注意空白字元問題)
float:Header 左右分離、Footer 三欄排列(需搭配 clearfix 清除浮動)
外層容器寬度控制慣例:
/* 外層撐滿螢幕,內層置中限寬 */
.section {
width: 100%;
}
.section__inner {
max-width: 1200px;
margin: 0 auto;
}
<header> <!-- 頁首導航 -->
<nav> <!-- 導航連結集合 -->
<main> <!-- 頁面主要內容 -->
<section> <!-- 獨立內容區塊 -->
<footer> <!-- 頁腳 -->
<h1> 只給頁面主標題,例如 Hero 的 "Fall & Winter",Logo 文字改用 <div> 或 <a>。 developer.mozilla
情境 | 結論 |
|---|---|
需要定位基準(absolute 的父層) | 需要容器 |
需要清除內部浮動(clearfix) | 需要容器 |
| 不需要再包 |
沒有 class 的無名 | 移除,避免巢狀過深 |
BEM 是 Block(區塊)__Element(元素)--Modifier(修飾符) 的命名方法論,目標是讓 CSS class 名稱具備自解釋能力,並避免樣式衝突。 sparkbox
.block {} /* 獨立元件本身 */
.block__element {} /* 元件的組成部分,雙底線 __ */
.block--modifier {} /* 元件的變體狀態,雙橫線 -- */
.header
.header__logo ← Block 的一級 Element
.header__nav ← Block 的一級 Element
.header__nav-list ← <ul> 列表容器
.header__nav-item ← <li> 單項
.header__nav-link ← <a> 連結
.products
.products__list ← <ul>
.products__item ← <li>
.products__item-link ← <a>
.products__item-img ← <img>
<ul class="header__nav-item"> <!-- ul 不是 item --> ✅ <ul class="header__nav-list"> ❌ <a href="#">Home</a> <!-- 缺少 class,無法精確控制樣式 --> ✅ <a href="#" class="header__nav-link">Home</a> ❌ <li><div class="products__item">...</div></li> <!-- 多餘容器 --> ✅ <li class="products__item">...</li>
BEM 一致性原則:products 不能在某個地方寫成 product(少一個 s),Block 名稱必須在整個元件內保持統一。 hackmd
/* ❌ 選擇器沒有 { },破壞後續 CSS 的解析 */
.header
.header__logo {
display: inline-block;
}
當 CSS 選擇器缺少配對的 {} 時,瀏覽器無法正確解析,導致後續的規則失效或行為異常。 developer.mozilla
/* 先把架構列出,未完成的用註解佔位 */
/* .header */
.header__logo {
display: inline-block;
}
/* .header__nav-link */
.header__cart {
float: right; /* 靠右對齊 */
}
口訣:選擇器若沒有規則,就先註解起來!
此外,display: inline-block 只能讓元素並排,不會改變對齊位置;要讓元素靠右需要用 float: right(傳統佈局下)。
vertical-align 有三個容易混淆的特性: w3docs
設定在子元素上,不是父元素
只對 inline 或 inline-block 元素有效
對齊基準是行盒(Line Box),不是父元素的邊界
行盒(Line Box)
┌─────────────────────────────────┐ ← line-height 決定高度
│ [logo] [nav] [cart] │ ← 三個 inline-block 元素
└─────────────────────────────────┘
步驟一:在所有並排子元素加上 vertical-align: middle
.header__logo,
.header__nav,
.header__cart {
display: inline-block;
vertical-align: middle; /* 設定在子元素,不是父元素 */
}
步驟二:在父元素設定 line-height 等於 height,撐高行盒
.header {
height: 100px;
line-height: 100px; /* 行盒高度 = 容器高度 → 子元素垂直置中 */
}
子元素過高時行盒會被撐大,對齊基準也跟著偏移,視覺上不在預期位置。防禦措施:
.header__cart-img {
max-height: 35px; /* 限制最大高度,防止撐破版面 */
height: auto;
width: auto;
}
目標元素 | 正確方法 |
|---|---|
| 在父層設 |
| 在自身設 |
margin: 0 auto 對 inline-block 無效,因為 margin: auto 只在 block formatting context 中計算。text-align: center 控制的是 inline formatting context 中的物件,而 inline-block 正是讓元素「偽裝」成行內物件,所以能被父層的 text-align 控制。 developer.mozilla
/* ✅ 正確:三張產品卡片水平置中 */
.products {
text-align: center;
}
.products__item {
display: inline-block;
}
<ul> 有瀏覽器預設的 padding-left: 40px,需要 reset:
.products__list {
padding: 0;
margin: 0;
list-style: none;
}
|
| |
|---|---|---|
層級 | HTML 內容層 | CSS 裝飾層 |
撐開容器 | (需手動設 | |
SEO/無障礙 | 有 | 無語義資訊 |
疊加文字 | 較複雜 | 直覺(搭配 |
Hero banner 使用 background-image,方便直接在容器內定位文字與按鈕。 developer.mozilla
.hero {
background-image: url("img/cover.jpg");
background-size: cover; /* 覆蓋容器,等比例裁切 */
background-position: center center;
background-repeat: no-repeat;
position: relative; /* 作為內部絕對定位元素的基準 */
height: 710px; /* background-image 不撐高,必須手動設定 */
}
<section class="hero">
<div class="hero__overlay"></div> <!-- 半透明遮罩層 -->
<div class="hero__content"> <!-- 文字與按鈕 -->
<h1 class="hero__title">Fall & Winter</h1>
<a href="#" class="hero__btn">Shop Now</a>
</div>
<p class="hero__shipping">FREE SHIPPING WORLDWIDE</p>
</section>
/* 遮罩層 */
.hero__overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 補償自身寬高的 50% */
width: 605px;
height: 190px;
background-color: rgba(255, 255, 255, 0.6);
z-index: 1; /* 遮罩在背景圖上方 */
}
/* 內容層,z-index 高於遮罩 */
.hero__content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2; /* 文字在遮罩上方 */
text-align: center;
}
/* 底部橫幅 */
.hero__shipping {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: rgb(222, 222, 222);
margin: 0;
padding: 10px 0;
text-align: center;
}
transform: translate(-50%, -50%) 原理:top: 50% 讓元素頂部對齊容器中線,但元素本身有寬高,所以要再往左上移動自身寬高的 50% 才會真正置中。 stackoverflow
.hero(position: relative)
├── background-image ← 最底層
├── .hero__overlay ← z-index: 1
├── .hero__content ← z-index: 2
└── .hero__shipping ← z-index: auto(最上層)
z-index 只對 position 不是 static 的元素生效。 w3schools
偽元素(::before/::after)與偽類(:hover/:focus)的核心差異: developer.mozilla
偽元素 | 偽類 | |
|---|---|---|
功能 | 創造新的虛擬節點 | 描述元素的狀態 |
常見例子 |
|
|
可被 JS 操作 | — |
這個層需要被 JavaScript 操作嗎?
├── 是 → 真實 DOM 元素
└── 否 → 是純視覺裝飾嗎?
├── 是 → 偽元素 ✅(::before / ::after)
└── 否(例如需要 ARIA / 點擊事件) → 真實 DOM 元素
本次遮罩選用真實 DOM,理由是尺寸為局部區域(不是全滿背景),且未來可能需要 JS 控制動態效果。
屬性 | 用途 |
|---|---|
| 圖片覆蓋容器,等比例裁切 |
| 控制背景圖位置 |
| 相對於 |
| 位移,用於水平垂直置中 |
| 含透明度的顏色,製作半透明遮罩 |
| 控制堆疊層級,只對非 |
| 控制 inline-block 兄弟元素的對齊基準 |
| 設定行盒高度,間接控制垂直置中範圍 |
| 使父層內的 inline-block 子元素水平置中 |
📅 2026-02-24 | 🏷 CSS · BEM · Layout · Positioning
電商首頁的切版練習,目標是不使用 flex/grid,僅用傳統 CSS 佈局完成設計稿還原。
由上而下拆成四個水平區塊:Header、Hero、Products、Footer。傳統佈局的三個核心工具分工明確:
Block 元素:四大區塊天生垂直堆疊,不需要額外設定
inline-block:讓選單項目、產品卡片水平並排(需注意空白字元問題)
float:Header 左右分離、Footer 三欄排列(需搭配 clearfix 清除浮動)
外層容器寬度控制慣例:
/* 外層撐滿螢幕,內層置中限寬 */
.section {
width: 100%;
}
.section__inner {
max-width: 1200px;
margin: 0 auto;
}
<header> <!-- 頁首導航 -->
<nav> <!-- 導航連結集合 -->
<main> <!-- 頁面主要內容 -->
<section> <!-- 獨立內容區塊 -->
<footer> <!-- 頁腳 -->
<h1> 只給頁面主標題,例如 Hero 的 "Fall & Winter",Logo 文字改用 <div> 或 <a>。 developer.mozilla
情境 | 結論 |
|---|---|
需要定位基準(absolute 的父層) | 需要容器 |
需要清除內部浮動(clearfix) | 需要容器 |
| 不需要再包 |
沒有 class 的無名 | 移除,避免巢狀過深 |
BEM 是 Block(區塊)__Element(元素)--Modifier(修飾符) 的命名方法論,目標是讓 CSS class 名稱具備自解釋能力,並避免樣式衝突。 sparkbox
.block {} /* 獨立元件本身 */
.block__element {} /* 元件的組成部分,雙底線 __ */
.block--modifier {} /* 元件的變體狀態,雙橫線 -- */
.header
.header__logo ← Block 的一級 Element
.header__nav ← Block 的一級 Element
.header__nav-list ← <ul> 列表容器
.header__nav-item ← <li> 單項
.header__nav-link ← <a> 連結
.products
.products__list ← <ul>
.products__item ← <li>
.products__item-link ← <a>
.products__item-img ← <img>
<ul class="header__nav-item"> <!-- ul 不是 item --> ✅ <ul class="header__nav-list"> ❌ <a href="#">Home</a> <!-- 缺少 class,無法精確控制樣式 --> ✅ <a href="#" class="header__nav-link">Home</a> ❌ <li><div class="products__item">...</div></li> <!-- 多餘容器 --> ✅ <li class="products__item">...</li>
BEM 一致性原則:products 不能在某個地方寫成 product(少一個 s),Block 名稱必須在整個元件內保持統一。 hackmd
/* ❌ 選擇器沒有 { },破壞後續 CSS 的解析 */
.header
.header__logo {
display: inline-block;
}
當 CSS 選擇器缺少配對的 {} 時,瀏覽器無法正確解析,導致後續的規則失效或行為異常。 developer.mozilla
/* 先把架構列出,未完成的用註解佔位 */
/* .header */
.header__logo {
display: inline-block;
}
/* .header__nav-link */
.header__cart {
float: right; /* 靠右對齊 */
}
口訣:選擇器若沒有規則,就先註解起來!
此外,display: inline-block 只能讓元素並排,不會改變對齊位置;要讓元素靠右需要用 float: right(傳統佈局下)。
vertical-align 有三個容易混淆的特性: w3docs
設定在子元素上,不是父元素
只對 inline 或 inline-block 元素有效
對齊基準是行盒(Line Box),不是父元素的邊界
行盒(Line Box)
┌─────────────────────────────────┐ ← line-height 決定高度
│ [logo] [nav] [cart] │ ← 三個 inline-block 元素
└─────────────────────────────────┘
步驟一:在所有並排子元素加上 vertical-align: middle
.header__logo,
.header__nav,
.header__cart {
display: inline-block;
vertical-align: middle; /* 設定在子元素,不是父元素 */
}
步驟二:在父元素設定 line-height 等於 height,撐高行盒
.header {
height: 100px;
line-height: 100px; /* 行盒高度 = 容器高度 → 子元素垂直置中 */
}
子元素過高時行盒會被撐大,對齊基準也跟著偏移,視覺上不在預期位置。防禦措施:
.header__cart-img {
max-height: 35px; /* 限制最大高度,防止撐破版面 */
height: auto;
width: auto;
}
目標元素 | 正確方法 |
|---|---|
| 在父層設 |
| 在自身設 |
margin: 0 auto 對 inline-block 無效,因為 margin: auto 只在 block formatting context 中計算。text-align: center 控制的是 inline formatting context 中的物件,而 inline-block 正是讓元素「偽裝」成行內物件,所以能被父層的 text-align 控制。 developer.mozilla
/* ✅ 正確:三張產品卡片水平置中 */
.products {
text-align: center;
}
.products__item {
display: inline-block;
}
<ul> 有瀏覽器預設的 padding-left: 40px,需要 reset:
.products__list {
padding: 0;
margin: 0;
list-style: none;
}
|
| |
|---|---|---|
層級 | HTML 內容層 | CSS 裝飾層 |
撐開容器 | (需手動設 | |
SEO/無障礙 | 有 | 無語義資訊 |
疊加文字 | 較複雜 | 直覺(搭配 |
Hero banner 使用 background-image,方便直接在容器內定位文字與按鈕。 developer.mozilla
.hero {
background-image: url("img/cover.jpg");
background-size: cover; /* 覆蓋容器,等比例裁切 */
background-position: center center;
background-repeat: no-repeat;
position: relative; /* 作為內部絕對定位元素的基準 */
height: 710px; /* background-image 不撐高,必須手動設定 */
}
<section class="hero">
<div class="hero__overlay"></div> <!-- 半透明遮罩層 -->
<div class="hero__content"> <!-- 文字與按鈕 -->
<h1 class="hero__title">Fall & Winter</h1>
<a href="#" class="hero__btn">Shop Now</a>
</div>
<p class="hero__shipping">FREE SHIPPING WORLDWIDE</p>
</section>
/* 遮罩層 */
.hero__overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 補償自身寬高的 50% */
width: 605px;
height: 190px;
background-color: rgba(255, 255, 255, 0.6);
z-index: 1; /* 遮罩在背景圖上方 */
}
/* 內容層,z-index 高於遮罩 */
.hero__content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2; /* 文字在遮罩上方 */
text-align: center;
}
/* 底部橫幅 */
.hero__shipping {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: rgb(222, 222, 222);
margin: 0;
padding: 10px 0;
text-align: center;
}
transform: translate(-50%, -50%) 原理:top: 50% 讓元素頂部對齊容器中線,但元素本身有寬高,所以要再往左上移動自身寬高的 50% 才會真正置中。 stackoverflow
.hero(position: relative)
├── background-image ← 最底層
├── .hero__overlay ← z-index: 1
├── .hero__content ← z-index: 2
└── .hero__shipping ← z-index: auto(最上層)
z-index 只對 position 不是 static 的元素生效。 w3schools
偽元素(::before/::after)與偽類(:hover/:focus)的核心差異: developer.mozilla
偽元素 | 偽類 | |
|---|---|---|
功能 | 創造新的虛擬節點 | 描述元素的狀態 |
常見例子 |
|
|
可被 JS 操作 | — |
這個層需要被 JavaScript 操作嗎?
├── 是 → 真實 DOM 元素
└── 否 → 是純視覺裝飾嗎?
├── 是 → 偽元素 ✅(::before / ::after)
└── 否(例如需要 ARIA / 點擊事件) → 真實 DOM 元素
本次遮罩選用真實 DOM,理由是尺寸為局部區域(不是全滿背景),且未來可能需要 JS 控制動態效果。
屬性 | 用途 |
|---|---|
| 圖片覆蓋容器,等比例裁切 |
| 控制背景圖位置 |
| 相對於 |
| 位移,用於水平垂直置中 |
| 含透明度的顏色,製作半透明遮罩 |
| 控制堆疊層級,只對非 |
| 控制 inline-block 兄弟元素的對齊基準 |
| 設定行盒高度,間接控制垂直置中範圍 |
| 使父層內的 inline-block 子元素水平置中 |
Share Dialog
Share Dialog
No activity yet