Create a layout centered and stretched to full screen height
รูปแบบหน้าจอที่ใช้บ่อยและแทบจะเป็นรูปแบบเริ่มต้นที่ผมใช้บ่อยจะเป็นลักษณะนี้:
1
2
3
4
5
6
7
8
9
------------
header
------------
main
------------
footer
------------
ลองจินตนาการดูว่าในตอนแรกที่เราทำ ทุกอย่างจะไปอยู่ด้านบนหมด แน่นอนว่าหากมี content ยาวมากพอ ก็จะไม่ดูแปลกอะไร แต่หาก content สั้น footer จะลอยอยู่กลางหน้า ไม่ติดขอบล่าง
เพื่อให้ได้ในสิ่งที่ต้องการ เราจะกำหนด css พื้นฐานที่เราพยายามจะไม่อิงกับ css framework ตัวไหน ๆ เลย ก็จะได้ออกมาดังนี้:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
html {
height: 100%;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
min-height: 100dvh; /* handles mobile address bar automatically */
}
main {
flex: 1 1;
}
หลักการสั้นๆ:
display: flex+flex-direction: columnบนbodyทำให้ลูกแต่ละตัวเรียงต่อกันลงในแนวตั้งmin-height: 100dvhตั้ง min height ของ body เท่าความสูง viewport ปัจจุบัน (dvh= dynamic viewport height ที่ปรับตาม mobile address bar ให้อัตโนมัติ) บรรทัด100vhเก็บไว้เป็น fallback สำหรับ browser เก่าflex: 1 1บนmainบอกให้กินพื้นที่เหลือทั้งหมดที่ header กับ footer ไม่ได้ใช้ ดัน footer ไปติดขอบล่าง
ในโพสเดิมเคยใช้
min-height: -webkit-fill-availableเป็น workaround สำหรับ mobile viewport ตอนนี้ browser สมัยใหม่รองรับdvh/svh/lvhหมดแล้ว ใช้100dvhตรงๆ คลีนกว่า
รูปแบบ html ง่ายสุดที่เราจะใช้คือ:
1
2
3
4
5
<header>
<nav></nav>
</header>
<main></main>
<footer></footer>
ใช้ <main> แทน <div class="main"> เพราะเป็น semantic HTML5 — screen reader จับ landmark ได้ ไม่ต้องประกาศ class เพิ่ม
เมื่อเราดูผลลัพธ์ที่ออกมาจะได้ว่าส่วน main จะยืดและดันให้ header และ footer ติดขอบบนและล่าง ซึ่งในระหว่าง main กับ header และ footer เราก็สามารถที่จะแทรก section หรืออะไรที่เราอยากจะแทรกไปได้เลย:
1
2
3
4
5
6
7
<header>
<nav></nav>
</header>
<div></div>
<main></main>
<section></section>
<footer></footer>
การแสดงผลก็ยังจะเต็มหน้าจอยู่เหมือนเดิม จนว่าจะมี content มากจน main ยืดอีกไม่ได้แล้ว จากนั้นหน้าก็จะเลื่อนลงได้
ทางเลือก: CSS Grid
ถ้าชอบ grid syntax อ่านง่ายกว่าก็ใช้แทนได้:
1
2
3
4
5
6
body {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
min-height: 100dvh;
}
autoแถวแรกและแถวสุดท้าย — สูงเท่ากับ content (header กับ footer)1frตรงกลาง — กินพื้นที่เหลือทั้งหมด
HTML ใช้แบบเดียวกัน ไม่ต้องเปลี่ยน