Global vs. Local Styling ใน Next.js
เผยแพร่แล้ว: 2022-03-10ฉันมีประสบการณ์ที่ยอดเยี่ยมในการใช้ Next.js เพื่อจัดการโครงการส่วนหน้าที่ซับซ้อน Next.js มีความคิดเห็นเกี่ยวกับวิธีการจัดระเบียบโค้ด JavaScript แต่ไม่มีความคิดเห็นในตัวเกี่ยวกับวิธีการจัดระเบียบ CSS
หลังจากทำงานภายในเฟรมเวิร์กแล้ว ฉันได้พบชุดรูปแบบการจัดองค์กรที่ฉันเชื่อว่าทั้งสองสอดคล้องกับปรัชญานำทางของ Next.js และปฏิบัติตามแนวทางปฏิบัติ CSS ที่ดีที่สุด ในบทความนี้ เราจะสร้างเว็บไซต์ (ร้านน้ำชา!) ร่วมกันเพื่อแสดงรูปแบบเหล่านี้
หมายเหตุ : คุณอาจไม่จำเป็นต้องมีประสบการณ์ Next.js มาก่อน แม้ว่าจะมีความเข้าใจพื้นฐานเกี่ยวกับ React และเปิดใจเรียนรู้เทคนิค CSS ใหม่ๆ บ้างก็ดี
การเขียน CSS แบบ “ล้าสมัย”
เมื่อดู Next.js เป็นครั้งแรก เราอาจต้องพิจารณาใช้ไลบรารี CSS-in-JS บางประเภท แม้ว่าอาจมีประโยชน์ขึ้นอยู่กับโปรเจ็กต์ แต่ CSS-in-JS ก็มีข้อควรพิจารณาทางเทคนิคมากมาย ต้องใช้ไลบรารีภายนอกใหม่ ซึ่งจะเพิ่มขนาดของบันเดิล CSS-in-JS ยังสามารถมีผลกระทบต่อประสิทธิภาพโดยทำให้เกิดการเรนเดอร์และการพึ่งพาสถานะโกลบอลเพิ่มเติม
การอ่านที่แนะนำ : “ The Unseen Performance Costs of Modern CSS-in-JS Libraries In React Apps)” โดย Aggelos Arvanitakis
ยิ่งไปกว่านั้น จุดรวมของการใช้ไลบรารีอย่าง Next.js คือการแสดงเนื้อหาแบบสแตติกทุกครั้งที่ทำได้ ดังนั้นจึงไม่สมเหตุสมผลเลยที่จะเขียน JS ที่ต้องเรียกใช้ในเบราว์เซอร์เพื่อสร้าง CSS
มีคำถามสองสามข้อที่เราต้องพิจารณาเมื่อจัดรูปแบบภายใน Next.js:
เราจะเข้ากับอนุสัญญา/แนวปฏิบัติที่ดีที่สุดของกรอบงานได้อย่างไร?
เราจะสร้างสมดุลระหว่างความกังวลเกี่ยวกับสไตล์ "โดยรวม" (แบบอักษร สี เลย์เอาต์หลัก และอื่นๆ) กับสไตล์ "ในพื้นที่" (สไตล์เกี่ยวกับส่วนประกอบแต่ละรายการ) ได้อย่างไร
คำตอบที่ฉันคิดสำหรับคำถามแรกคือการ เขียน CSS แบบ เก่าที่ดี Next.js ไม่เพียงแต่รองรับการทำเช่นนั้นโดยไม่ต้องตั้งค่าเพิ่มเติม ยังให้ผลลัพธ์ที่มีประสิทธิภาพและคงที่
ในการแก้ปัญหาที่สอง ฉันใช้แนวทางที่สามารถสรุปได้เป็นสี่ส่วน:
- โทเค็นการออกแบบ
- สไตล์สากล
- คลาสยูทิลิตี้
- รูปแบบส่วนประกอบ
ฉันเป็นหนี้บุญคุณความคิดของ Andy Bell เกี่ยวกับ CUBE CSS (“องค์ประกอบ ยูทิลิตี้ บล็อก ข้อยกเว้น”) ที่นี่ หากคุณไม่เคยได้ยินหลักการขององค์กรนี้มาก่อน เราขอแนะนำให้คุณตรวจสอบเว็บไซต์อย่างเป็นทางการหรือคุณสมบัติใน Smashing Podcast หลักการหนึ่งที่เราจะนำมาจาก CUBE CSS คือแนวคิดที่เราควร ยอมรับ มากกว่าที่จะกลัว CSS cascade มาเรียนรู้เทคนิคเหล่านี้โดยนำไปใช้กับโครงการเว็บไซต์
เริ่มต้น
เราจะสร้างร้านน้ำชาเพราะว่าชาก็อร่อย เราจะเริ่มต้นด้วยการเรียกใช้งาน yarn create next-app
เพื่อสร้างโครงการ Next.js ใหม่ จากนั้น เราจะลบทุกอย่างใน styles/ directory
(เป็นโค้ดตัวอย่างทั้งหมด)
หมายเหตุ : หากต้องการติดตามผลงานที่ทำเสร็จแล้ว สามารถตรวจสอบได้ที่นี่
โทเค็นการออกแบบ
ในการตั้งค่า CSS แทบทุกประเภท จะมีประโยชน์ที่ชัดเจนในการ จัดเก็บค่าที่ใช้ร่วมกันทั้งหมดไว้ในตัวแปร หากลูกค้าขอให้เปลี่ยนสี การนำการเปลี่ยนแปลงไปใช้นั้นเป็นเพียงขั้นตอนเดียว แทนที่จะเป็นปัญหาในการค้นหาและแทนที่ ดังนั้น ส่วนสำคัญของการตั้งค่า Next.js CSS ของเราจะจัดเก็บค่าทั่วทั้งไซต์เป็น โทเค็นการออกแบบ
เราจะใช้คุณสมบัติที่กำหนดเอง CSS ในตัวเพื่อจัดเก็บโทเค็นเหล่านี้ (หากคุณไม่คุ้นเคยกับรูปแบบนี้ คุณสามารถดู "คู่มือกลยุทธ์สำหรับคุณสมบัติที่กำหนดเองของ CSS" ได้) ฉันควรพูดถึงว่า (ในบางโครงการ) ฉันเลือกใช้ตัวแปร SASS/SCSS เพื่อจุดประสงค์นี้ ฉันไม่พบข้อได้เปรียบที่แท้จริงใดๆ เลย ดังนั้นฉันมักจะรวม SASS ไว้ในโปรเจ็กต์หากพบว่าฉันต้องการฟีเจอร์ SASS อื่นๆ (มิกซ์-อิน การวนซ้ำ การนำเข้าไฟล์ และอื่นๆ) ในทางตรงกันข้าม คุณสมบัติที่กำหนดเองของ CSS ยังทำงานกับ cascade และสามารถเปลี่ยนแปลงได้เมื่อเวลาผ่านไป แทนที่จะคอมไพล์แบบสแตติก ดังนั้น สำหรับวันนี้ เรามาติด CSS ธรรมดา กัน
ในไดเร็กทอรี styles/
ของเรา มาสร้างไฟล์ design_tokens.css ใหม่:
:root { --green: #3FE79E; --dark: #0F0235; --off-white: #F5F5F3; --space-sm: 0.5rem; --space-md: 1rem; --space-lg: 1.5rem; --font-size-sm: 0.5rem; --font-size-md: 1rem; --font-size-lg: 2rem; }
แน่นอน รายการนี้สามารถและจะเติบโตเมื่อเวลาผ่านไป เมื่อเราเพิ่มไฟล์นี้แล้ว เราต้องข้ามไปที่ไฟล์ pages/_app.jsx ซึ่งเป็นเลย์เอาต์หลักสำหรับเพจทั้งหมดของเรา และเพิ่ม:
import '../styles/design_tokens.css'
ฉันชอบคิดว่าโทเค็นการออกแบบเป็นกาวที่รักษาความสม่ำเสมอทั่วทั้งโครงการ เราจะอ้างอิงตัวแปรเหล่านี้ในระดับโลก เช่นเดียวกับภายในส่วนประกอบแต่ละส่วน เพื่อให้มั่นใจว่าภาษาการออกแบบที่เป็นหนึ่งเดียว
สไตล์สากล
ถัดไป มาเพิ่มหน้าเว็บไซต์ของเรากันเถอะ! ไปที่ไฟล์ pages/index.jsx กัน (นี่คือหน้าแรกของเรา) เราจะลบต้นแบบทั้งหมดและเพิ่มบางอย่างเช่น:
export default function Home() { return <main> <h1>Soothing Teas</h1> <p>Welcome to our wonderful tea shop.</p> <p>We have been open since 1987 and serve customers with hand-picked oolong teas.</p> </main> }
น่าเสียดายที่มันจะดูค่อนข้างธรรมดา เรามากำหนด สไตล์โกลบอลสำหรับองค์ประกอบพื้นฐานกัน เช่น แท็ก <h1>
(ฉันชอบคิดว่ารูปแบบเหล่านี้เป็น "ค่าเริ่มต้นทั่วโลกที่สมเหตุสมผล") เราอาจลบล้างได้ในบางกรณี แต่เป็นการคาดเดาที่ดีว่าเราต้องการอะไรหากไม่ต้องการ
ฉันจะใส่สิ่งนี้ในไฟล์ styles/globals.css (ซึ่งมาโดยค่าเริ่มต้นจาก Next.js):
*, *::before, *::after { box-sizing: border-box; } body { color: var(--off-white); background-color: var(--dark); } h1 { color: var(--green); font-size: var(--font-size-lg); } p { font-size: var(--font-size-md); } p, article, section { line-height: 1.5; } :focus { outline: 0.15rem dashed var(--off-white); outline-offset: 0.25rem; } main:focus { outline: none; } img { max-width: 100%; }
แน่นอนว่าเวอร์ชันนี้ค่อนข้างพื้นฐาน แต่ไฟล์ globals.css ของฉันไม่จำเป็นต้องมีขนาดใหญ่เกินไป ที่นี่ ฉันจัดรูปแบบองค์ประกอบ HTML พื้นฐาน (ส่วนหัว เนื้อหา ลิงก์ และอื่นๆ) ไม่จำเป็นต้องห่อองค์ประกอบเหล่านี้ในส่วนประกอบ React หรือเพิ่มคลาสอย่างต่อเนื่องเพื่อจัดเตรียมรูปแบบพื้นฐาน
ฉันยังรวมการ รีเซ็ตสไตล์เบราว์เซอร์เริ่มต้น ด้วย ในบางครั้ง ฉันจะมีรูปแบบเลย์เอาต์ทั่วทั้งไซต์เพื่อให้มี "ส่วนท้ายที่เหนียว" แต่จะอยู่ที่นี่ก็ต่อเมื่อทุกหน้าใช้เลย์เอาต์เดียวกัน มิเช่นนั้นจะต้องกำหนดขอบเขตไว้ภายในส่วนประกอบแต่ละส่วน
ฉันมักจะใส่ :focus
styling เพื่อ ระบุ องค์ประกอบเชิงโต้ตอบสำหรับผู้ใช้คีย์บอร์ดอย่างชัดเจนเมื่อโฟกัส ทางที่ดีควรทำให้มันเป็นส่วนสำคัญของ DNA การออกแบบของไซต์!
ตอนนี้เว็บไซต์ของเรากำลังเริ่มเป็นรูปเป็นร่าง:
คลาสยูทิลิตี้
พื้นที่หนึ่งที่หน้าแรกของเราสามารถปรับปรุงได้อย่างแน่นอนคือข้อความจะขยายออกไปที่ด้านข้างของหน้าจอเสมอ ดังนั้นเรามาจำกัดความกว้างของข้อความกันเถอะ เราต้องการเลย์เอาต์นี้ในหน้านี้ แต่ฉันคิดว่าเราอาจต้องการเลย์เอาต์นี้ในหน้าอื่นด้วย นี่เป็นกรณีการใช้งานที่ยอดเยี่ยมสำหรับคลาสยูทิลิตี้!
ฉันพยายาม ใช้คลาสยูทิลิตี้เท่า ที่จำเป็นแทนที่จะแทนที่แค่เขียน CSS เกณฑ์ส่วนตัวของฉันเมื่อเหมาะสมที่จะเพิ่มหนึ่งรายการในโครงการคือ:
- ฉันต้องการมันซ้ำแล้วซ้ำอีก
- มันทำสิ่งหนึ่งได้ดี
- ใช้กับส่วนประกอบหรือหน้าต่างๆ ที่หลากหลาย
ฉันคิดว่ากรณีนี้ตรงตามเกณฑ์ทั้งสาม เรามาสร้างไฟล์ CSS ใหม่ style/utilities.css และเพิ่ม:
.lockup { max-width: 90ch; margin: 0 auto; }
จากนั้น มาเพิ่มการนำเข้า '../styles/utilities.css'
ใน หน้าของเรา/_app.jsx สุดท้าย เรามาเปลี่ยนแท็ก <main>
ใน pages/index.jsx เป็น <main className="lockup">
ตอนนี้เพจของเรากำลังมากันมากยิ่งขึ้น เนื่องจากเราใช้คุณสมบัติ max-width
เราจึงไม่ต้องการคิวรี่สื่อใดๆ เพื่อให้เลย์เอาต์ของเราตอบสนองต่ออุปกรณ์เคลื่อนที่ และเนื่องจากเราใช้หน่วยวัด ch
ซึ่งเท่ากับความกว้างของอักขระหนึ่งตัว การปรับขนาดของเราจึงเป็นไดนามิกตามขนาดแบบอักษรของเบราว์เซอร์ของผู้ใช้
เมื่อเว็บไซต์ของเราเติบโตขึ้น เราก็สามารถเพิ่มคลาสยูทิลิตี้เพิ่มเติมต่อไปได้ ฉันใช้แนวทางที่ค่อนข้างเป็นประโยชน์ที่นี่: ถ้าฉันทำงานและพบว่าฉันต้องการชั้นเรียนอื่นสำหรับสีหรืออะไรบางอย่าง ฉันจะเพิ่มมันเข้าไป ฉันไม่ได้เพิ่มทุกคลาสที่เป็นไปได้ภายใต้ดวงอาทิตย์ — มันจะทำให้ขนาดไฟล์ CSS ขยายใหญ่และทำให้โค้ดของฉันสับสน บางครั้ง ในโครงการขนาดใหญ่ ฉันชอบแบ่งสิ่งต่าง ๆ ออกเป็นไดเร็กทอรี styles/utilities/
ด้วยไฟล์ที่แตกต่างกันสองสามไฟล์ แล้วแต่ความต้องการของโครงการ
เราสามารถนึกถึงคลาสยูทิลิตี้เป็น ชุดเครื่องมือทั่วไปของคำสั่งการจัดรูปแบบซ้ำๆ ที่แชร์กันทั่วโลก ช่วยป้องกันไม่ให้เราเขียน CSS เดิมซ้ำระหว่างส่วนประกอบต่างๆ
ลักษณะส่วนประกอบ
เราได้ทำโฮมเพจเสร็จแล้วในขณะนี้ แต่เรายังคงต้องสร้างส่วนหนึ่งของเว็บไซต์ของเรา นั่นคือ ร้านค้าออนไลน์ เป้าหมายของเราคือการแสดง ตารางการ์ดของชาทั้งหมดที่เราต้องการขาย ดังนั้นเราจะต้องเพิ่มส่วนประกอบบางอย่างในไซต์ของเรา
มาเริ่มกันด้วยการเพิ่มเพจใหม่ที่ pages/shop.jsx :
export default function Shop() { return <main> <div className="lockup"> <h1>Shop Our Teas</h1> </div> </main> }
จากนั้น ก็ต้องมีชามาโชว์ เราจะใส่ชื่อ คำอธิบาย และรูปภาพ (ในไดเรกทอรีสาธารณะ/) สำหรับแต่ละชา:
const teas = [ { name: "Oolong", description: "A partially fermented tea.", image: "/oolong.jpg" }, // ... ]
หมายเหตุ : นี่ไม่ใช่บทความเกี่ยวกับการดึงข้อมูล ดังนั้นเราจึงใช้เส้นทางที่ง่ายและกำหนดอาร์เรย์ที่จุดเริ่มต้นของไฟล์
ต่อไป เราจะต้องกำหนดองค์ประกอบเพื่อแสดงชาของเรา เริ่มต้นด้วยการสร้าง components/
ไดเร็กทอรี (Next.js ไม่ได้สร้างสิ่งนี้โดยค่าเริ่มต้น) จากนั้น มาเพิ่มไดเร็กทอรี components/TeaList
กัน สำหรับส่วนประกอบใด ๆ ที่ต้องการมากกว่าหนึ่งไฟล์ ฉันมักจะใส่ไฟล์ที่เกี่ยวข้องทั้งหมดไว้ในโฟลเดอร์ การทำเช่นนี้จะป้องกันไม่ให้ components/
โฟลเดอร์ของเราใช้งานไม่ได้
ตอนนี้ มาเพิ่มไฟล์ ส่วนประกอบ/TeaList/TeaList.jsx ของเรา:
import TeaListItem from './TeaListItem' const TeaList = (props) => { const { teas } = props return <ul role="list"> {teas.map(tea => <TeaListItem tea={tea} key={tea.name} />)} </ul> } export default TeaList
จุดประสงค์ของส่วนประกอบนี้คือเพื่อวนซ้ำบนชาของเราและแสดงรายการสำหรับแต่ละรายการ ดังนั้นตอนนี้ เรามากำหนด ส่วนประกอบ/TeaList/TeaListItem.jsx ส่วนประกอบของเรา:
import Image from 'next/image' const TeaListItem = (props) => { const { tea } = props return <li> <div> <Image src={tea.image} alt="" objectFit="cover" objectPosition="center" layout="fill" /> </div> <div> <h2>{tea.name}</h2> <p>{tea.description}</p> </div> </li> } export default TeaListItem
โปรดทราบว่าเรากำลังใช้องค์ประกอบรูปภาพในตัวของ Next.js ฉันตั้งค่าแอตทริบิวต์ alt
เป็นสตริงว่างเนื่องจากรูปภาพมีการตกแต่งเท่านั้นในกรณีนี้ เราต้องการหลีกเลี่ยงไม่ให้ผู้ใช้โปรแกรมอ่านหน้าจอสะดุดด้วยคำอธิบายรูปภาพแบบยาวที่นี่
สุดท้าย มาสร้างไฟล์ component/TeaList/index.js เพื่อให้ง่ายต่อการนำเข้าส่วนประกอบจากภายนอก:
import TeaList from './TeaList' import TeaListItem from './TeaListItem' export { TeaListItem } export default TeaList
จากนั้น มารวมเข้าด้วยกันโดยเพิ่มการนำเข้า TeaList จาก ../ ../components/TeaList
และองค์ประกอบ <TeaList teas={teas} />
ในหน้าร้านค้าของเรา ตอนนี้ ชาของเราจะแสดงในรายการ แต่มันจะไม่สวยนัก
Colocating Style ด้วยส่วนประกอบผ่านโมดูล CSS
เริ่มต้นด้วยการจัดสไตล์การ์ดของเรา (องค์ประกอบ TeaListLitem
) เป็นครั้งแรกในโปรเจ็กต์ของเรา เราต้องการเพิ่มสไตล์ที่เฉพาะเจาะจงสำหรับองค์ประกอบเดียว มาสร้างไฟล์ใหม่ component/TeaList/TeaListItem.module.css
คุณอาจสงสัยเกี่ยวกับโมดูลในนามสกุลไฟล์ นี่คือ โมดูล CSS Next.js รองรับโมดูล CSS และมีเอกสารประกอบที่ดีอยู่ด้วย เมื่อเราเขียนชื่อคลาสจากโมดูล CSS เช่น .TeaListItem
ชื่อคลาสจะถูกแปลงเป็นอย่างอื่นโดย . TeaListItem_TeaListItem__TFOk_
. TeaListItem_TeaListItem__TFOk_
พร้อมอักขระพิเศษจำนวนมากที่ถูกตรึงไว้ ดังนั้น เราจึงสามารถใช้ชื่อคลาสใดก็ได้ที่เราต้องการ โดยไม่ต้องกังวลว่าจะขัดแย้งกับชื่อคลาสอื่นในไซต์ของเรา
ข้อดีอีกประการของโมดูล CSS คือประสิทธิภาพ Next.js มีคุณลักษณะการนำเข้าแบบไดนามิก ถัดไป/ไดนามิกช่วยให้เราโหลดคอมโพเนนต์แบบ Lazy Loading เพื่อให้โค้ดของพวกเขาโหลดได้เมื่อจำเป็นเท่านั้น แทนที่จะเพิ่มขนาดบันเดิลทั้งหมด หากเรานำเข้าสไตล์โลคัลที่จำเป็นลงในส่วนประกอบแต่ละส่วน ผู้ใช้ก็จะสามารถ โหลด CSS สำหรับส่วนประกอบที่นำเข้าแบบไดนามิก ได้ สำหรับโปรเจ็กต์ขนาดใหญ่ เราอาจเลือกที่จะขี้เกียจโหลดโค้ดจำนวนมากและโหลด JS/CSS ที่จำเป็นที่สุดล่วงหน้าเท่านั้น ด้วยเหตุนี้ ฉันมักจะจบลงด้วยการสร้างไฟล์โมดูล CSS ใหม่สำหรับส่วนประกอบใหม่ทั้งหมดที่ต้องการการจัดสไตล์ในเครื่อง
เริ่มต้นด้วยการเพิ่มรูปแบบเริ่มต้นลงในไฟล์ของเรา:
.TeaListItem { display: flex; flex-direction: column; gap: var(--space-sm); background-color: var(--color, var(--off-white)); color: var(--dark); border-radius: 3px; box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); }
จากนั้น เราสามารถนำเข้าสไตล์จาก ./TeaListItem.module.css
ในองค์ประกอบ TeaListitem
ของเรา ตัวแปรสไตล์มาในรูปแบบออบเจกต์ JavaScript ดังนั้นเราจึงสามารถเข้าถึง style.TeaListItem.
หมายเหตุ : ชื่อคลาสของเราไม่จำเป็นต้องเป็นตัวพิมพ์ใหญ่ ฉันพบว่าแบบแผนของชื่อคลาสที่เป็นตัวพิมพ์ใหญ่ภายในโมดูล (และตัวพิมพ์เล็กด้านนอก) แยกความแตกต่างของชื่อคลาสท้องถิ่นและระดับโลกด้วยสายตา
ลองใช้คลาสท้องถิ่นใหม่ของเราและกำหนดให้กับ <li>
ในองค์ประกอบ TeaListItem
ของเรา:
<li className={style.TeaListComponent}>
คุณอาจกำลังสงสัยเกี่ยวกับเส้นสีพื้นหลัง (เช่น var(--color, var(--off-white));
) ข้อมูลโค้ดนี้หมายความว่า โดยค่าเริ่มต้น พื้นหลังจะเป็นค่า --off-white
แต่ถ้าเราตั้งค่า --color
คุณสมบัติกำหนดเองบนการ์ด มันจะแทนที่และเลือกค่านั้นแทน
ในตอนแรก เราจะต้องการให้การ์ดทั้งหมดของเรา --off-white
แต่เราอาจต้องการเปลี่ยนค่าของการ์ดแต่ละใบในภายหลัง สิ่งนี้ทำงานคล้ายกับอุปกรณ์ประกอบฉากใน React เราสามารถตั้งค่าเริ่มต้นได้ แต่สร้างช่องที่เราสามารถเลือกค่าอื่นได้ในบางสถานการณ์ ดังนั้นฉันจึงแนะนำให้เรา นึกถึงคุณสมบัติที่กำหนดเองของ CSS เช่น props เวอร์ชันของ CSS
สไตล์จะยังดูไม่ดีนักเพราะเราต้องการให้แน่ใจว่ารูปภาพอยู่ในคอนเทนเนอร์ องค์ประกอบรูปภาพของ Next.js ที่มีเสา layout="fill"
ได้รับ position: absolute;
จาก framework จึงสามารถจำกัดขนาดโดยใส่คอนเทนเนอร์ที่มีตำแหน่ง: ญาติ;.
มาเพิ่มคลาสใหม่ให้กับ TeaListItem.module.css ของเรา:
.ImageContainer { position: relative; width: 100%; height: 10em; overflow: hidden; }
จากนั้นให้เพิ่ม className={styles.ImageContainer}
ใน <div>
ที่มี <Image>
ของเรา ฉันใช้ชื่อที่ค่อนข้าง "ธรรมดา" เช่น ImageContainer
เนื่องจากเราอยู่ในโมดูล CSS ดังนั้นเราจึงไม่ต้องกังวลว่าจะขัดแย้งกับรูปแบบภายนอก
สุดท้าย เราต้องการ เพิ่มช่องว่างภายในเล็กน้อย ที่ด้านข้างของข้อความ ดังนั้น ให้เพิ่มคลาสสุดท้ายและใช้ตัวแปรการเว้นวรรคที่เราตั้งค่าเป็นโทเค็นการออกแบบ:
.Title { padding-left: var(--space-sm); padding-right: var(--space-sm); }
เราสามารถเพิ่มคลาสนี้ใน <div>
ที่มีชื่อและคำอธิบายของเรา ตอนนี้การ์ดของเราไม่ได้ดูแย่นัก:
ผสมผสานสไตล์ระดับโลกและระดับท้องถิ่น
ต่อไป เราต้องการให้การ์ดของเราแสดงในรูปแบบตาราง ในกรณีนี้ เราแค่อยู่ใกล้เส้นแบ่งระหว่างสไตล์ท้องถิ่นและสไตล์สากล เราสามารถเขียนโค้ดเลย์เอาต์ของเราโดยตรงบนคอมโพเนนต์ TeaList
แต่ฉันสามารถจินตนาการได้ด้วยว่าการมี คลาสยูทิลิตี้ที่เปลี่ยนรายการเป็นเลย์เอาต์กริด อาจมีประโยชน์ในที่อื่นๆ อีกหลายแห่ง
ลองใช้แนวทางสากลที่นี่และเพิ่มคลาสยูทิลิตี้ใหม่ใน styles/utilities.css ของเรา:
.grid { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--min-item-width, 30ch), 1fr)); gap: var(--space-md); }
ตอนนี้ เราสามารถเพิ่มคลาส .grid
ในรายการใดก็ได้ และเราจะได้รับเค้าโครงกริดที่ตอบสนองโดยอัตโนมัติ นอกจากนี้เรายังสามารถเปลี่ยน --min-item-width
กำหนดเองคุณสมบัติ (โดยค่าเริ่มต้น 30ch
) เพื่อเปลี่ยนความกว้างขั้นต่ำของแต่ละองค์ประกอบ
หมายเหตุ : อย่าลืมนึกถึงคุณสมบัติที่กำหนดเอง เช่น อุปกรณ์ประกอบฉาก! หากไวยากรณ์นี้ดูไม่คุ้นเคย คุณสามารถตรวจสอบ “ตาราง CSS ที่ตอบสนองภายในด้วย minmax()
และ min()
” โดย Chris Coyier
เนื่องจากเราได้เขียนสไตล์นี้ไปทั่วโลก การเพิ่ม className="grid"
ลงในองค์ประกอบ TeaList
ของเรานั้นไม่ต้องการความหรูหราใดๆ แต่สมมติว่าเราต้องการจับคู่สไตล์สากลนี้กับร้านค้าในพื้นที่เพิ่มเติม ตัวอย่างเช่น เราต้องการเพิ่ม "ความงามของชา" เข้าไปอีกเล็กน้อย และทำให้การ์ดใบอื่นๆ มีพื้นหลังสีเขียว สิ่งที่เราต้องทำคือสร้างไฟล์ component/TeaList/TeaList.module.css ใหม่:
.TeaList > :nth-child(even) { --color: var(--green); }
จำได้ไหมว่าเราสร้าง --color custom
บนองค์ประกอบ TeaListItem
ของเราได้อย่างไร ตอนนี้เราสามารถตั้งค่าได้ภายใต้สถานการณ์เฉพาะ โปรดทราบว่าเรายังคงใช้ตัวเลือกย่อยภายในโมดูล CSS ได้ และไม่สำคัญว่าเราจะเลือกองค์ประกอบที่มีรูปแบบภายในโมดูลอื่น ดังนั้น เรายังสามารถใช้รูปแบบองค์ประกอบในเครื่องของเราเพื่อส่งผลต่อองค์ประกอบย่อย นี่เป็นคุณลักษณะมากกว่าข้อบกพร่อง เนื่องจากช่วยให้เรา ใช้ประโยชน์จาก CSS cascade ได้ ! หากเราพยายามจำลองเอฟเฟกต์นี้ด้วยวิธีอื่น เราอาจจบลงด้วยซุป JavaScript บางประเภท แทนที่จะเป็น CSS สามบรรทัด
แล้วเราจะเก็บคลาส .grid ทั่วโลกไว้ในองค์ประกอบ .grid
ของเรา TeaList
ในขณะที่เพิ่มคลาส .TeaList
ในพื้นที่ด้วย นี่คือจุดที่ไวยากรณ์อาจดูขี้ขลาดเล็กน้อยเพราะเราต้องเข้าถึงคลาส .TeaList
ของเราจากโมดูล CSS โดยทำบางอย่างเช่น style.TeaList
ทางเลือกหนึ่งคือใช้การแก้ไขสตริงเพื่อรับบางสิ่งเช่น:
<ul role="list" className={`${style.TeaList} grid`}>
ในกรณีเล็กๆ นี้ มันอาจจะดีพอ หากเรากำลังผสมคลาสต่างๆ เข้าด้วยกันมากขึ้น ฉันพบว่าไวยากรณ์นี้ทำให้สมองของฉันระเบิดขึ้นเล็กน้อย ดังนั้นบางครั้งฉันจะเลือกใช้ไลบรารี่ชื่อคลาส ในกรณีนี้ เราจะได้รายการที่ดูสมเหตุสมผลกว่า:
<ul role="list" className={classnames(style.TeaList, "grid")}>
ตอนนี้ เราได้ทำเพจร้านค้าเสร็จแล้ว และเราได้ทำให้องค์ประกอบ TeaList
ของเราใช้ประโยชน์จากสไตล์ ทั้งแบบ สากลและแบบท้องถิ่น
พระราชบัญญัติสมดุล
ตอนนี้เราได้สร้างร้านน้ำชาของเราโดยใช้ CSS ธรรมดาในการจัดการสไตล์ คุณอาจสังเกตเห็นว่าเราไม่ต้องใช้เวลานานในการจัดการกับการตั้งค่า Webpack แบบกำหนดเอง การติดตั้งไลบรารีภายนอก และอื่นๆ นั่นเป็นเพราะรูปแบบที่เราเคยใช้กับ Next.js มาก่อน นอกจากนี้ ยัง สนับสนุนแนวทางปฏิบัติ CSS ที่ดีที่สุด และเหมาะสมกับสถาปัตยกรรมเฟรมเวิร์ก Next.js อย่างเป็นธรรมชาติ
องค์กร CSS ของเราประกอบด้วยสี่ส่วนสำคัญ:
- โทเค็นการออกแบบ
- สไตล์สากล
- คลาสยูทิลิตี้
- สไตล์คอมโพเนนต์
ขณะที่เราสร้างไซต์ของเราต่อไป รายการโทเค็นการออกแบบและคลาสยูทิลิตี้ของเราจะเติบโตขึ้น สไตล์ใดๆ ที่ไม่เหมาะสมที่จะเพิ่มเป็นคลาสยูทิลิตี้ เราสามารถเพิ่มลงในสไตล์ส่วนประกอบโดยใช้โมดูล CSS ด้วยเหตุนี้ เราจึงพบความสมดุลอย่างต่อเนื่องระหว่างความกังวลเกี่ยวกับสไตล์ท้องถิ่นและระดับโลก นอกจากนี้เรายังสามารถ สร้างโค้ด CSS ที่มีประสิทธิภาพและใช้งานง่าย ซึ่งเติบโตอย่างเป็นธรรมชาติควบคู่ไปกับไซต์ Next.js ของเรา