Skip to main content

CSS Responsive กับ โจทย์แต่ละแบบ

ทีนี้เราจะลองมาดู CSS Responsive กันบ้าง

ใน CSS เองก็มีท่าที่อำนวยความสะดวกในการทำ Reponsive design ไว้อยู่แล้ว ซึ่งเพื่อให้เห็นภาพมากขึ้น ผมจะแบ่งออกเป็น 4 หัวข้อคือ

  1. Viewports (breakpoint) - media query min และ max อันเป็นแก่นของ CSS Responsive เลยก็ว่าได้ คือ คำสั่งที่ใช้สำหรับการแบ่งแต่ละขนาดหน้าจอ

  2. Fluid Layouts (flex) and Flexible Grid Systems (grid) แล้วให้ column ไม่เท่ากันในแต่ละ ขนาดหน้าจอ (ใช้ร่วมกับ media query ในข้อที่ 1.)

  3. Navigation and menu (menu bar กับ hamburger menu) ลองทำตัวอย่างประสบการณ์ที่แตกต่างกันระหว่าง mobile, desktop menu

  4. images and media (srcset and size) ใช้ภาพหลายขนาดในแต่ละขนาดหน้าจอ

1. Viewports (breakpoint) - media query

Viewports คือสิ่งที่ใช้ใน responsive design เพื่อเป็นการกำหนดขอบเขตของการใช้ CSS ในแต่ละขนาดหน้าจอ

ปกติแล้วจะมี 2 เคสคือ

  • max-width: n px คือการกำหนดว่า จากหน้าจอขนาดไม่เกิน n pixel จะใช้ css ตัวนี้แทน
  • min-width: n px คือการกำหนดว่า จากหน้าจอขนาดไม่น้อยกว่า n pixel จะใช้ css ตัวนี้แทน

เพื่อความเข้าใจที่มากขึ้นจะขอยกตัวอย่าง 2 เคส

เคสแรกคือ

  • ถ้าขนาดหน้าจอ desktop = ให้แสดงสีนำ้เงิน
  • ถ้าขนาดหน้าจอน้อยกว่า 600px = ให้แสดงสีเขียว

code CSS ก็จะหน้าตาประมาณนี้

/* Default styles that apply to all devices */
body {
background-color: lightblue;
}

/* Styles that apply to screens narrower than 600px */
@media only screen and (max-width: 600px) {
body {
background-color: lightgreen;
}
}

ผลลัพธ์ที่ได้

type-1

เคสที่ 2 เราจะทำเหมือนเคสที่ 1 แต่กลับกัน

  • ถ้าขนาดหน้าจอมากกว่า 600px = ให้แสดงสีเขียว
  • ถ้าขนาดหน้าจออื่นๆ = ให้แสดงสีน้ำเงิน
/* Default styles that apply to all devices */
body {
background-color: lightblue;
}

/* Styles that apply to screens narrower than 600px */
@media only screen and (max-width: 600px) {
body {
background-color: lightgreen;
}
}

ผลลัพธ์ที่ได้

type-2

2. Fluid Layouts (flex) and Flexible Grid Systems (grid)

ในเคสของ Flex กับ Grid เองนั้นก็มีการ handle โดยใช้ breakpoint เข้ามาช่วยได้เช่นกัน โดยเราจะแบ่งออกเป็น 2 เคสคือ

  1. Flex ใช้สำหรับแบ่ง column ซ้ายขวา และให้เรียง column ใหม่เป็น column เดียวตอนเล็กลง (ในกรณีที่จอเล็ก) = ใช้สำหรับ handle จำนวน column ตามขนาดหน้าจอ
  2. Grid ใช้สำหรับแบ่ง row, column และให้เรียงเป็น row, column ใหม่ตามขนาดหน้าจอที่เล็กลง = ใช้สำหรับ handle พวก grid ที่ต้องการ handle ทั้ง column และ row ทั้ง grid ไปพร้อมๆกัน

เรามาดูทั้ง 2 เคสผ่าน code กัน

1. Flex สำหรับแบ่ง column แบบ responsive

เรามากำหนดโจทย์กันหน่อย

  • สมมุติเรามี container ที่มี item แบ่งซ้ายขวา ออกจากกัน
  • โดยเมื่อขนาดหน้าจอเล็กกว่า 768px = ให้จากแต่เดิมแบ่ง column ซ้ายขวา ให้มาเรียงเป็น column เดียวกันแทน

สิ่งนี้สามารถทำได้โดยการใช้สิ่งที่เรียกว่า flex-direction

  • flex-direction คือ การเรียง flex แบบใหม่ โดย default ของ flex คือจะทำการเรียงเป็น row (จากซ้ายไปขวา) มาเรียงใหม่เป็นตามที่ต้องการได้ โดยเราจะมาเรียงใหม่เป็น column แทน (จากบนลงล่าง) แทน

ดูได้จากใน link นี้เพิ่มเติมเรื่อง flex-direction https://css-tricks.com/snippets/css/a-guide-to-flexbox/

และนี่ก็คือ code ของโจทย์นี้

<html lang="en">
<head>
<style>
.container {
display: flex;
}

.container .item {
padding: 10px;
flex: 1;
}

@media screen and (max-width: 768px) {
.container {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
</div>
</body>
</html>

ผลลัพธ์

type-4

2. Grid สำหรับแบ่ง row, column แบบ responsive

เรามากำหนดโจทย์กันหน่อยดีกว่า (โจทย์จะคล้ายๆกับ Flex)

  • ถ้าเป็น desktop จะใช้ grid 3 columns
  • ถ้าหน้าจอขนาดเล็กกว่า 768px จะใช้เป็น grid 2 columns
  • ถ้าหน้าจอขนาดเล็กกว่า 640px จะใช้เป็น grid 1 column

ใน Grid จะมีสิ่งที่เรียกว่า grid-template-columns ในการกำหนดจำนวน column ใน grid ได้ โดยสามารถกำหนด ratio ได้ในแต่ละ column

เราจะใช้สิ่งนี้ในการ handle column ในแต่ละขนาดหน้าจอกัน และนี้ก็คือ code ของโจทย์นี้

<html lang="en">
<head>
<style>
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}

.grid-container .item {
padding: 10px;
}

@media screen and (max-width: 768px) {
.grid-container {
grid-template-columns: 1fr 1fr;
}
}

@media screen and (max-width: 640px) {
.grid-container {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="grid-container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
</div>
</body>
</html>

ผลลัพธ์

type-5

3. Navigation and menu

สำหรับเคสนี้เราจะมาลองทำตัวอย่าง Navbar menu กันโดย

  • ฉบับ desktop จะโชว์เมนูแสดงทั้งหมดออกมาเป็นแนวนอน
  • ฉบับ mobile (ขนาดหน้าจอน้อยกว่า 768px) จะโชว์เมนูออกมาเป็นแนวตั้ง และ ให้โชว์เมนูเมื่อเอาเมาส์มาวางบนเมนู
<html lang="en">
<head>
<style>
ul {
list-style: none;
margin: 0;
padding: 0;
}
.desktop ul {
display: flex;
}
.desktop ul > li {
margin-right: 20px;
}
.mobile-menu,
.mobile {
display: none;
}
@media screen and (max-width: 768px) {
.desktop {
display: none;
}
.mobile-menu {
display: block;
}
.mobile-menu:hover + .mobile {
display: block;
}
}
</style>
</head>
<body>
<div class="desktop">
<ul>
<li>Home</li>
<li>About</li>
<li>Contact Us</li>
</ul>
</div>
<div class="mobile-menu">Menu</div>
<div class="mobile">
<ul>
<li>Home</li>
<li>About</li>
<li>Contact Us</li>
</ul>
</div>
</body>
</html>

ผลลัพธ์

type-6

4. images and media

ใน html เองก็มี tag ที่สามารถจัดการภาพแบบ responsive ได้โดย

  • มี tag <picture> และสามารถแบ่งภาพแต่ละขนาดหน้าจอได้โดยใช้ tag <source> ได้

เช่นตาม code นี้

  • ถ้าเป็น desktop เราจะใช้ภาพหนึ่ง
  • ถ้าเป็น mobile (ขนาดหน้าจอน้อยกว่า 768px) จะใช้ภาพอีกภาพหนึ่งแทน
<picture>
<source
media="(max-width: 768px)"
srcset="https://fastly.picsum.photos/id/883/200/200.jpg?hmac=evNCTcW3jHI_xOnAn7LKuFH_YkA8r6WdQovmsyoM1IY"
>
<img src="https://fastly.picsum.photos/id/23/200/200.jpg?hmac=IMR2f77CBqpauCb5W6kGzhwbKatX_r9IvgWj6n7FQ7c">
</picture>

ผลลัพธ์

type-3