Graceful Solution for Vertical Alignment
Tags: verticalalignment, webdev, flexbox, css3
Published: 2020-04-21 19:20:27

---
title: Graceful Solution for Vertical Alignment
published: true
description: 
tags: Vertical Alignment,Web Development,Flex Box,CSS3
---

เนื่องจากว่าเพิ่งได้ลองใช้ Flex Box เป็นครั้งแรกในการทำ alignment แล้วประทับใจมาก เลยอยากบอกต่อ

Flex Box เป็นชุดของ property ที่ถูกเพิ่มเข้าใน `CSS3` จุดประสงค์คือเพื่อนำมาช่วยทำให้เราสามารถจัดวาง web แบบ responsive ได้ง่ายขึ้นกว่า `layout` แบบเดิมที่ต้องมากำหนด `float` หรือ `position : absolute`

เกริ่นก่อนว่าเป็นผมเป็น developer สาย backend ครับ ซึ่งการทำ UI จัดวาง web layout เนี่ยสำหรับผมถือว่าเป็นสิ่งที่ไม่ถูกโฉลกอย่างมาก แต่ว่าเนื่องจากผมมีงานที่จำเป็นต้องใช้ความรู้ในส่วนนี้ จึงได้พยามรื้อฟื้นการวิธีทำ layout แบบต่าง และได้รู้จักกับ `Flex Box` ซึ่งช่วยเปลี่ยนชีวิตผมให้สะดวกมากขึ้น เพราะว่าอย่างแรกเลย คือมันเข้าใจง่าย แต่ละ property ของ Flex Box ทำงานแบบตรงไปตรงมาตามชื่อ อย่างที่สองคือ มันสามารถนำไปประยุกต์ใช้งานง่ายกว่า display property แบบเดิมๆ ครับโดยที่เราใช้แต่ไม่กี่ property ก็สามารถแก้ปัญหายอดฮิตของ web developer ทั้งหลายได้ เช่นการเรียงให้ `div` ให้ `vertical align` เป็นต้น
เข้าเนื้อหาครับ ทีนี้ขออธิบายก่อนว่าแต่ละ property มีอะไรยังไงบ้างนะครับ อาจจะน่าเบื่อนิดนึง สามารถข้ามไปที่ปัญหาแล้วค่อยย้อนกลับมาอ่านก็ได้ครับ

### **สำหรับ Container**

```css
display: flex
/* ใช้บอกว่าจะจัดเรียง content ในแนวไหนเป็นแกนหลัก row คือ แนวนอน column คือ
แนวตั้ง reverse คือแนวเดิมแต่กลับทางกันจาก ซ้ายไปขวาก็เป็น ขวาไปซ้าย */
flex-direction:  row-reverse, column-reverse, column, row
--------------------------------------------------------------------
/* ใช้กำหนดว่าจะจัดการ content ที่เลยไปยังไง wrap คือจะขึ้นแถวใหม่ข้างล่างตามแนว    
เดิม wrap-reverse คือขึ้นแถวใหม่ข้างบน หรือทางซ้ายถ้าแกนหลักเป็น column */
flex-wrap:  wrap, nowrap, wrap-reverse
--------------------------------------------------------------------
/* รวม flex-direction กับ flex-wrap เข้าด้วยกัน */
flex-flow: row wrap <- ตัวอย่าง
--------------------------------------------------------------------
/* flex-start จัดวาง content ทั้งหมดที่จุดเริ่มของแกนหลัก ถ้าเป็น row คือซ้ายสุด
   flex-end จัดวางที่จุดปลาย ถ้า column-reverse คือล่างขึ้นบน จุดปลายคือบน
   flex-center ให้ content ทั้งหมดกติดกันอยู่ตรงกลาง
   stretch ยืด content ตามแนว แกนหลักจนเต็ม
   space-around ให้ทั้งหมดกระจายเท่าๆกัน โดยมีเผื่อช่องว่างที่ปลายสุด2ด้านของแกนหลัก
   space-between ให้ทั้งหมดกระจายเท่าๆกัน แต่ไม่มีช่องว่างตรงปลาย
   space-evenly กระจายเท่ากันโดยที่ช่องว่างปลายสุด 2 ด้านเท่ากับระหว่าง content
*/
justify-content: flex-start,   flex-end,       center,       stretch,
                 space-around, space-evenly,   spece-between
--------------------------------------------------------------------
/* เหมือนกับ justify-content ของแกนฉาก(cross-axis) แต่ไม่สามารถ
control space ระหว่างแถว*/
align-items: center, flex-start, flex-end, baseline, stretch
--------------------------------------------------------------------
/* เหมือนกับ justify-content ของแกนฉาก
   แต่ใช้ได้แค่กรณีที่มีการ wrap ขึ้นแถวใหม่ตามแกนหลัก control space ระหว่างแถวของ      
   แกนหลักได้ */
align-content: center, flex-start, flex-end, baseline
--------------------------------------------------------------------
```


### **สำหรับ Content**
```css
flex-basis: 100px /* ขนาดเริ่มต้นก่อนย่อขยาย เหมือน width กรณี แกนหลักเป็น row   */
flex-shrink: 0    /* อัตราส่วนที่ย่อเมื่อเทียบกับ content ตัวอื่นกรณี container โดนบีบ*/
flex-grow: 0      /* อัตราส่วนที่ขยายกรณี container ขยาย 0 คือไม่เปลี่ยน         */
flex: 0 1 100px   /* รวม flex-grow flex-shrink flex-basis เข้าด้วยกัน      */
align-self        /* เหมือน align-items แต่เฉพาะตัวเอง                     */
order: -1         /* ใช้ในการจัดลำดับการแสดงผลใน list ได้เรียกจากมากไปน้อย    */
```

---

หวังว่าจะพอคุ้นหน้าคุ้นตากับ property ใหม่กันแล้วนะครับ ไปลุยปัญหากันเลยดีกว่า

> ### ปัญหา?
> ทำยังให้หลายๆ `div` อยู่ตรงกลาง `div`
> vertical align center & horizontal align center

สมมุติเรามี div 3 ก้อนอย่างงี้ เมื่อก่อนเราอาจจะใช้ margin: auto display: inline-block ทำสารพัดท่าทั้งที่ container และ item เพื่อที่ให้ก้อนทั้ง 3 ก้อนนี้เรียงกันสวยๆ กลาง container

![alt text](https://miro.medium.com/max/1400/1*p-8zVFA0n9Kn_wo91_aopg.png)

จุดเริ่มต้นที่เราต้องการให้เรียงกันตรงกลาง
แต่ตอนนี้ด้วย Flex Box เราใช้แค่ 4 property ที่ container ก็เพียงพอแล้วโดยที่แต่ละอันมีความหมายแบบตรงไปตรงมาตามนี้ครับ
1. เป็นตัวบอกว่าเราจะใช้ display แบบ flex box
 - `display: flex;`
2. เป็นตัวบอกว่า content ทั้งหมดจะอยู่รวมกันแนว row
(ให้ row เป็นแกนหลัก main-axis โดย column เป็น cross-axis แกนตั้งฉาก)
 - `flex-direction: row;`
3. เป็นตัวบอกให้ 3 ก้อนนี้จัดวางตามแกนหลัก(row) แบบมารวมกันตรงกลาง
 - `justify-content: center;`
4. อันนี้จะเป็นตัวบอกว่าจะให้จัดวางแนวแกนฉาก(column) แบบอยู่ตรงกลาง
 - `align-items: center;`

![ผลลัพท์](https://miro.medium.com/max/1456/1*YMhdz3bfb5P5cGUIa5FbLw.png)
![alt text](https://miro.medium.com/max/150/1*vHG-TiMZscnhAIFPuo1P6A.png)

### ตัวอย่างการใช้งาน Flex Box
ทีนี้สำหรับคนที่ไม่เข้าใจว่า Flex Box มันช่วยให้ง่ายขึ้นยังไง เราลองเปรียบเทียบกับ Layout แบบเก่าดู
สมมุติว่าเราต้องการทำแบบเดียวกันโดยใช้ layout แบบเก่าสิ่งที่ต้องทำมีดังนี้ครับ
1. ผมต้องเซ็ต container display เป็น table-cell และเซ็ต vertical-alignment เป็น middle เนื่องจากว่า ตัว vertical-alignment อันนี้มันมีไว้ใช้กับ กับบรรทัดเท่านั้น เราเลยต้องเซ็ต display ให้เป็นเสมือนช่องตารางที่ภายในเป็นบรรทัดเดียว

2. ผมต้องสร้าง div ใหม่มาขั้นกลางเพราะการทำ horizontal alignment center วิธีนี้ใช้ได้กับแค่ object เดียวครับ เราเลยต้องสร้าง wrapper แล้วแก้ style ของ wrapper แทน

3. ผมต้องเซ็ตตัว wrapper divให้ width เป็น fit-content และ margin เป็น auto เพื่อที่ wrapper div จะได้อยู่ตรงกลาง container และไม่มี space ภายใน wrapper div เพื่อที่ว่า div 3 ก้อนข้างในจะได้อยู่ตรงกลาง container เหมือนที่ wrapper div เป็น

4. เซ็ต display ของ item ข้างในให้เป็น inline-block ให้หมดเพื่อที่ div จะได้มาเรียงอยู่แถวเดียวกัน


เสร็จแล้วครับ ถึงแม้ว่าขั้นตอนจะไม่ยาวมากแต่ เรื่องเหตุผลของการตั้งค่าแต่ละ CSS Property น่าปวดหัวกว่า Flex Box น่าดูเลย

หวังว่า post นี้จะช่วยแก้ปัญหาให้ใครหลายคนที่กำลังมองหาวิธีการทำ alignment หรือหนักใจกับการหาวิธีจัด layout ได้นะครับ

__Reference__
-------------
- [RFC](https://www.w3.org/TR/css-flexbox-1/#flex-basis-property)
- [W3School](https://www.w3schools.com/css/css3_flexbox.asp)