DEV Community

Panuwach Boonyasup
Panuwach Boonyasup

Posted on

Graceful Solution for Vertical Alignment

เนื่องจากว่าเพิ่งได้ลองใช้ 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

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

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

จุดเริ่มต้นที่เราต้องการให้เรียงกันตรงกลาง
แต่ตอนนี้ด้วย 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;

ผลลัพท์
alt text

ตัวอย่างการใช้งาน 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

Top comments (0)