在前一篇文章中,我們討論了如何動態生成 Card 元件 並構建了基礎的 Service Section。今天,我們將繼續優化這個部分,重點放在如何使用 CSS Grid Layout 實現彈性且響應式的卡片佈局。CSS Grid 不僅讓我們能輕鬆處理不同螢幕尺寸下的佈局變化,還能夠與 Flexbox 互補,在每個 Card 元件內部提供精細的對齊與排列控制。
我們將展示如何使用 CSS Grid 管理整體卡片佈局,並通過 Flexbox 來簡化卡片內部內容的排列。本文會深入探討這些技術的具體應用,並解答開發中常見的佈局問題,例如 Grid 元素不對齊、如何針對不同瀏覽器進行佈局優化等。
在前端開發中,Flexbox 和 Grid Layout 是常見的佈局工具。Flexbox 更適合處理一維佈局(水平或垂直方向上的排列),而 CSS Grid 則更加靈活,能夠處理二維佈局(行和列同時控制),特別適合像 Card 元件 這樣需要根據螢幕大小調整排列方式的設計。
特點 | Grid Layout | Flexbox |
---|---|---|
適用場景 | 二維佈局(同時控制行和列) | 一維佈局(控制行或列的排列) |
設計方式 | 元素在網格中按照行和列排列 | 元素按行或列方向排列 |
靈活性 | 更加靈活,適合處理複雜佈局 | 適合簡單的線性佈局 |
佈局控制 | 同時控制行和列,適合響應式卡片佈局 | 適合單方向的內容排列,比如導航或按鈕布局 |
在我們的佈局設計中,Grid Layout 主要負責整個 Service Section 的卡片排列,而每個 Card 元件 的內部佈局則使用 Flexbox,這樣可以更有效地控制卡片內部內容的垂直與水平對齊。
在實際項目中,很多時候我們會同時使用 Grid Layout 和 Flexbox,因為它們各有不同的特點和適用場景。在這裡,我們使用 CSS Grid 來管理整個頁面中的卡片佈局,讓卡片根據螢幕尺寸動態調整列數,而在卡片內部,我們則使用 Flexbox 來簡化卡片內部的內容排列。
這樣的結合能夠讓我們在同一頁面中,既能靈活地調整整體卡片佈局,又能精細地控制卡片內部的對齊方式。
首先,我們設置 Grid Layout 來處理 ServiceSection 中卡片的排列,根據不同的螢幕尺寸靈活調整列數和間距。
// src/pages/Portfolio/ServiceSection.module.scss
@import '@/styles/variables';
// 其他樣式...
// 手機佈局:單列
.services {
display: grid;
grid-template-columns: repeat(1, minmax(180px, 1fr)); // 單列
grid-auto-rows: 1fr;
gap: 50px; // 卡片之間的間距
}
// 平板佈局:多列
@media (min-width: $breakpoint-mobile) and (max-width: $breakpoint-tablet - 1px) {
.services {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); // 自動調整列數
gap: 50px;
}
}
// 桌機佈局:三列
@media (min-width: $breakpoint-tablet) {
.services {
grid-template-columns: repeat(3, minmax(200px, 1fr)); // 三列佈局
gap: 50px;
}
}
為什麼 Grid 元素不對齊?
grid-auto-rows
為每個網格單元格設置統一的行高,這樣無論內容多少,Grid 的每個項目都會保持相同的高度。我們將使用 Flexbox 來控制卡片內部的圖標、標題、描述等內容的排列方式,確保它們能夠在垂直方向上自適應並居中對齊,保持卡片整體佈局的穩定性。
首先,為每個卡片的外層元素設置基本的 Flexbox 結構,保證卡片內的內容可以垂直排列,並根據卡片內部的內容高度自適應。
scss
複製程式碼
// 卡片外層樣式:使用 Flexbox 進行排列,適應 Mobile First
.card {
display: flex;
flex-direction: column; // 垂直排列卡片內容
justify-content: center; // 垂直居中
background-color: var(--grey-light);
padding: 1rem;
box-sizing: border-box;
position: relative;
z-index: 1;
min-height: 500px; // 卡片最小高度
}
.cardContent {
display: flex;
flex-direction: column;
justify-content: space-between; // 在頂部和底部之間平衡分佈內容
align-items: center; // 水平居中
height: 100%; // 確保卡片內容佔滿卡片高度
width: 100%;
}
這段代碼使用 Flexbox 將卡片內部的元素進行垂直排列,確保卡片內容在手機和小螢幕裝置上垂直顯示且自適應高度。
flex-grow
將卡片內容按比例分佈接下來,我們使用 Flexbox 的 flex-grow
屬性,為卡片的各個區塊(cardTitle
、cardDescription
、cardFooter
)分配不同的高度比例,確保它們在垂直方向上按比例佔用空間。
scss
複製程式碼
// 卡片標題、描述與底部的布局
.cardTitle {
flex-grow: 2; // 標題區佔據2份高度
font-size: var(--subtitle);
margin-bottom: 0.5rem;
}
.cardDescription {
flex-grow: 3; // 描述區佔據3份高度
font-size: var(--body1);
color: var(--text-primary);
margin-bottom: 1rem;
}
.cardFooter {
margin-top: 1.5rem;
flex-grow: 1; // 底部區佔據1份高度,確保底部對齊
min-height: 156px; // 保持卡片底部高度一致
.cardCategory {
font-weight: bold;
font-size: var(--subtitle);
}
.cardDetails {
font-size: var(--body1);
color: var(--text-primary);
}
}
這樣,我們可以確保卡片內的標題、描述和底部內容都能按比例自動調整,並且卡片的整體高度在各個區塊之間保持一致。
卡片之間的排版為什麼會不一致, 如下圖?
cardTitle
、cardDescription
和 cardFooter
)的高度不一致,且缺少合理的空間分配,導致卡片在垂直方向上無法統一對齊。cardTitle
、cardDescription
和 cardFooter
)設置不同的 flex-grow
值,確保它們按比例自動填充垂直空間。這樣可以使卡片內部的各區塊按預期的比例分配空間,避免卡片之間的高度不一致。min-height: 156px
來確保 cardFooter
的高度一致,同時使用 justify-content: space-between
來平衡卡片內的元素,使卡片內部各部分保持一致的間距,從而實現卡片之間的整齊對齊。在不同的螢幕尺寸下,元素之間的間距有時會顯得不協調,特別是在行動裝置上,顯示內容可能過於擁擠或過於稀疏。我們可以利用 Flexbox 的靈活性,並通過媒體查詢(media queries)調整不同設備下的佈局。具體來說,我們會使用 Flexbox 的 gap
屬性來控制元素之間的間距,並根據不同的螢幕尺寸進行響應式調整。這樣可以確保在大螢幕和小螢幕上的間距都能保持協調一致。
以下是針對 Stats Section 的具體修改方案:
@import '@/styles/variables';
.statsContainer {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
gap: 10vh;
}
@media (min-width: $breakpoint-tablet) {
.statsContainer {
flex-direction: row;
justify-content: space-around;
gap: 50px;
margin-top: 60px;
}
}
說明:
gap: 50px
),以確保畫面不會顯得太擁擠。在這篇文章中,我們成功地結合了 CSS Grid 和 Flexbox,構建了一個響應式的卡片佈局。Grid Layout 負責整體的卡片排列,而 Flexbox 則負責卡片內部的內容排列,這種結合使用提供了靈活且高效的佈局方式。
以下是最終在桌機、平板和手機上的顯示效果:
下一篇文章中,我們將深入探討 單頁應用的滾動與導航。當用戶點擊導航菜單中的不同項目時,如何平滑滾動到對應區塊,以及如何自動更新菜單狀態,這些功能將提升整體的互動性與使用體驗。如果你對這些技術感興趣,請繼續關注我們的後續文章!
✨ 流光館Luma<∕> ✨ 期待與你繼續探索更多技術知識!