Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ในบทช่วยสอนวันนี้ เราจะสร้าง Navigation Bar บนสุดด้วย HTML และ CSS เราจะดู 2 วิธี: Flexbox และ CSS Grid

จะเป็นโอกาสดีในการเปรียบเทียบความแตกต่างของทั้งสองวิธี และคุณสามารถเลือกวิธีที่ชอบได้

นี่คือลักษณะ Navigation Bar ที่เสร็จสมบูรณ์:

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

บน Desktop ลิงก์ทั้งหมดอยู่แถวเดียว Home อยู่ซ้าย ลิงก์อื่นๆ อยู่ขวา

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

บน Mobile จะมี Home บนแถวบน และลิงก์อื่นๆ บนแถวล่าง ลิงก์จะจัดกึ่งกลางหน้า

เริ่มต้นด้วยการตั้งค่าไฟล์

ตั้งค่าไฟล์

เพื่อสร้าง Navigation เราจะสร้างไฟล์ index.html และ style.scss ซึ่งจะคอมไพล์เป็น style.css ด้วย extension VS Code Live Sass

ในส่วน <head> เราจะเพิ่ม element <link> โหลด style.css

เริ่มสร้าง Navigation Bar กันเลย!

สร้าง HTML Markup

ใน index.html ให้สร้าง HTML markup สำหรับ Navigation ผมพยายามใช้ Semantic HTML tags มากที่สุด เพื่อหลีกเลี่ยงการใช้แค่ div

เราจะสร้าง element <nav> ที่จะ contain ลิงก์นำทางทั้งหมด แล้ววางลิงก์ใน unordered list <ul> เช่นนี้:

<nav> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Blog</a></li> <li><a href="#">Contact</a></li> </ul> </nav>

นี่คือ markup พื้นฐานสำหรับ Navigation เราจะปรับแต่งเมื่อสร้าง Flexbox และ Grid versions แต่เริ่มต้นด้วยการสร้าง 2 ชุดของ element <nav> นี้

หากโหลด index.html ในเบราว์เซอร์ จะดูพื้นฐานมาก

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ไม่ต้องกังวล! เริ่มเพิ่มสไตล์ใน style.scss กันเลย

เริ่มเพิ่ม Global Styles และ Media Queries

ขั้นแรก ผมเพิ่ม global styles ที่ใช้บ่อย:

html { font-size: 100%; box-sizing: border-box; } body { margin: 0px; padding: 0px; min-height: 100vh; } *, *::before, *::after { box-sizing: inherit; }

เพิ่มเติม ให้สีสันน่าสนใจขึ้น ในแท็ก <body> ตั้ง background-color: #1b1b1b และให้ทุก element และลิงก์ <a> เป็นสีขาว color: #ffffff เพื่อธีมมืด

สำหรับ element <ul> ใน <nav>: เพิ่ม list-style-type: none ซ่อน bullet และตั้ง margin padding เป็น 0px

เพิ่ม padding ให้ <nav> ด้วย padding: 10px และเพิ่ม padding สำหรับ tablet/desktop ด้วย media query:

nav { padding: 10px; @media (min-width: 600px){ padding: 20px; } }

ดูดีขึ้นแล้ว! แทนฟอนต์ serif เริ่มต้น ผมอยากใช้ Google Font Open Sans

นำเข้า font family เข้า style.scss โดยเพิ่มบรรทัดนี้บนสุด:

@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); 

ในสไตล์ <body> ตั้ง font-family: 'Open Sans', Arial, Helvetica, sans-serif โหลด Open Sans หรือ fallback font

ทำให้ link styles น่าสนใจขึ้น

ลบ underline เริ่มต้นด้วย text-decoration: none ให้ element <a> และแทนด้วย underline สีชมพูหนาขึ้นด้วย border-bottom พร้อมสร้าง gradient underline เมื่อ hover สีชมพูไปม่วง

สำหรับสี ผมชอบสร้าง Sass variables บนสุดของ style.scss ใต้ @import เพิ่ม:

$linkPink: rgb(216, 29, 216); $linkPurple: rgb(98, 16, 250);

ตัวแปรจะทำให้ง่ายขึ้นเวลาเพิ่มสีในสไตล์อื่นๆ

ตอนนี้ สร้าง underline หนาด้วย pseudo-element ของ <a> ให้มี bottom border

โค้ด:

a { position: relative; text-decoration: none; } a::before { content: ""; position: absolute; height: 3px; right: 0px; bottom: -3px; left: 0px; background-color: $linkPink; }

ที่นี่เราทำให้ ::before pseudo-element สูง 3px พื้นหลังสีชมพู เพื่อจัดตำแหน่งด้านล่าง ตั้ง position: absolute และให้ <a> มี position: relative เพื่อไม่ให้บินขึ้นไป (อธิบายเพิ่มเติม ที่นี่)

จัดตำแหน่ง pseudo-element ใต้ข้อความด้วย bottom: -3px เว้นช่องว่างเล็กน้อยระหว่างข้อความลิงก์และเส้น และให้เส้นขยายเต็มความกว้างของลิงก์ด้วย left: 0px และ right: 0px

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ลิงก์ดูสวยขึ้นแล้ว!

Linear Gradient Hover Style

เพิ่ม hover effect ให้ underline เปลี่ยนเป็น gradient สีชมพูไปม่วง และข้อความลิงก์เปลี่ยนจากขาวเป็นชมพูเมื่อ hover

ใช้ selector a:hover พร้อมสไตล์:

a:hover { color: $linkPink; &::before { background: linear-gradient(to right, $linkPink 40%, $linkPurple 75%); } }

สำหรับ ::before พื้นหลังเปลี่ยนเป็น linear-gradient ในฟังก์ชัน gradient ระบุให้เปลี่ยนจากชมพูไปม่วงเมื่อเคลื่อนจากซ้ายไปขวา

ควบคุมจุดเปลี่ยนสีด้วยเปอร์เซ็นต์ ต้องการสีชมพูแรกจาก 0% (ซ้ายสุด) ถึง 40% ความกว้าง และสีม่วงที่สองจาก 100% (ขวาสุด) ถึง 75% ความกว้าง จะมี gradient ระหว่าง 40% ถึง 75% ของความกว้าง element

ยังเปลี่ยนสีข้อความลิงก์เป็นชมพูเมื่อ hover

ตอน hover ลิงก์จะลักษณะ:

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ดู fancy ขึ้นใช่ไหม?

ตอนนี้เราเสร็จ global styles ที่ใช้สำหรับ Flexbox และ Grid navigation bars ทั้งสอง

เริ่มเขียนสไตล์สำหรับ Flexbox Navigation กันเลย

Flexbox Navigation

ผมมักเริ่มเขียน Desktop styles ก่อน แล้วค่อย Mobile เพราะ Desktop มักซับซ้อนกว่ามีหลายคอลัมน์ ส่วน Mobile มัก stack เป็นคอลัมน์เดียว แต่คุณเขียนลำดับไหนก็ได้

ใน Desktop Navigation เราต้องการ Home link ซ้าย และลิงก์รอง 3 ตัวขวา

เพื่อทำได้ด้วย Flexbox ต้องแบ่งลิงก์ 2 กลุ่ม: กลุ่มซ้ายและกลุ่มขวา ทั้งคู่จะเป็น flex children ของ flex parent

กลับไปที่ HTML markup เราต้องการ <nav> เป็น flex parent ดังนั้นย้าย Home link ออกจาก <ul> ทำให้เป็น direct child ของ <nav>

ลิงก์อื่นๆ อยู่ใน <ul> ต่อ

เพิ่ม class "flexbox" ให้ <nav> แยกสไตล์ flexbox จาก grid styles

Markup ที่อัปเดต:

<nav class="flexbox"> <a href="#">Home</a> <ul> <li><a href="#">About</a></li> <li><a href="#">Blog</a></li> <li><a href="#">Contact</a></li> </ul> </nav>

เพิ่ม Flexbox Styles สำหรับ Desktop

ตอนนี้ ใน Navigation เราเปิด Flexbox โดยตั้ง nav.flexbox เป็น display: flex เพิ่ม justify-content: space-between วางกลุ่มแรกซ้าย กลุ่มอื่นขวา

ทำ <ul> เป็น flex parent อีกทีด้วย display: flex และ justify-content: flex-end จัดลิงก์ขวา เพิ่ม align-items: center; จัดกึ่งกลางแนวตั้ง flex children

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ดูดีขึ้น!

ตอนนี้เราต้องการลิงก์รอง 3 ตัวติดกันใน Flexbox ดังนั้นทำ <ul> เป็น flex parent ของ 3 ลิงก์ ตั้ง align-items: center เพิ่มระยะห่างระหว่างลิงก์ด้วย margin-right: 20px แต่ทำเป็น 0px สำหรับ selector :last-child เพื่อไม่ให้ลิงก์สุดท้ายมีระยะว่างเกิน

Desktop styles ตอนนี้:

nav.flexbox { display: flex; justify-content: space-between; align-items: center; ul { display: flex; align-items: center; } ul li { margin-right: 20px; &:last-child { margin-right: 0px; } } }

Navigation Bar จะลักษณะ:

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

เพิ่ม Flexbox Styles สำหรับ Mobile

เพิ่ม Mobile Styles ขั้นแรก จัดกึ่งกลาง flex content บน Mobile

ตอนนี้บน Mobile Home link จัดซ้ายเพราะ justify-content: space-between ของ flex parent

จัดกึ่งกลางได้โดยย้าย style rule นั้นเข้า media query สำหรับความกว้างใหญ่ แล้วตั้ง justify-content เป็น center สำหรับ Mobile

ต่อไป ต้องการลิงก์รอง 3 ตัว wrap ไปแถวใหม่ เพิ่ม flex-wrap: wrap ให้ selector nav.flexbox เพื่อเปิด wrapping

Styles ควรเป็น:

nav.flexbox { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; @media (min-width: 600px){ justify-content: space-between; } }

เพื่อบังคับ wrapping เราจะทำให้ <ul> flex child กินความกว้าง 100% จึงต้องเลื่อนใต้ Home link

ผมชอบ helper classes เพิ่ม class "fullwidth" ให้ <ul> สร้าง style rules สำหรับ .fullwidth ใน rule nav.flexbox

ตั้ง flex: 1 0 100% คุณสมบัติ flex เป็น shorthand ของ flex-grow, flex-shrink, flex-basis

อนุญาตให้ grow ถ้าจำเป็น flex-grow 1 ไม่อนุญาต shrink flex-shrink 0 ตั้งความกว้างเริ่มต้น 100% ด้วย flex-basis

จัดกึ่งกลางลิงก์ใน flex parent บน Mobile ด้วย justify-content: center

แต่ไม่ต้องการลิงก์รอง fullwidth และ centered บน Tablet/Desktop สำหรับความกว้างใหญ่ ต้องการ flex เป็น 0 1 auto ไม่ grow สามารถ shrink ได้ ความกว้างเริ่มต้นเป็น natural width ของเนื้อหา

เพิ่ม media query สำหรับ Desktop Styles:

.fullwidth { flex: 1 0 100%; justify-content: center; @media (min-width: 600px){ flex: 0 1 auto; } }

อาจเขียน max-width media query เพื่อ target style rules แรกเฉพาะ Mobile แต่ผมชอบใช้ Mobile style rules เป็นค่าเริ่มต้น แล้วค่อยเพิ่ม min-width media queries ขึ้นเรื่อยๆ เพื่อหลีกเลี่ยง conflict

ขึ้นอยู่กับคุณชอบ media query แบบไหน แต่อย่างไรก็ตามแนะนำเลือกแบบเดียว (min หรือ max) ใช้ส่วนใหญ่

สำหรับลิงก์รอง 3 ตัว ผมอยากตั้ง width ให้ข้อความ "Blog" จัดกึ่งกลางใต้ "Home" ตอนนี้จัดกึ่งกลางตามความกว้างรวมของแถวที่สอง แต่เพราะ "Contact" ยาวกว่า "About" จุดกึ่งกลางของแถวเลยขวาของ "Blog" เล็กน้อย

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

แก้โดยทำให้ flex child column แต่ละตัวในแถวที่สอง มี static width เท่ากัน 100px ตั้ง flex เป็น 0 0 100px จัดข้อความกึ่งกลาง ต้องการเฉพาะ Mobile ยกเลิกสำหรับ Desktop ตั้ง flex เป็น 0 0 auto

ลดระยะห่างระหว่าง item Mobile เป็น 10px คง 20px สำหรับ Desktop

โค้ดทั้งหมด:

ul li { flex: 0 0 100px; margin-right: 10px; text-align: center; @media (min-width: 600px){ flex: 0 0 auto; margin-right: 20px; } &:last-child { margin-right: 0px; } }

การปรับแต่งสุดท้าย เพิ่มระยะห่างระหว่าง Home link แรก และลิงก์รอง 3 ตัวด้วย margin-bottom สำหรับ Mobile เขียน style rule target element <a> ที่เป็น direct child ของ nav.flexbox parent เพื่อให้เฉพาะ Home link ได้ผล

nav.flexbox { > a { margin-bottom: 10px; @media (min-width: 600px){ margin-bottom: 0px; } } }

Mobile Navigation จะลักษณะนี้ (เปิด Firefox Flexbox Inspector ดูเส้นคอลัมน์):

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

เสร็จแล้วสำหรับ Flexbox Navigation! ไปสร้างด้วย CSS Grid ต่อ

CSS Grid Method

ความแตกต่างหลักระหว่าง Flexbox และ Grid คือ Flexbox จัดเรียงคอลัมน์/แถวโดย flex properties บน flex children ใน property flex และ flex parent ตั้ง wrap หรือไม่ Flexbox เป็น "content-first" approach

CSS Grid เป็น "grid-first" approach คุณออกแบบ Grid Template (คอลัมน์/แถว) ด้วย grid properties ใน parent element และควบคุมตำแหน่ง grid children ใน template ได้แต่ละตัว

ด้วยการควบคุมระดับรายตัว ใน Grid Navigation Bar เราสามารถวางลิงก์ทั้งหมดรวม Home link ใน parent <ul> เดียวกัน

<nav class="grid"> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Blog</a></li> <li><a href="#">Contact</a></li> </ul> </nav>

เพิ่ม Grid Styles สำหรับ Mobile

เปลี่ยนวิธีกับ Grid Navigation เริ่มเขียน Mobile Styles ก่อน!

บน Mobile ต้องการ Home link แถวแรก กิน 100% ความกว้าง แล้วลิงก์รอง 3 ตัวแถวที่สอง จัดกึ่งกลาง

ใน <ul> grid parent element เราเปิด Grid ด้วย display: grid

ออกแบบ Grid Template มีลิงก์ 3 ตัวแถวที่สอง สร้าง 3-column template

อยากให้คอลัมน์กว้างเท่ากัน แต่ไม่กว้างเกินไป ตั้ง grid-template-columns: repeat(3, 100px) บน <ul> grid parent

ใช้ฟังก์ชัน repeat() สร้าง 3 คอลัมน์ กว้าง 100px

คุณสมบัติมีประโยชน์ของ CSS Grid คือสร้าง gutters (ช่องว่าง) ระหว่าง grid items แทนที่จะต้องเพิ่ม margin ให้ grid children เหมือน Flexbox ใช้ grid-gap: 10px แทน

จัดกึ่งกลาง grid ทั้งหมดด้วย justify-content: center และจัดข้อความในแต่ละคอลัมน์กึ่งกลางด้วย justify-items: center

เปิด Firefox Grid Inspector (เก่งมาก ลองดูสิ) Grid จะลักษณะ:

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

เห็น 3 คอลัมน์กึ่งกลางชัดเจน แต่ Home link ต้องอยู่แถวเดียว กิน 3 คอลัมน์

ทำได้โดยใช้ helper class อีกครั้ง เพิ่ม class "fullwidth" ให้ element <li> ของ Home

ในสไตล์ ให้ selector .fullwidth rule grid-column: 1 / 4 ทำให้ grid child column เริ่มที่ grid line แนวตั้งแรก และขยายถึง grid line ที่ 4 ท้ายสุด

ลักษณะ (เปิด line numbers ดูการ編號):

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

เพิ่ม Grid Styles สำหรับ Desktop

สำหรับ Desktop ต้องการลิงก์ทั้งหมดแถวเดียว Home ซ้าย ลิงก์อื่น 3 ตัวขวา

อยากให้ 3 คอลัมน์สุดท้าย ขนาดตามเนื้อหา เพื่อให้ระยะห่างระหว่างลิงก์เท่ากัน

ทั้งหมดนี้หมายถึงต้องเปลี่ยน Grid Template สำหรับความกว้างใหญ่ด้วย Media Query

ควรเปลี่ยน Template เป็นอะไร? ต้องการลิงก์ทั้งหมดแถวเดียว ต้องการ 4-column grid

เริ่มต้นเปลี่ยน grid-template-columns จาก repeat(3, 100px) เป็น repeat(4, 100px) บน Grid Parent สำหรับความกว้างมากกว่า 600px

จะสร้าง 4 คอลัมน์ แล้วค่อยปรับต่อ

อัปเดตสไตล์ .fullwidth ให้กิน 1 คอลัมน์บน Desktop grid-column: 1 / 2 ทำให้คอลัมน์ Home แรก ขยายจาก grid line 1 ถึง 2

ตอนนี้เป็น:

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ลิงก์อยู่ 4 คอลัมน์ แต่กว้าง 100px ทุกคอลัมน์ จึงแค่จัดกึ่งกลางหน้า

เพื่อให้ Home link แรกอยู่ซ้ายสุด ต้องทำให้ Grid เองกิน 100% ความกว้างหน้า ทำได้โดยให้คอลัมน์แรกใน Grid Template กินพื้นที่ว่าง

เปลี่ยน grid-template-columns เป็น 1fr repeat(3, 100px) จะคง 3 ลิงก์รองไว้ 100px คอลัมน์แรกกินพื้นที่ที่เหลือ

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ใกล้แล้ว! แต่เพื่อให้ 3 คอลัมน์สุดท้ายกว้างตามเนื้อหา ใช้ฟังก์ชัน fit-content() ถ้าตั้ง 3 คอลัมน์สุดท้ายเป็น fit-content(50px) คอลัมน์จะปรับขนาดตามเนื้อหา

grid-template-columns สำหรับ Desktop จะเป็น 1fr repeat(3, fit-content(50px))

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

ความกว้างคอลัมน์ดูดีแล้ว!

ปรับการจัดข้อความลิงก์ในคอลัมน์ ตอนนี้จัดกึ่งกลางเพราะ justify-items: center สำหรับ Mobile

เปลี่ยนสำหรับ Desktop เป็น justify-items: end จัดลิงก์ขวา แล้วจัด Home link ซ้ายด้วย justify-self: start สำหรับ selector .fullwidth

ตอนนี้เห็น Desktop Navigation สำหรับ Grid เสร็จแล้ว ตรงกับ Flexbox Navigation:

วิธีสร้าง Responsive Navigation Bar (Flexbox vs CSS Grid)

Flexbox หรือ Grid?

ในการสร้าง Navigation นี้ Flexbox Styles ใช้ 46 บรรทัดใน style.scss และ HTML Markup ซับซ้อนกว่า

Grid Styles ใช้เพียง 24 บรรทัด! ส่วนใหญ่ต่างกันที่ Flexbox ต้องเพิ่ม margin-bottom และ margin-right สำหรับระยะห่าง Grid จัดการหมดด้วย grid-gap

ผมชอบโค้ดที่เบามากของ CSS Grid แต Flexbox ยังเป็นตัวเลือกดีหากคุณคล่องกับ Flexbox!

ดู Source Code ได้ ที่นี่ บน Codepen