โดยปกติแล้ว Website หรือ Application ทั่วไปจะมีการแบ่งสัดส่วนองค์ประกอบไว้อย่างชัดเจน ซึ่งการแบ่ง Layout ตาม Design ก็มักจะเป็นขั้นตอนแรก ๆ ที่เกิดขึ้น
ในการพัฒนา Website แน่นอนว่าเราต้องใช้ CSS ในการกำหนด Style ของ Component ต่าง ๆ แต่ CSS ตัวไหนถึงจะเหมาะกับการขึ้นโครง Application ของเรา ทั้งยังต้องง่ายต่อการแก้ไขในอนาคต วันนี้จึงขอเสนอหนึ่งตัวเลือกในการจัด Layout อันยอดเยี่ยม ซึ่งก็คือ CSS Display Property ที่ชื่อว่า Flexbox
ตัวอย่าง layout เบื้องต้น
ในวันนี้เราจะไม่ได้พูดถึงเนื้อหาทั้งหมดของ Flex แต่จะโฟกัสกับ Flex Properties เบื้องต้น ที่มักจะได้ใช้บ่อย ๆ ในการจัดหน้า Website ดังนี้
1 ) display: flex
2 ) flex-direction
3 ) flex: 1
1. display: flex
หลาย ๆ คนที่ต้องจับ CSS น่าจะเคยผ่าน Property Display กันมาบ้างแล้ว เพราะเป็นตัวกำหนดการแสดงผลของ HTML Element ไม่ว่าจะเป็น display: none
display: inline หรือ display: block แต่ในวันนี้เราจะมาพูดถึง display: flex กัน
หน้าที่หลัก ๆ ของ Flex คือการช่วยให้การสร้าง Flexible หรือ Responsive Layout ทำได้โดยง่าย และไม่จำเป็นต้องพึ่งพาการเซต Position
กล่าวก็คือเราสามารถทำให้ของอยู่ในจุดต่าง ๆ บนหน้าเว็บได้โดยที่ไม่จำเป็นต้องบอกตำแหน่งของมันแบบเป๊ะ ๆ โดยสิ่งที่ Flex ทำหลัก ๆ คือ การจัดเรียงของให้อยู่ในแนวเดียวกัน
มาดูกันดีกว่าว่าพอใช้จริงแล้วหน้าตามันออกมาเป็นอย่างไร
div ที่มี class box สามอันเรียงกัน
หน้าเว็บที่ได้
จะเห็นได้ว่าจาก HTML และ CSS เราจะได้สี่เหลี่ยมจัตุรัสสีเทาสามอัน ซึ่งก็จะเรียงกันลงมาเป็นปกติของ HTML
ทีนี้ถ้าเราครอบกล่องของเราด้วย flex container
ใส่ div ที่มี display flex ครอบทั้ง 3 กล่อง
หน้าเว็บที่ได้
จะเห็นได้เลยว่ากล่องของเราถูกดันขึ้นมาอยู่ในบรรทัดเดียวกันอย่างที่กล่าวไว้ข้างต้น ซึ่งเรายังสามารถกำหนดการกระจายตัวของวัตถุใน flex container ได้อีกหลากหลายแบบ
(สามารถอ่านเพิ่มเติมได้ที่ : https://www.w3schools.com/css/css3_flexbox_container.asp)
2. flex-direction
อย่างที่กล่าวไปในหัวข้อก่อนหน้าว่า flex container นั้นช่วยจัดของให้อยู่ในแนวเดียวกัน นั่นแปลว่าเราสามารถจัดให้มันอยู่ได้ทั้ง แนวตั้ง และ แนวนอน ซึ่ง Propery ที่เป็นตัวกำหนดนั้นมีชื่อว่า flex-direction ซึ่งสามารถ Set ได้สองแบบคือ row และ column
flex-direction: row เป็นการจัดของให้อยู่ด้วยกันในแนวนอน
(เป็นค่าเริ่มต้น หากไม่ใส่ flex-direction)
ผลลัพธ์ที่ได้ ไม่ต่างกับการไม่ใส่ flex-direction เพราะเป็นค่า default
flex-direction: column เป็นการจัดของให้อยู่ด้วยกันในแนวตั้ง
จะเห็นได้ว่ากล่องอยู่เรียงกันในแนวตั้ง และ ยังอยู่ภายใน flex container
.
จากผลที่ออกมา อาจจะทำให้รู้สึกว่า flex-direction: column ดูไม่น่ามีประโยชน์อะไร เพราะมันอยู่เรียงกันแบบตอนยังไม่ได้ครอบด้วย flex container แต่เราต้องไม่ลืมว่า flex container นั้น ช่วยเราในเรื่องของการวางตำแหน่งของ element ภายใน ทำให้แม้ว่าจะหน้าตาเหมือนกับในตอนแรก แต่ก็จะมีความสามารถ ในการจัดตำแหน่งที่สูงกว่ามาก ดังที่จะได้เห็นในหัวข้อถัดไป
3. flex: 1
property flex ของ Element ที่อยู่ภายใน flex container จริง ๆ แล้วใช้สำหรับกำหนด
ว่า element นั้น ๆ ควรจะยืด หดขนาดไหนในที่ว่างที่มีเหลืออยู่ หากว่าเราไม่ได้ไปกำหนดอะไรมัน ขนาดของใน flex container ก็จะมีขนาดเท่ากับค่าตั้งต้นของมัน แต่หากเราใส่ flex: 1 เข้าไป Element นั้นก็จะพยายามขยายตัวเองให้เต็มพื้นที่ในแนวแกนที่มันอยู่
(สามารถใช้ได้กับทั้ง direction row และ column)
เราจะใช้ code แบบในหัวข้อที่แล้ว แต่จะเพิ่ม class flex-1 เข้ามา
กล่องแต่ละกล่องยังมีขนาดดั้งเดิมตามที่กำหนดไว้ใน class box
เราจะลองเพิ่ม class flex-1 เข้าไปในกล่องแรกดู เพื่อจะได้ดูว่ามันยืดขนาดตัวเองออกให้เต็มพื้นที่ในแกนนอนจริงไหม
เพิ่ม class flex-1 ให้กับกล่องแรก
ขนาดของกล่องแรกยืดออกจนเต็มพื้นที่ในแกนนอน
จากตัวอย่างจะเห็นได้ว่ากล่องแรกนั้นยืดออกเองโดยที่เราไม่ต้องไปกำหนด width ให้มันใหม่เลย ซึ่งตรงจุดนี้จะมีประโยชน์มาก ๆ กับการเอาไปประยุกต์ใช้ในการทำ Layout
ในส่วนต่อไปจะเป็นตัวอย่างว่าจะเกิดอะไรขึ้นถ้าเราเพิ่ม flex-1 ให้กับกล่องอื่น ๆ
สองกล่องแรกแบ่งกันยืดออกตามพื้นที่ว่างที่มีอยู่อย่างเท่า ๆ กัน
ถ้าใส่ flex-1 ให้กับทั้งสามกล่อง แต่ละกล่องก็จะยืดออกจนเต็มพื้นที่อย่างเท่ากัน สามารถนำไปประยุกต์ใช้ในกรณีที่อยากแบ่งของให้เต็มพื้นที่และมีขนาดเท่า ๆ กันได้
ถ้าหากให้สรุปง่าย ๆ flex: 1 ก็คือการทำให้ Element นั้น ๆ ขยายขนาดจนเต็มพื้นที่ว่างที่เหลืออยู่ ซึ่ง property flex ยังมีรายละเอียดที่ลึกลงไปอีก
(สามารถอ่านเพิ่มเติมได้ที่ : https://www.w3schools.com/cssref/css3_pr_flex.php )
*Flex: 1 จะทำงานเมื่ออยู่ภายใน flex container เท่านั้น
การนำ flex ไปประยุกต์ใช้จริง
หลังจากได้รู้พื้นฐานแล้ว เราลองเอามาปรับใช้กันดีกว่า โดยที่เราจะมาลองแบ่ง Layout หน้าตาแบบนี้กัน (กำหนดให้ nav bar และ footer สูง 48 px)
ซึ่งจาก Design จะมีการกำหนด height ของ header และ footer ที่ชัดเจน
จะเหลือก็แต่ content ที่เราอยากให้มันขยายจนเต็มพื้นที่ที่เหลืออยู่
หน้าตาของ HTML ที่แบ่งเป็น 3 ส่วนตาม Design
CSS เบื้องต้น สำหรับกำหนดความสูงของ header และ footer
.
จาก CSS ด้านบน จะเห็นได้ว่าเรามีการกำหนดค่าให้ Body มีความสูง 100 vh ซึ่งหมายถึง
จะต้องสูงให้เต็มความสูงของหน้าจอ และมีการ Fix ความสูงของ class nav-bar และ footer ให้เท่ากับ 48 px ตาม Design ทีนี้ก็เหลือแค่ในส่วนของ Body ที่เราต้องจัดการ
หน้าเว็บของเราตอนนี้
ถึงตรงนี้ก็จะเป็นจุดที่พระเอกของเราจะออกโรง เราจะใช้ display: flex และ flex: 1 ในการช่วยจัดการขนาดของ content ที่อยู่ตรงกลางให้มีขนาดพอดี
โดยเราจะเริ่มจากการสร้าง flex container ขึ้นมาครอบ <div/> ทั้ง 3 ตัวของเราก่อน
และเพิ่ม display: flex กับ flex-direction: column เพื่อให้ class v-container
กลายเป็น flex box แบบแนวตั้ง และกำหนดค่า height: 100% เพื่อให้ div มีขนาดสูงเต็มหน้าจอ
เพิ่ม div class v-container เข้าไปครอบ
หน้าเว็บที่ออกมา
ในตอนนี้จะสังเกตุได้ว่า หน้าเว็บของเรา ยังมีหน้าตาเหมือนเดิมแม้ว่าจะมีการนำ div มาครอบ แต่จริง ๆ แล้วการที่เรามี flex ครอบอยู่ทำให้เราสามารถใช้ flex: 1 ได้ ซึ่งจะช่วยทำให้ content ของเรามีขนาดเต็มพอดีกับพื้นที่ที่เหลือในแนวแกนตั้ง
เพิ่ม flex: 1 ใน class content
ก็จะได้ content ที่พอดีกับพื้นที่ที่เหลือ แบบไม่ขาดไม่เกิน
ไม่ว่าเราจะย่อจอยังไง content ก็จะปรับขนาดตามแบบอัตโนมัติ
สรุปคือ flex จัดการให้หมดเลย เราแค่ต้องวางแผนก่อนว่าอะไรอยู่ตรงไหน เพียงเท่านี้
ก็จะได้ Layout ตามที่ต้องการ พร้อมด้วย HTML ที่มีโครงสร้างเรียบง่าย
และ CSS ที่ไม่รกจนเกินไป
เรามาลองดูวิธีอื่นกันบ้าง โดยในตัวอย่างนี้จะใช้ CALC ในการช่วยคำนวณความสูง
โดย CALC สามารถนำค่าต่างหน่วยมาทำการบวก ลบ คูณ หาร กันได้
ไม่จำเป็นต้องมี flex container ครอบ และ ใช้ CALC ในการคำนวณความสูง
ซึ่งจากวิธีนี้ก็จะเห็นได้ว่าผลลัพธ์นั้นไม่ต่างกัน แต่เราจำเป็นจะต้องคอยใส่เลขที่จะใช้คำนวณ
ให้ถูก ทำให้เวลามีการเปลี่ยนแปลงอาจจะจำเป็นต้องแก้ไขหลายที่ flex: 1 จึงดูเป็นตัวเลือกที่สะดวกกว่า เพราะไม่ต้องมาคอยคำนวณเอง
มาถึงตรงนี้ก็คิดว่าทุก ๆ คนน่าจะได้เห็นประโยชน์ของ flex ในการจัด Layout กันไปแล้ว ส่วนถ้าใครอยากลองฝีมือก็มีโจทย์ง่าย ๆ ให้ทุกคนได้ลองเล่นกัน
(มีเฉลยด้านล่าง อย่าเพิ่งแอบดูนะ)
จงแบ่ง Layout ตามภาพที่กำหนดด้านล่าง
- ให้ height ของ nav bar = 48px
- ให้ height ของ footer = 48px
- ให้ width ของ side bar = 220px
เฉลย
แนวคิดของการจัด Layout ด้วย flex คือ การค่อย ๆ ย่อย Design ว่าอะไรอยู่นอกสุด และแบ่งพื้นที่กันในแนวแกนไหน จากโจทย์จะเห็นได้ว่า side bar กินพื้นที่แนวนอนแบ่งกับ 3 Element ทางขวาอยู่ เราก็ควรจะทำ Flex Container ในแนวนอนก่อน แล้วค่อยไปแบ่ง nav bar, content, footer ในแนวแกนตั้งเหมือนกับตัวอย่างในหัวข้อที่แล้ว
ทำ container แนวนอน เพื่อแบ่งพื้นที่กับ container แนวตั้ง
ในวันนี้ก็หวังว่าจะพอทำให้เพื่อน ๆ ได้รู้สึกว่าการจัด Layout นั้นไม่ใช่เรื่องยากอีกต่อไป และอย่าลืมว่าเรื่องราวของ flex ยังมีสิ่งที่สามารถลงรายละเอียดได้อีกมาก เพื่อน ๆ สามารถหาอ่านต่อยอดได้อีกมากมาย แต่ในวันนี้คงต้องลากันไปก่อน หวังว่าจะได้มีโอกาสเจอกันใหม่ในวันข้างหน้าครับ
อ้างอิง
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
https://www.w3schools.com/css/css3_flexbox.asp