เข้าสู่ Dark mode ไปกับ Next.js

Nattakit Len
te<h @TDG
Published in
2 min readFeb 9, 2020

สมัยนี้เนี้ยอะไรๆมันก็ต้อง dark ใช่ไหมล่ะ ทั้งด้าน windows หรือ macOS เองก็มี dark mode และถ้าต่อต้านไม่ได้ก็จงเข้าร่วม !? แต่ในที่นี้ผมกำลังพูดถึงการทำให้เว็บไซต์ของเรานั้นเป็น dark mode โดยอ้างอิงจาก OS ของ user มิใช่การกดสลับจากหน้าเว็บ และถ้าพร้อมกันแล้ว เรามาพาเว็บไซต์ของเราให้เข้าสู่ DARK MODE ไปด้วยกันกับ Next.js และ styled-components

เตรียมตัวเข้าสู่ด้านมืด

ผมจะถือว่าทุกคนมี project next อยู่แล้วนะ หากใครยังไม่มีก็สามารถสร้าง project ได้ง่ายๆด้วย create-next-app และทำการติดตั้งแพคเกจ styled-components ด้วยล่ะ

Theme Objects

ก่อนอื่นเลย เราจะต้องสร้าง Theme ของเราขึ้นมาก่อน ทั้งแบบ light และ dark โดยค่าเริ่มต้นนั้นผมจะใช้เป็น light

ในตัวอย่างผมจะสร้าง theme แบบง่ายๆขึ้นมา โดยมีแค่สีของ background และ text เหตุผลที่ผมสร้างไว้แค่นี้นั้นก็เพราะว่าผม “ขี้เกียจ” ครับ

Using theme objects in ThemeProvider

style-components นั้นมีคอมโพเนนต์ที่ชื่อว่า ThemeProvider โดยเจ้า ThemeProvider จะทำให้คอมโพเนนต์(style-components) ที่เป็นอยู่ภายใต้ตัวมันสามารถเรียกใช้ค่าต่างๆของ theme ได้ผ่าน props เลย

ในตัวอย่างผมจะสร้างคอมโพเนนต์ Providers ขึ้นมาครอบเจ้า ThemeProvider อีกที ถามว่าทำไมต้องทำแบบนี้ เพราะในอนาคตอันใกล้นี้เราจะเล่นกับเจ้าคอมโพเนนต์ตัวนี้ครับ

useDarkMode Hook

สิ่งที่เรากำลังจะทำต่อจากนี้ คือตัวกำหนดว่าแอปของเรานั้นจะใช้ theme light หรือ dark โดยดูจาก OS ของ user ซึ่งจริงๆแล้วนั้นมันไม่มีอะไรมากเลยครับ เพราะปัจจุบันนี้ CSS นั้นมีความสามารถนี้อยู่แล้ว นั้นคือ prefers-color-scheme (สามารถดู browser ที่รองรับได้ที่ caniuse) เราก็แค่นำสิ่งนี้มาปรับใช้กับแอปของเรา

ในที่นี่ผมจะใช้ React Hooks โดยเจ้า Hook ของผมก็จะมีหน้าตาประมาณนี้

แต่

ประเด็นมันมีอยู่ว่า Next.js นั้นเป็น SSR(Server-Side Rendering) ทำให้ในครั้งแรกที่แอปของเราทำงานมันอยู่บน server “ให้ตายเถอะ”(เสียงน้าค่อม) !!! นั้นหมายความว่า prefers-color-scheme จะไม่สามารถรู้ได้เลยว่าฝั่ง client ที่เป็น user นั้นมีการตั้งค่า mode บน OS เป็น light หรือ dark ทำให้ครั้งแรกที่หน้าเว็บโชว์จะแสดงค่าเป็น theme default ตามที่เราได้ตั้งไว้แล้วค่อยเปลี่ยน theme อีกทีด้วยผลของ prefers-color-scheme ซึ่งนั้นส่งผลให้หน้าเว็บของเรามีการกระพริบเนื่องจากการ re-render

แต่ (2)

ทางที่จะเข้าสู่ด้านมืดนั้นเปิดอ้ารับเราอยู่เสมอ หมายความว่ามันก็ยังมีท่าดิ้นกันอยู่และท่านั้นก็คือเพื่อนเก่าของเรา visibility: hidden นั้นเองในตอนที่ฝั่ง client ได้รับหน้าเว็บของเราจาก server เราจะทำการซ่อนทั้งหมดไว้ก่อนและปล่อยให้พระเอกของเรา prefers-color-scheme ได้ทำหน้าตรวจสอบว่า user นั้นใช้ mode ใดอยู่และทำการเซตค่าให้เรียบร้อยก่อนจะโชว์หน้าเว็บของเรา นั้นเอง

Put it all together

ได้เวลานำทุกอย่างที่เราทำมาประกอบร่างแล้ว

Demo

หากใครอยากเล่นหรือดูโค้ดเต็มๆก็สามารถไป clone project ได้ที่ Github

สุดท้ายนี้

.

.

.

แสงแดดที่แยงตา ยังไม่เท่าสายตาที่แยงใจ

ขอบคุณครับ

🙏🏼 special thanks

--

--