🎨 แชร์ประสบการณ์ การใช้งาน Next.js คู่กับ ant-design และ styled-components 💄

ช่วงนี้ผมได้มีโอกาสเขียนเว็บแอพ​โดยใช้ Next.js คู่กันกับ ant-design

ใครยังไม่รู้ว่า Next.js คืออะไร หรือดียังไง ก็ลองอ่านดูได้ ที่นี่

อธิบาย ant-design ง่าย ๆ ก็คือ library ที่ประกอบไปด้วย component สำเร็จรูปมากมาย ให้เราสามารถเรียกใช้ได้ทันที


การเขียน CSS ใน Next.js

ตอนเริ่มต้น Next.js มาพร้อมกับการเขียน CSS ด้วย styled-jsx ซึ่งมันก็ดีในระดับหนึ่ง เนื่องจากมันมีการจำกัด scope อยู่เพียงแค่ภายใน component ที่เราเขียนขึ้นจริง ๆ รวมไปถึง syntax เองก็เขียนแบบ CSS ปกติ

(ผมไม่ชอบเขียน syntax inline ใน React แบบปกติซักเท่าไหร่ เนื่องจากชื่อ syntax มันถูกเปลี่ยน เช่น จาก text-align กลายเป็น textAlign รวมไปถึงตัว editor เองก็ไม่สามารถทำการ auto complete ให้ผมได้)


ปัญหาใน styled-jsx

หลังจากเขียน styled-jsx ไปได้ซักพัก ผมก็พบกับวิบากกรรม เนื่องจาก project ของผม ใช้งานคู่กันกับ ant-design ซึ่งมีการจัด style มาเรียบร้อยแล้ว (แต่เราดันทะลึ่งอยากไป customize design มันไง)

อย่างที่กล่าวไปข้างต้น styled-jsx มี scope แค่ภายในจุดที่เราเขียน

กล่าวคือ CSS ของผมไม่สามารถเจาะไปภายใต้ component ของ ant-design ได้

ซึ่งวิธีการที่เราจะเจาะเข้าไป edit style ของ component ภายใต้ได้นั้น เราต้องทำโดยการเขียน styled-jsx โดยบอกให้มันเป็น global

ซึ่งหมายความว่าเมื่อเราเขียนให้ CSS ของเรามีการแก้ไขบางอย่างภายใน component เรา มันก็อาจจะส่งผลต่อ component อื่น โดยรอบได้

ซึ่งมันฟังดูไม่น่ารื่นรมนักสำหรับแนวคิดที่เราอยากแยกให้ทุกอย่างถูกแบ่งออกเป็น component ของมัน ร่วมไปถึง style


Solution

ณ จุดนี้ผมรู้สึกว่า styled-jsx นั้นไม่ตอบโจทย์ของผมอีกต่อไป เราจึงหันเหไปหาวิธีการใหม่ ๆ ซึ่งก็ทำให้ผมได้พบกับ styled-components

styled-components

ลอง style ของด้วย styled-components

หลังการ setup เสร็จเรียบร้อย ผมก็ทดสอบโดยการ style html elements ธรรมดาเนี่ยแหละ ด้วย styled-components

โค้ดก็จะเป็นประมาณนี้

import styled from 'styled-components'
const Button = styled.button`
background: #fff;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`
export default () =>
<div>
<Button>Press It</Button>
</div>

ก็จะได้ผลลัพธ์ปุ่มประมาณนี้


อธิบายการ style ของด้วย styled-components

ลักษณะง่าย ๆ ในการใช้คือ หากเราต้องการ style อะไรก็ตาม เราจะทำการสร้าง components ขึ้นมาด้วย styled-components โดยที่เราสามารถระบุได้ว่า components ที่เราสร้างขึ้นมานั้น ต้องการให้เป็น tag อะไร (ในตัวอย่างเป็นเราทำการสร้าง component ขึ้นมาโดยใส่ style ให้กับ tag button สังเกตได้จาก styled.button )

ส่วนวิธีการนำไปใช้เราก็สามารถนำเอา components ที่สร้างขึ้นเหล่านี้ไปใช้งาน เหมือนกับ components ปกติได้เลย

หลังจากทดสอบไปได้ซักพักผมก็รู้สึก… อืมม์ มันช่างดูสะอาดและตอบโจทย์ของผมได้เป็นอย่างดี จนไม่สามารถเลิกใช้มันได้เลย

โดยผมมีขั้นเหตุผลที่ทำให้เลือกใช้ styled-components ดังต่อไปนี้


1. สามารถเขียน CSS ด้วย syntax CSS ปกติได้

อันนี้คือโค้ดที่ผมทดสอบเขียน CSS ด้านบน

import styled from 'styled-components'
const Button = styled.button`
background: #fff;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`
export default () =>
<div>
<Button>Press It</Button>
</div>

ถ้าลองสังเกตดูจะพบว่า ตัว CSS ที่ถูกเขียนขึ้นจริงๆ นั้นอยู่ภายใต้กอรอบของ styled.button`…` ทั้งสิ้น และมี syntax เหมือนกันกับการเขียน CSS ปกติทั้งหมด


2. editor ของผมสามารถขึ้น auto complete สำหรับการเขียน CSS ได้แล้ว!!

ไม่มีอะไรมากเลยครับ ผมเป็นคนขี้เกียจ ถ้า editor มันจะช่วย auto complete ให้เราได้ มันก็จะเป็นอะไรที่ฟินสุด ๆ ประมาณนี้


3. สามารถ customize style, based on prop ที่ใส่เข้าไปใน component ได้

เราสามารถทำให้ style ของ component เราเปลี่ยนแปลงไปตาม prop ที่ใส่เข้าไปได้ เช่นจากโค้ดเดิมก่อนหน้านี้

const Button = styled.button`
background: #fff;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`

ผมทำการใส่เงื่อนไขเข้าไปว่า เมื่อรับ props primary เข้ามาจะให้มีสีสลับกัน

const Button = styled.button`
background: ${props => props.primary ? 'palevioletred' : '#fff'};
color: ${props => props.primary ? '#fff' : 'palevioletred'};
  font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`

เวลานำไปใช้งานจริง ก็จะได้ผลลัพธ์ประมาณนี้


4. สามารถเขียน CSS เจาะเข้าไปถึง child components ภายใต้ได้

อันนี้ต้องเรียกว่าเป็นสาเหตุหลักที่ผมเปลี่ยนมาใช้ styled-component เลยทีเดียวครับ เพราะ styled-components สามารถทำให้ผมเขียน CSS เจาะเข้าไปใน child component ข้างใต้ได้ แต่ไม่กระทบอะไรกันกับ component อื่นรอบ ๆ

ตัวอย่างปัญหา

ตอนนี้เว็บที่ผมทำอยู่ใช้งานคู่กันกับ ant design แล้วปรากฎว่า style ปัจจุบันของ field ที่มันให้มานั้น มีขนาดเล็กเกินไป

ผมอยากเพิ่มขนาด label และ input ดู ผมจึงลองใส่ style เข้าไปโดยตรงดังนี้

ปรากฎว่าผลลัพธ์ไม่เป็นไปตามคาด ผมไม่สามารถไป fix style มันได้โดยตรงทั้งหมด

ดังนั้นผมจึงได้นำเอา styled-components เข้ามาจัดการงานตรงนี้ โดยผมลองทำการ inspect dom เหล่านี้ดู ก็พบว่าตัวที่ผมต้องการเปลี่ยนขนาด font มันมี tag เป็น label และ input

ผมจึงทำการสร้าง Wrapper ขึ้นมาและบอกว่า tag label หรือ input อะไรก็ตามที่อยู่ใน wrapper นี้นั้น font จะมีขนาดเท่ากับ 22px

จากนั้นนำเอา Wrapper ไปครอบ Form ที่ผมได้สร้างขึ้นก่อนหน้า ก็จะได้ผลลัพธ์ดังนี้

เท่านี้เองครับ ผมก็สามารถเจาะ CSS เข้าไปแก้ไขถึง child component ข้างใต้ได้ โดยไม่กระทบกับ component รอบ ๆ แล้ว


ส่งท้าย

สำหรับเพื่อน ๆ ใครก็ตามที่มีปัญหาเรื่องการ style ของใน React ผมก็อยากจะขอฝาก styled-components เอาไว้ลองพิจารณาดูนะครับ

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

ใครสนใจศึกษา styled-components เพิ่มเติมก็สามารถเข้าไปอ่าน document เพิ่มเติมได้ ที่นี่

และอย่าลืมกด ⭐️ ให้กับ repo ดี ๆ แบบนี้ด้วยนะครับ