SCSS Components

จากบทความที่แล้ว เรื่อง “จัดระเบียบ CSS ด้วย SCSS กันเถอะ

มาว่ากันต่อด้วยนิยาม “SCSS Components”

เวลาคุณเขียน CSS คุณมีมุมมองในการเขียนยังไง?

คุณได้มองมันเป็น “Components” หรือเปล่า?

เช่น ในเว็บ 1 เว็บ ถ้ามอง Components ที่ใหญ่ที่สุดของมัน คุณก็จะแยกออกได้เป็น

  • header
  • navigation
  • content
  • footer

แล้วถ้ามองย่อยลงไปอีก คุณก็จะแยกได้อีกว่า

header ประกอบด้วยอะไรบ้าง ซึ่งก็อาจจะเป็น logo, company name หรือ tag line, navigation เป็นต้น

เหล่านี้ก็สามารถแยกออกเป็น components ได้ ไม่มีผิด และไม่มีถูก

แต่สำหรับการแยก SCSS Components ในแนวทางของ SCSS อยากให้ลืมมันไปก่อน

แต่ให้คุณแยก SCSS Components ด้วยแนวคิดว่า

“อะไรที่ใช้ทุกหน้า และอะไรใช้แค่หน้าเดียว”

ถ้าคุณใช้ Google Pagespeed ในการวัดผลคุณภาพเว็บไซต์ของคุณ หนึ่งข้อที่สำคัญที่ Pagespeed ระบุไว้ คือ อย่าใช้การ @import CSS เข้ามาหลายๆไฟล์ แต่ให้รวมเป็นไฟล์เดียวกันซะ เพราะมันทำให้ HTTP Request เยอะเกินความจำเป็น (ใจความรวมๆก็คือ พยายามเรียกไฟล์ css แค่ไฟล์เดียวนั่นแหละ อย่ายัดไส้โดยการใช้คำสั่ง @import ไฟล์ CSS อื่นข้างในเยอะๆ)

ทีนี้จากที่ข้างบนบอกว่า ให้แยกไฟล์ SCSS ตามแนวคิดที่ว่า “อะไรที่ใช้ทุกหน้าให้รวมไว้ไฟล์เดียวกัน ส่วนอะไรที่ใช้แค่หน้าเดียวให้แยกของใครของมัน

ในทางปฏิบัติ จะขอยกตัวอย่างดังนี้

วิเคราะห์ก่อนว่าหน้าเว็บประกอบด้วยอะไรบ้าง

ส่วนประกอบหน้าเว็บเพจโดยทั่วไป Credit : http://www.homeandlearn.co.uk/WD/images/chapter6/one-column-layout.gif
  1. header
  2. Navigation
  3. Footer
  4. Content ในแต่ละหน้า

แล้วอะไรบ้างที่ใช้เหมือนกันทุกหน้า = header, navigation, footer

ส่วนที่ต่างกันคือ content ในแต่ละหน้า

ดังนั้น เราสามารถ group header, navigation และ footer ไว้ในไฟล์เดียวกันได้เลย นั่นคือ base.scss (หรือจะใช้ชื่ออื่นก็ได้ตามใจคนเขียน)

ส่วนของ content ที่ต่างกันในแต่ละหน้า เราก็ดูว่า content เหล่านั้นมันต่างกันจริงๆหรือไม่

แล้วถ้ามี content หรือ Element ไหนที่มันยังซ้ำเหมือนกันอีก เช่น

carousel, calendar , กล่อง share social ฯลฯ เราก็แยกออกมา ไว้ใน base.s ……
^
^

เดี๋ยวก่อน !!! .. ก่อนจะโยน content ที่ซ้ำกันในแต่ละหน้าเข้าไปที่ base.scss ให้เช็คดูอีกทีว่า content เหล่านั้นใช้ทุกหน้าจริงหรือไม่???

.
.

คำตอบคือ “ไม่ใช่” เพราะบางหน้าก็ใช้ carousel บางหน้าก็อาจจะไม่ใช้ก็ได้ ดังนั้น เราจึงแยกย่อย Content Element เหล่านี้ออกมาเป็น .scss ไฟล์เพิ่มเติมได้อีก ดังนี้

carousel.scss — เก็บ CSS สำหรับ carousel โดยเฉพาะ

calendar.scss — เก็บ CSS สำหรับ calendar โดยเฉพาะ

share.scss — เก็บ CSS สำหรับ share โดยเฉพาะ

จากโจทย์ จะเห็นว่าไฟล์ .scss เริ่มมีมากขึ้น

ทีนี้ ในหน้าเพจต่างๆที่เราเขียนขึ้นมา เราก็เขียนแยกเป็นไฟล์ .scss มาอีกไฟล์นึง สมมติว่าเรามี 3 page ได้แก่

  1. Homepage โดย Homepage มี Content คือ Carousel และ Calendar : สร้างไฟล์ homepage.scss ขึ้นมา 1 ไฟล์ โดยในไฟล์นี้จะเรียกไฟล์ .scss ย่อยๆ ได้แก่
ตัวอย่างไฟล์​ homepage.scss
  • base.scss → มี Header, Navigation , Footer
  • carousel.scss
  • calendar.scss
  • และมี CSS อื่นๆที่ใช้สำหรับหน้านี้เท่านั้นต่อท้าย (ภายใต้ /*Another style especially for …*/)

2. Portfolio โดยหน้า Portfolio มี Content คือ Carousel และ share : สร้างไฟล์ portfolio.scss ขึ้นมา 1 ไฟล์ โดยในไฟล์นี้จะเรียกไฟล์ .scss ย่อยๆ ได้แก่

ตัวอย่างไฟล์​ portfolio.scss
  • base.scss → มี Header, Navigation , Footer
  • carousel.scss
  • share.scss
  • และมี CSS อื่นๆที่ใช้สำหรับหน้านี้เท่านั้นต่อท้าย (ภายใต้ /*Another style especially for …*/)

3. About Us มี Content เป็นข้อความธรรมดา โดยไม่มี Element อื่นๆเลย: สร้างไฟล์ about.scss ขึ้นมา 1 ไฟล์ โดยไฟล์นี้จะเรียกไฟล์ .scss ย่อยๆได้แก่

ตัวอย่างไฟล์​ about.scss
  • base.scss → มี Header, Navigation , Footer
  • และมี CSS อื่นๆที่ใช้สำหรับหน้านี้เท่านั้นต่อท้าย (ภายใต้ /*Another style especially for …*/)

จากโค้ดทั้ง 3 ชุดด้านบน .. จะเห็นคำสั่ง @import ‘components/_xx.scss’; แล้วแบบนี้มันก็เหมือนการ import css ไฟล์ที่ Google Pagespeed ไม่ชอบน่ะสิ !!??

คำตอบคือไม่เหมือนกันอย่างสิ้นเชิง เพราะจำนวนไฟล์ของ SCSS ไม่ได้มีผลกับ CSS หลังการ Compile

คำสั่ง @import ไฟล์ที่ขึ้นต้นด้วย _ (under score) ใน SCSS คืออะไร?

.
.

@import ใน SCSS จะใช้งานเหมือน CSS ในกรณีที่ไฟล์ที่ถูก import เข้ามา “ไม่ได้ถูกขึ้นต้นด้วย “_” (under score)

นั่นคือมันก็คือการเรียกไฟล์ต่อๆกัน ในแบบที่ Google Pagespeed ไม่แนะนำ เพราะทำให้เกิด HTTP Request ที่เยอะเกินไป

แต่ถ้าเราตั้งชื่อไฟล์ .SCSS หรือ .css แล้วนำหน้าด้วยเครื่องหมาย under score (_), SCSS จะเข้าใจว่า เราต้องการ compile ไฟล์นั้นแล้วต่อท้ายด้วย CSS Property อื่นๆในหน้านั้น

อธิบายแบบนี้คงยังมองภาพไม่ออก เราไปดูความแตกต่างกันดีกว่า ว่าการ @import ไฟล์ที่มี _ นำหน้า กับไม่มีต่างกันยังไง

ผลการ Compile about.scss ที่ทำการ @import ไฟล์ css ที่ไม่มีเครื่องหมาย under score นำหน้า จะเห็นว่าหลังการ compile มันก็ยัง import ไฟล์ไปข้างนอกอยู่ดี (Pagespeed ไม่ชอบ)
ผลการ Compile about.scss ที่ทำการ @import ไฟล์ css ที่มีเครื่องหมาย under score นำหน้า

จากตัวอย่างด้านบน จะเห็นได้ว่าตัวอย่างในรูปที่ 2 จะเป็นการ compile ไฟล์ base.scss เข้ามาอยู่เสมือนเป็นการเขียนในไฟล์ about.scss ที่เดียวกัน ไม่ใช่การ @import css มาอีกทอดนึง

เพราะเครื่องหมาย under score แล้วนำหน้าไฟล์ .scss จะมีไว้เพื่อบ่งบอกว่า ให้ทำการ include หรือรวม css ในไฟล์นั้น เข้ากับไฟล์ปัจจุบันที่เรียกใช้มันอยู่ไปเลย ทำให้ผลลัพธ์จากการ compile ถูกรวมเป็นไฟล์เดียว นั่นคือ about.scss โดยอัตโนมัติ

แล้วทำไมเราต้องแยก .scss เป็นแบบย่อยละเอียดยิบแบบนั้นด้วยล่ะ ?

ก่อนอื่นเรามาดูผลสรุปก่อนว่า ในโจทย์ตัวอย่างเราจะได้ structure ของ .scss ทั้งหมดเป็นดังภาพ

ไฟล์ .SCSS ทั้งหมดสำหรับโจทย์ด้านบน

ทีนี้ให้นึกย้อนไปว่า สมมติเราย้าย CSS ที่ควบคุม carousel ไปไว้ในไฟล์ที่มันถูกใช้โดยตรง เช่น homepage.scss และ portfolio.scss แทนที่จะแยกมันออกมาเขียนไว้ใน _carousel.scss

แต่วันนึง… เราอยากจะแก้ไข carousel ทั้งสองหน้าให้แสดงผลในอีกรูปแบบนึง..
.
.

สิ่งที่เราต้องทำ ก็คือการเข้าไปแก้ไฟล์ homepage.scss และ portfolio.scss ทั้งสองไฟล์ เพราะเราดันฝัง css ที่ควบคุม carousel ไว้ในสองไฟล์นี้ทั้งคู่ ซึ่งเสียเวลามาก…

.
.

ดังนั้น ถ้าเราแยก carousel.scss ออกมาเป็นอีก 1 Components ในอนาคตที่เราจะต้องแก้อะไรอะไร เราก็แค่เข้าไปแก้ _carousel.scss ไฟล์ที่เดียว จุดเดียวก็จบแล้ว

สงสัยต่อ !!! แล้วถ้าเราเอาไปวางไว้ใน base.scss ล่ะ มันก็ใช้ร่วมกันได้ เวลาจะแก้ ก็เข้าไปแก้ใน _base.scss ทีเดียวจบเหมือนกัน

คำตอบก็คือ “ได้นะ” .. แต่ในไฟล์ที่ไม่ต้องการใช้ carousel ก็กลายเป็นต้อง ติด CSS Carousel ตัวนี้ไปด้วยโดยปริยาย เช่น about.scss ที่ @import _base.scss เข้ามา

แล้วยิ่งถ้ามีหลายๆ components มากๆ .. ที่ไม่ได้ใช้แต่กลับโดนเรียกบ่อยๆ มันก็ทำให้ css เราบวมขึ้นเรื่อยๆ .. เปลือง Bandwidth เกินความจำเป็น

ดังนั้น ในการเขียนแยก Component คุณจะต้องกลับไปที่เงื่อนไขข้างต้นว่า “อะไรที่ใช้ร่วมกันทุกหน้า และอะไรที่ใช้แค่หน้าเดียว” คุณต้องแยกออกจากกันให้ดีที่สุด

เพราะผลลัพธ์ที่ออกมา คุณมีแต่ได้มากกว่าเสีย

  • ประหยัดเวลาในการแก้ไข
  • ไม่งง .. จะแก้ จะคัดลอก จะเพิ่มเติมเมื่อไหร่ก็ได้
  • โครงสร้าง CSS เป็นไปในรูปแบบเดียวกัน จะมาเขียนต่อ หรือเพิ่มสักกี่คน ก็ยังเป็น structure เดิม
  • ถ้าคุณแยก components ดีๆ .. จะทำให้ css สุดท้ายที่เรียกใช้จริงๆ ลดขนาดไฟล์ลงไปมาก เพราะขจัดสิ่งที่ไม่จำเป็นออกไปเรียบร้อยแล้ว
  • ทีม Programmer ที่เอางานไปทำต่อ ไม่ได้รับผลกระทบ .. เพราะไฟล์ที่เรียกใช้จริงๆ มีแค่ 3 ไฟล์ .. ได้แก่ homepage.css/portfolio.css และ about.css ส่วนกระบวนการ @import หลังบ้าน แยกออกจากกัน เป็นหน้าที่ของ Front end ในการจัดการ
  • สามารถทำ critical css ได้อย่างง่ายดาย (Above the Fold) ขออธิบายตอนหน้านะ

โปรดติดตามตอนต่อไป

Author: AbaiyaMook