延續 Day 14 Angular Router 的學習,這次開始實作智慧醫院管理平台的其他功能頁面。
前面幾天主要完成首頁的 HTML/CSS,包括 Header、Hero、快速服務、尋找醫師、最新公告與 Footer。
接下來希望按照 Figma 設計,逐步完成其他頁面的畫面。
這次主要開發兩個頁面:
和首頁不同,這兩個頁面主要用來呈現醫院與就醫相關資訊,因此需要處理比較多的圖片、文字、卡片與說明內容。
本次主要目標:
details、summary 建立 FAQ。這次仍然以 HTML/CSS 與畫面設計為主,其他 Angular 功能會在後續文章中繼續介紹。
在 Day 14,我開始認識 Angular Router,了解如何透過不同網址顯示對應的頁面 Component。
因此這次不再只修改首頁,而是開始製作不同功能頁面的內容。
本次主要包含:
SmartCare Hospital
│
├── Home
│
├── About
│ ├── 頁面標題
│ ├── 醫院介紹
│ ├── 醫療理念
│ ├── 醫療服務
│ └── 醫療團隊
│
└── Information
├── 頁面標題
├── 就醫流程
├── 初診須知
├── 看診前準備
├── 預約掛號須知
└── 常見問題
這次沿用既有的共用 Header,並保留不同頁面對 Footer 的設計需求。
其中醫院介紹使用包含交通、聯絡資訊與地圖的 Footer,而就醫資訊使用比較精簡的政策與版權資訊。
因為這些頁面在 Figma 中的設計並不完全相同,所以沒有強制所有頁面都使用相同的 Footer 外觀。
醫院介紹頁面主要用來呈現醫院的特色、醫療理念、服務項目與醫療團隊。
和首頁不同,這個頁面包含比較多圖文內容,因此在規劃時,需要先思考每個區塊的排列方式。
目前醫院介紹的主要結構:
醫院介紹
│
├── 頁面標題
│
├── 醫院介紹
│ ├── 院區圖片
│ └── 介紹文字
│
├── 醫療理念
│ ├── 理念一
│ ├── 理念二
│ └── 理念三
│
├── 醫療服務
│ ├── 服務卡片
│ ├── 服務卡片
│ └── 服務卡片
│
└── 醫療團隊
├── 醫師卡片
├── 醫師卡片
└── 醫師卡片
這次主要使用 CSS Grid 建立欄位,再搭配 Flexbox 調整卡片內部內容。
前面的首頁已經使用過 Grid,例如 Day 13 的 Footer。
但這次開始將 Grid 應用在更多主要內容區塊,而不只是頁尾。
首先建立醫院介紹頁面的標題區塊。
<section class="page-banner" aria-labelledby="about-title">
<h1 id="about-title">醫院介紹</h1>
<p>康智醫院SmartCare Hospital</p>
</section>
這次使用:
<h1>
作為頁面的主要標題。
而後續不同區塊使用 h2,卡片內容則可以使用 h3。
這樣可以讓頁面的標題具有清楚的層級。
另外:
aria-labelledby="about-title"
讓這個區塊可以透過指定的標題元素取得名稱。
使用 section 區分醫院介紹、醫療理念與服務等內容。
這次也使用 article 建立理念、服務及醫師卡片。
因為每張卡片都有自己的標題與內容,可以作為相對獨立的資訊項目。
醫院介紹區塊主要由院區圖片與介紹文字組成。
這次選擇將圖片放在左側、介紹文字放在右側,讓使用者可以同時看到醫院環境與相關說明。
這次醫院介紹區塊使用 CSS Grid 排列圖片與文字。
目前 CSS:
.introduction-inner {
max-width: 1200px;
margin: auto;
padding: 72px 12px 56px;
display: grid;
grid-template-columns: 452px minmax(0, 1fr);
gap: 128px;
align-items: center;
}
這次使用:
grid-template-columns: 452px minmax(0, 1fr);
將容器分成兩個欄位。
第一欄固定為 452px,主要用來放置院區圖片。
第二欄則使用剩餘的可用空間,放置醫院介紹文字。
大致的排列方式:
┌──────────────────┬─────────────────────────┐
│ │ │
│ 醫院圖片 │ 醫院介紹文字 │
│ │ │
└──────────────────┴─────────────────────────┘
這次接觸到:
minmax(0, 1fr)
minmax() 可以設定 Grid 欄位的最小值與最大值。
這裡的意思是讓第二欄可以使用剩餘空間,並允許它縮小。
相較於單純使用 1fr,這種寫法在需要控制內容溢出時很有幫助。
gap: 128px;
用來控制圖片與文字之間的距離。
這次的間距較大,是為了配合 Figma 的桌面版設計。
不過固定像素間距也需要搭配 RWD,避免較窄的畫面出現空間不足的問題。
align-items: center;
讓圖片與介紹文字在 Grid 區域中沿著交叉方向對齊。
這樣即使圖片與文字的高度不同,也能讓整體畫面保持適當的排列。
完成圖文排列後,接著調整院區圖片。
目前 CSS:
.hospital-image {
display: block;
width: 100%;
height: auto;
border-radius: 64px;
}
讓圖片寬度配合所在的容器。
讓圖片高度按照原本比例調整。
這樣可以避免同時固定寬度與高度時,造成圖片變形。
border-radius: 64px;
讓圖片呈現較大的圓角。
這次圖片圓角比前面快速服務卡片使用的 10px 更大,是因為不同區塊有不同的設計需求。
這也讓我了解到:
CSS 屬性雖然相同,但不同頁面的設計並不一定需要使用相同的數值,仍然要依照 Figma 與內容需求調整。
除了醫院介紹的圖文雙欄,這次也使用 Grid 排列醫療理念、醫療服務與醫療團隊。
目前桌面版主要採用三欄排列。
例如:
醫療理念
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 理念一 │ │ 理念二 │ │ 理念三 │
└──────────┘ └──────────┘ └──────────┘
這次和 Day 11 的快速服務有一個差異。
之前主要使用 Flexbox 排列服務卡片。
但這次使用 Grid 來控制整體的三欄結構,再透過 Flexbox 控制每張卡片內部的圖片、文字與按鈕。
例如醫療服務卡片內部,可以透過:
justify-content: space-between;
讓卡片中的內容分配適當的垂直空間。
這次開始理解:
Grid 可以負責卡片之間的欄位配置,而 Flexbox 則可以處理單張卡片內部的元素排列。
這次醫療團隊區塊有一個比較特別的設計。
醫師頭像不是完全放在卡片裡面,而是有一部分跨出卡片上緣。
為了製作這個效果,使用了負 margin。
目前 CSS:
.doctor-portrait {
display: block;
width: 216px;
height: 216px;
margin-top: -108px;
border-radius: 50%;
}
border-radius: 50%;
讓正方形的醫師圖片呈現圓形。
margin-top: -108px;
這次比較特別的是使用負數 margin。
由於醫師圖片高度為 216px,設定:
216 ÷ 2 = 108
因此透過 margin-top: -108px,讓圖片向上移動自身高度的一半。
視覺效果大致為:
O
醫師頭像
┌──────────────┐
│ │
│ 醫師姓名 │
│ 職稱與專長 │
│ │
└──────────────┘
這次沒有使用絕對定位來安排整張卡片,而是透過負 margin 達成重疊效果。
不過這個做法也需要注意卡片上方是否保留足夠空間,否則頭像可能和前面的內容重疊。
這也是後續調整 RWD 時需要一起考慮的地方。
完成醫院介紹後,接著實作就醫資訊頁面。
和醫院介紹相比,就醫資訊主要是提供使用者看診前需要了解的資訊。
目前包含:
整體結構:
就醫資訊
│
├── 頁面標題
│
├── 就醫流程
│ ├── 步驟一
│ ├── 步驟二
│ ├── 步驟三
│ └── 步驟四
│
├── 初診須知
│
├── 看診前準備
│
├── 預約掛號須知
│
└── 常見問題
這次主要需要思考:
如何將較多的文字資訊整理成容易閱讀的畫面,而不是直接放入大量段落?
因此在不同區塊使用了流程卡片、勾選清單、圓形編號與 FAQ 等設計方式。
這次就醫資訊最主要的畫面之一,是四步驟就醫流程。
桌面版使用四欄 Grid:
.flow-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
這次使用:
repeat(4, minmax(0, 1fr))
可以理解成建立四個相同設定的欄位。
相當於:
grid-template-columns:
minmax(0, 1fr)
minmax(0, 1fr)
minmax(0, 1fr)
minmax(0, 1fr);
使用 repeat() 可以讓程式碼更簡潔。
桌面版大致為:
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ 步驟一 │ → │ 步驟二 │ → │ 步驟三 │ → │ 步驟四 │
└────────┘ └────────┘ └────────┘ └────────┘
這次除了需要排列四張卡片,也希望使用箭頭連接不同步驟,讓使用者更容易理解就醫流程的順序。
因此接下來使用 CSS 偽元素建立箭頭。
這次就醫流程的箭頭不是圖片,而是透過 CSS 偽元素建立。
目前 CSS:
.flow-card {
position: relative;
min-width: 0;
}
.flow-card:not(:last-child)::after {
content: '';
position: absolute;
z-index: 1;
width: 94px;
height: 46px;
right: -86px;
top: 46%;
background: #b2e7ff;
clip-path: polygon(
0 20%,
62% 20%,
62% 0,
100% 50%,
62% 100%,
62% 80%,
0 80%
);
filter: drop-shadow(0 3px 2px #619fbe);
}
這裡有幾個之前比較少使用的 CSS 屬性。
::after
是 CSS 偽元素,可以在元素內容後方產生一個用來呈現樣式的區域。
這次使用它建立裝飾箭頭。
.flow-card:not(:last-child)::after
代表除了最後一張流程卡片之外,其他卡片都會產生箭頭。
因為最後一個步驟後面不需要再顯示下一個箭頭。
position: relative;
讓流程卡片成為箭頭定位時的參考容器。
而:
position: absolute;
則用來控制箭頭相對於卡片的位置。
clip-path: polygon(...);
這次透過 polygon() 定義圖形的裁切範圍,將原本的矩形區域裁切成箭頭形狀。
這是我在之前首頁開發中比較少接觸的 CSS 技術。
原本製作圖示時,主要使用圖片或 SVG。
這次則開始了解:
某些簡單的裝飾圖形,也可以直接透過 CSS 繪製,不一定需要額外建立圖片檔案。
不過這次只有流程箭頭使用 CSS 繪製,流程卡片中的插圖仍然是 PNG 圖片。
除了四步驟流程,就醫資訊還包含初診須知、看診前準備與預約掛號須知。
這些內容主要由文字組成,因此需要透過圖形與間距增加可讀性。
目前 CSS:
.checklist li::before {
content: '';
display: block;
flex: 0 0 28px;
width: 28px;
height: 15px;
border-left: 2px solid #484848;
border-bottom: 2px solid #484848;
rotate: -45deg;
align-self: flex-start;
margin-top: 23px;
}
這次使用 ::before,在清單項目前面產生勾選符號。
主要透過:
border-left: 2px solid #484848;
border-bottom: 2px solid #484848;
建立兩條邊框。
再搭配:
rotate: -45deg;
將圖形旋轉,形成勾選的外觀。
這次讓我發現,CSS 的 border 不只能用來畫元素邊框,也可以搭配旋轉製作簡單圖形。
預約掛號須知使用圓形數字搭配說明文字。
目前 CSS:
.booking-notes li {
display: grid;
grid-template-columns: 38px minmax(0, 1fr);
gap: 22px;
align-items: baseline;
}
這裡將每筆須知分成兩欄。
左邊是圓形編號,右邊是說明文字。
圓形編號的 CSS:
.note-number {
display: grid;
place-items: center;
width: 38px;
height: 38px;
border-radius: 50%;
background: #cff2ff;
color: #216f94;
}
其中:
place-items: center;
可以將 Grid Item 在水平與垂直方向置中。
因此不需要另外使用多個屬性,就能讓數字顯示在圓形中央。
這次就醫資訊的最後一個主要區塊是常見問題。
原本在 Figma 中,FAQ 具有點擊問題後展開答案的設計。
在實作時,使用 HTML 原生的 details 和 summary 元素。
目前主要結構:
<div class="faq-list">
<details>
<summary>常見問題標題</summary>
<p>常見問題的回答內容。</p>
</details>
</div>
這裡使用簡化的 HTML 說明結構,實際 Angular 模板則會根據資料產生 FAQ 項目。
<details>
是一種可以展開與收合內容的 HTML 元素。
<summary>
主要用來表示可以點擊的問題標題。
當使用者點擊 summary 時,瀏覽器可以直接展開或收合 details 中的其他內容。
這次比較特別的是:
FAQ 的基本展開與收合不一定需要額外撰寫 JavaScript,也可以使用 HTML 原生元素完成。
目前 FAQ 沒有限制一次只能開啟一題,因此可以同時展開多個問題。
除了使用 HTML 原生展開功能,也需要讓 FAQ 的視覺樣式符合 Figma。
這次使用 CSS 偽元素建立三角形圖示。
.faq-list summary::before {
content: '';
flex: 0 0 36px;
height: 30px;
background: currentColor;
clip-path: polygon(0 0, 100% 0, 50% 100%);
align-self: flex-start;
margin-top: 12px;
}
其中:
clip-path: polygon(0 0, 100% 0, 50% 100%);
用來建立三角形。
另外使用:
background: currentColor;
讓三角形使用目前元素的文字顏色。
當 FAQ 展開時,details 會具有 open 屬性。
因此可以使用:
.faq-list details[open] summary::before {
rotate: 180deg;
}
讓三角形旋轉。
.faq-list details[open] summary {
border-bottom: 1px solid #8bceef;
}
這樣當使用者展開問題時,問題標題下方就會出現分隔線。
這次開始理解:
CSS 不只可以透過 Hover 改變樣式,也可以根據 HTML 元素目前具有的屬性,呈現不同的視覺狀態。
這次兩個頁面都需要在不同螢幕尺寸下調整排版。
主要採用桌面版為基礎,再透過 max-width 逐步調整。
目前主要斷點包括:
1199px:縮小字體、圖片及區塊間距。899px:保留部分雙欄與三欄結構,但調整尺寸。599px:圖文介紹、理念、服務及醫療團隊改成單欄。例如桌面版:
┌───────────┬───────────┬───────────┐
│ 理念一 │ 理念二 │ 理念三 │
└───────────┴───────────┴───────────┘
手機版:
┌───────────┐
│ 理念一 │
├───────────┤
│ 理念二 │
├───────────┤
│ 理念三 │
└───────────┘
另外,醫療團隊的頭像也會配合手機版重新調整尺寸與負 margin,避免頭像和卡片之間的比例不一致。
就醫流程的 RWD 比較特別。
桌面版使用四欄:
.flow-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
當螢幕寬度小於等於 899px 時,改成兩欄:
@media (max-width: 899px) {
.flow-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 44px 48px;
}
.flow-card:nth-child(2)::after {
display: none;
}
}
而當螢幕寬度小於等於 599px 時,改成單欄:
@media (max-width: 599px) {
.flow-grid {
grid-template-columns: 1fr;
gap: 42px;
}
.flow-card:not(:last-child)::after {
display: block;
top: auto;
bottom: -38px;
rotate: 90deg;
}
}
其中:
rotate: 90deg;
讓原本水平的流程箭頭旋轉成向下的方向。
因此手機版可以呈現:
┌───────────┐
│ 步驟一 │
└───────────┘
↓
┌───────────┐
│ 步驟二 │
└───────────┘
↓
┌───────────┐
│ 步驟三 │
└───────────┘
↓
┌───────────┐
│ 步驟四 │
└───────────┘
這次讓我進一步理解:
RWD 不一定只是調整卡片大小,也可以依照裝置寬度重新安排資訊的呈現方向。
這次除了完成頁面,也在實作與驗收時遇到幾個需要調整的問題。
原本希望直接讀取 Figma,但無法取得設計內容,因此改成使用完整頁面截圖。
這次也讓我了解到,使用 AI 協助將 Figma 轉換成程式碼時,設計素材是否完整非常重要。
如果只有整頁縮圖,可能無法清楚辨識部分文字、圖片或區塊間距。
第一版建置時,醫院介紹與就醫資訊的 CSS 曾出現樣式容量警告。
當時醫院介紹約為 5.22KB,就醫資訊約為 6.04KB,超過既有的 4KB 警告門檻。
後續將部分內容拆成獨立 Component:
pages
│
├── about
├── about-team
│
├── information
├── information-flow
└── information-faq
讓不同區塊的 HTML/CSS 可以分開管理。
最終建置已沒有原本的樣式容量警告。
這次也開始理解:
Component 的拆分不只是為了讓檔案變小,更重要的是讓不同區塊具有清楚的責任,方便後續維護。
在調整桌面版理念文字時,為了讓部分文字維持單行,加入了相關 CSS 設定。
但在 1440px 畫面下,曾發生水平溢出的問題。
後續調整理念項目的 Flexbox 排列,讓圖片與文字重新對齊。
經過修改後,再次檢查已沒有原本的水平溢出問題。
這讓我發現:
有時候為了讓畫面符合 Figma 而固定文字排列,反而可能造成其他版面問題,因此仍需要搭配不同視窗尺寸進行測試。
這次和前面幾天最大的不同,是開始處理比較完整、複雜的功能頁面。
之前主要學習:
Day 11
Flexbox → 快速服務卡片
Day 12
HTML/CSS → 搜尋欄位與公告列表
Day 13
Grid → Footer 多欄版面
而這次開始進一步使用:
Day 15
│
├── Grid → 圖文雙欄與多欄卡片
│
├── Flexbox → 卡片內部排列
│
├── 負 margin → 醫師頭像重疊效果
│
├── 偽元素 → 箭頭、勾選符號與三角形
│
├── details / summary → FAQ 展開收合
│
└── Media Query → 依螢幕大小改變排列
這次也讓我發現,實際將 Figma 轉換成網頁時,不一定需要每個裝飾圖形都使用圖片。
像是流程箭頭、勾選符號與 FAQ 三角形,都可以透過 CSS 製作。
另外,不同頁面的內容需求也會影響版面設計方式。
醫院介紹比較重視圖片、文字與卡片的配置,而就醫資訊則更重視資訊的分類、閱讀順序與操作方式。
因此:
HTML/CSS 不只是將畫面排出來,而是需要根據資訊內容與使用情境,選擇適合的結構與排版方式。
本次主要學習:
minmax(0, 1fr)。repeat() 簡化 Grid 欄位設定。border-radius: 50%。::before、::after 建立裝飾圖形。clip-path: polygon() 製作箭頭與三角形。rotate 改變圖形方向。details、summary 建立 FAQ。[open] 設定展開時的 CSS 樣式。本次使用 AI 協助將 Figma 畫面轉換成 Angular HTML/CSS。
主要協助內容:
這次使用 AI 的方式主要是先提供設計畫面與需求,再讓 Codex 協助完成程式碼,最後透過測試結果確認畫面與功能。
我也希望透過整理程式碼與撰寫開發日誌,進一步理解每個 HTML 元素及 CSS 屬性的用途,而不只是完成畫面。
本次主要完成智慧醫院管理平台的醫院介紹與就醫資訊頁面。
主要包含:
實際畫面:

醫療團隊卡片:

主要包含:
實際畫面:

就醫流程 RWD 比較:
桌面版:

手機版:

FAQ 展開效果:
FAQ 收合狀態:

FAQ 展開狀態:

目前首頁、醫院介紹與就醫資訊的主要畫面已經逐步完成。
接下來預計開發智慧醫院管理平台的「醫師查詢」與「醫師詳細資訊」頁面。
這兩個頁面是後續預約掛號流程的重要入口。
下一階段主要目標:
這次仍希望先完成 Figma 到 Angular HTML/CSS 的實作,之後再集中學習醫師搜尋、科別篩選、路由參數與資料處理等 TypeScript 功能。
最後再整合 ASP.NET Core Web API 與 Oracle Database,逐步完成智慧醫院預約掛號系統。