Vấn đề: Full-height app với Flexbox
Khi xây dựng layout full-height (header + content + footer), content cần cuộn dọc (overflow-y: auto) trong khi header/footer cố định. Flexbox giải quyết thanh lịch.
HTML Structure
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Flexbox Full Height Layout</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
#app {
display: flex;
flex-direction: column;
min-height: 100vh; /* Quan trọng: min-height không phải height */
}
header {
background: #2c3e50;
color: white;
padding: 1rem 2rem;
flex-shrink: 0; /* Không co lại */
}
main {
flex: 1 1 auto; /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
overflow-y: auto; /* Cuộn dọc tại đây */
padding: 2rem;
background: #f8f9fa;
}
footer {
background: #34495e;
color: white;
padding: 1rem 2rem;
text-align: center;
flex-shrink: 0;
}
.content-block {
background: white;
padding: 1.5rem;
margin-bottom: 1.5rem;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div id="app">
<header>
<h1>Header - Cố định</h1>
</header>
<main>
<div class="content-block">
<h2>Nội dung 1</h2>
<p>Lorem ipsum dolor sit amet...</p>
</div>
<div class="content-block">
<h2>Nội dung 2</h2>
<p>Lorem ipsum dolor sit amet...</p>
</div>
<!-- Nhiều block để test scroll -->
</main>
<footer>
© 2024 Footer - Cố định
</footer>
</div>
</body>
</html>
Giải thích Flex Properties
main {
/* Shorthand: flex-grow | flex-shrink | flex-basis */
flex: 1 1 auto;
/* Tương đương: */
flex-grow: 1; /* Mở rộng lấp đầy không gian còn lại */
flex-shrink: 1; /* Có thể co lại nếu cần (thường không xảy ra do min-height) */
flex-basis: auto; /* Kích thước ban đầu dựa trên content */
overflow-y: auto; /* Cuộn dọc khi content cao hơn viewport */
}
Tại sao dùng min-height: 100vh thay vì height: 100vh?
height: 100vh: Ép container đúng 100vh. Nếu content ít, footer dính dưới. Nếu content nhiều, overflow ra ngoài viewport (không scroll trong main).min-height: 100vh: Container tối thiểu 100vh. Content ít → footer ở dưới cùng. Content nhiều → container mở rộng, main scroll nội bộ.
Biến thể: Sidebar + Content
<div id="app">
<header>Header</header>
<div class="layout">
<aside class="sidebar">Sidebar</aside>
<main class="content">Content scrollable</main>
</div>
<footer>Footer</footer>
</div>
<style>
.layout {
display: flex;
flex: 1;
overflow: hidden; /* Quan trọng: ngăn layout overflow */
}
.sidebar {
width: 260px;
flex-shrink: 0;
background: #f8f9fa;
border-right: 1px solid #ddd;
overflow-y: auto; /* Sidebar tự scroll nếu cần */
max-height: 100%;
}
.content {
flex: 1;
overflow-y: auto; /* Content scroll */
padding: 2rem;
}
</style>
Legacy Flexbox (2012) - Prefixes cũ
Chỉ cần nếu hỗ trợ IE10, Android Browser cũ:
#container {
display: -webkit-box; /* Old WebKit */
display: -ms-flexbox; /* IE10 */
display: -webkit-flex; /* New WebKit */
display: flex; /* Standard */
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
main {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
overflow-y: auto;
}
Lưu ý quan trọng
overflow: hiddentrên flex container cha nếu con cóoverflow: auto(tránh double scroll)flex-shrink: 0trên header/footer/sidebar cố định- Tránh
height: 100%trên flex item (gây overflow), dùngflex: 1+overflow: auto min-height: 0trên flex item nếu content có thể nhỏ hơn (fix Firefox bug)
Debug Flexbox
/* DevTools: Enable "Flexbox" badge trong Elements panel */
/* CSS Debug helper */
.flex-debug * {
outline: 1px solid rgba(255,0,0,0.1);
}
.flex-debug .flex-container {
outline: 2px solid red;
}
.flex-debug .flex-item {
outline: 2px solid blue;
}