• สาเหตุสำคัญของประสิทธิภาพเว็บไซต์ที่แย่ลงในช่วงหลังคือ การใช้ JavaScript มากเกินไป และสคริปต์ติดตามต่าง ๆ ซึ่งในหลายกรณีสามารถแทนที่ได้ด้วย HTML/CSS เพียงอย่างเดียว
  • ฟีเจอร์ที่เพิ่งเพิ่มเข้ามาเมื่อไม่นานนี้ เช่น CSS nesting, relative colors, หน่วย viewport แบบใหม่ (lvh, svh, dvh) ช่วยให้แก้ปัญหาที่แต่ก่อนต้องพึ่งพา JS หรือ preprocessor ได้อย่างง่ายดาย
  • CSS ไม่ใช่แค่เครื่องมือจัดสไตล์ธรรมดา แต่เป็นภาษาที่ทรงพลังซึ่งสามารถสร้างได้ตั้งแต่ แอนิเมชัน, การตรวจสอบข้อมูลนำเข้า, ธีม dark mode, ไปจนถึงเมนู accordion
  • ในด้านประสิทธิภาพ CSS ยังทำงานด้วยการเร่งผ่าน GPU และทำงานบนเธรดแยก จึง ลื่นไหลและมีประสิทธิภาพกว่า JS สำหรับแอนิเมชันและเอฟเฟกต์เปลี่ยนผ่าน
  • ผู้เขียนเน้นว่า CSS ไม่ได้เป็นเพียงเครื่องมือเชิงปฏิบัติ แต่ยังเป็น สื่อของการแสดงออกและศิลปะ และแนะนำให้นักพัฒนาเว็บใช้ศักยภาพของ CSS ยุคใหม่ให้มากขึ้น

บทนำ: ความซับซ้อนของเว็บ และความพยายามครั้งใหม่

  • หลายเว็บไซต์กำลังเผชิญกับปัญหาประสิทธิภาพและความซับซ้อนจากการใช้ JavaScript framework มากเกินไป
    • แอป React ใช้เวลาหลายวินาทีในการโหลด และ NextJS ก็ก่อให้เกิด hydration error
    • โฟลเดอร์ node_modules กินพื้นที่หลายกิกะไบต์
  • แม้ไม่มี JavaScript ก็ยังสามารถสร้างฟังก์ชันที่ทรงพลังได้ด้วย HTML และ CSS เพียงอย่างเดียว
    • นอกเหนือจากรถเข็นช็อปปิงของเว็บอีคอมเมิร์ซที่ซับซ้อนหรือแดชบอร์ดแล้ว JavaScript อาจไม่ได้จำเป็นเสมอไป
  • บทความนี้แนะนำ ฟีเจอร์ใหม่ล่าสุด ของ CSS และชวนให้นักพัฒนาสำรวจความเป็นไปได้ที่หลากหลายโดยไม่ต้องพึ่งพา JavaScript เพียงอย่างเดียว

ความเข้าใจผิดและมุมมองต่อ CSS

CSS ยากและใช้งานลำบากจริงหรือ?

  • มุมมองเชิงลบต่อ CSS มักเกิดจาก การเรียนรู้พื้นฐานไม่เพียงพอ
    • นักพัฒนาจำนวนมากข้ามพื้นฐานของ CSS แล้วไปโฟกัสที่ JavaScript หรือ TypeScript
    • CSS ไม่ใช่แค่เครื่องมือจัดสไตล์ธรรมดา แต่เป็น ภาษาเฉพาะทาง (domain-specific language) ที่มีความสามารถสูง
  • CSS สามารถทำเลย์เอาต์ที่ซับซ้อนได้ง่ายด้วยเครื่องมืออย่าง flexbox
    • ตัวอย่าง: ใช้ display: flex และ justify-content: center เพื่อจัด div ให้อยู่กึ่งกลางได้อย่างง่ายดาย
    • เครื่องมือนักพัฒนา ของเบราว์เซอร์มีวิดเจ็ตสำหรับปรับคุณสมบัติ flexbox แบบมองเห็นได้
  • หากเจาะลึกอยู่ฝั่งเดียวเท่านั้น (เช่น JS) และละเลย CSS ก็เป็นธรรมดาที่จะรู้สึกว่ามันเป็นภาระ

ความเจ็บปวดของการเขียน CSS และการเปลี่ยนแปลง

  • ในอดีตการเขียน CSS ไม่ได้สะดวกนัก จึงเกิดเครื่องมืออย่าง Sass และ Tailwind ขึ้นมา
    • ตัวอย่าง: ต้องคอยจัดการ selector chain ที่ยาวอย่าง .post > .buttons .like:hover
  • ช่วงหลังมีการเพิ่ม ฟีเจอร์ที่ช่วยยกระดับคุณภาพการเขียน (เช่น nesting) ทำให้พัฒนาได้สบายขึ้นด้วย CSS พื้นฐานเพียงอย่างเดียว
    • CSS nesting ช่วยรวมสไตล์ที่เกี่ยวข้องไว้ในที่เดียวและเพิ่มความอ่านง่าย
      • ตัวอย่าง: .post { & > .buttons { .like { &:hover { ... } } } }
      • ความสัมพันธ์ระหว่าง parent-child ชัดเจนขึ้น ทำให้ใช้ชื่อคลาสที่สั้นและเรียบง่ายได้
  • relative colors ทำให้การปรับแต่งสีง่ายขึ้น
    • สามารถปรับความสว่างได้ด้วย hsl(from #123456 h s calc(l + 10))
    • ใช้ color-mix() เพื่อผสมสองสีและสร้างสีแบบไดนามิก
  • ไวยากรณ์ช่วงของ media query ทำให้ตั้งเงื่อนไขที่เข้าใจง่ายอย่าง (width <= 768px) ได้
  • หน่วย lh รองรับการจัดสไตล์ให้สอดคล้องกับความสูงบรรทัด
  • พร็อพเพอร์ตี scrollbar-gutter ช่วยแก้ปัญหาเลย์เอาต์ขยับเพราะสกรอลล์บาร์
  • Baseline ช่วยรับประกันความเข้ากันได้ของฟีเจอร์กับเบราว์เซอร์หลัก
    • newly available คือฟีเจอร์ที่ทำงานได้ในเบราว์เซอร์รุ่นล่าสุด
    • widely available คือรองรับไปถึงเบราว์เซอร์เมื่อ 2.5 ปีก่อน
    • ตัวอย่าง: CSS nesting ได้รับการรองรับจากทุกเบราว์เซอร์ตั้งแต่เดือนธันวาคม 2023

ทำไมจึงพัฒนาโดยใช้ CSS/HTML เท่านั้น?

  • ผู้ใช้บางส่วน ปิดการทำงานของ JavaScript เป็นค่าเริ่มต้น (ด้วยเหตุผลด้านความปลอดภัย ความเป็นส่วนตัว ฯลฯ)
  • หากให้บริการเว็บไซต์ด้วย CSS/HTML ล้วน ผู้ใช้เหล่านี้ก็มีโอกาสใช้งานเว็บไซต์ได้มากขึ้น
  • ทั้งในมุมของนักพัฒนาและผู้ใช้ การใช้เพียง CSS/HTML มี ข้อดี มากในด้านความเร็ว การเข้าถึง และการใช้ CPU/แบตเตอรี่
    • CSS animation ทำงานบน compositor thread จึงลดภาระของ CPU
    • JavaScript ทำงานผ่าน event loop จึงอาจเกิดความหน่วงเล็กน้อยได้
  • การเข้าถึง และ ความสะดวกในการใช้งาน ดีขึ้น
    • เอฟเฟกต์ hover ของปุ่ม, toast animation, การตรวจสอบข้อมูลนำเข้า ฯลฯ สามารถทำได้ง่ายด้วย CSS

ตัวอย่างการใช้งานจริงและฟีเจอร์สำคัญของ CSS

สร้างแอนิเมชันเริ่มต้นที่เป็นธรรมชาติด้วย @starting-style

  • ก่อนหน้านี้การทำแอนิเมชันตอนองค์ประกอบปรากฏขึ้นต้องใช้โครงสร้างที่ซับซ้อน เช่น keyframes หรือ JS trigger
  • การมาของ @starting-style ทำให้กำหนดสถานะเริ่มต้นได้ง่ายขึ้น และสร้างแอนิเมชันสถานะเริ่มต้นขององค์ประกอบ (เช่น fade-in) ได้สะดวก
    • ตั้งค่าได้ด้วย transition: opacity 1s; @starting-style { opacity: 0; }
    • ทำงานได้โดยไม่ต้องมี @keyframes หรือ JavaScript เพิ่มเติม
  • เพียงระบุสถานะเริ่มต้นร่วมกับ transition ก็จะได้แอนิเมชันที่เป็นธรรมชาติ
    • ตัวอย่าง: เปลี่ยนความทึบและตำแหน่งของข้อความ toast ได้อย่างนุ่มนวล

ตั้งค่าธีม dark/light mode ได้ง่าย

  • color-scheme: light dark สลับธีมอัตโนมัติตามความชอบของผู้ใช้
  • ฟังก์ชัน light-dark(#000, #FFF) ใช้กำหนดสีให้เหมาะกับโหมดสว่าง/มืด
  • รองรับการเลือกธีมด้วยปุ่มวิทยุและ selector :has
    • สลับธีมได้ด้วย CSS เพียงอย่างเดียวโดยไม่ต้องใช้ JavaScript
    • จะเพิ่ม JavaScript เพื่อบันทึก/โหลดธีมแบบเลือกใช้ก็ได้

สร้าง UI แบบกำหนดเองด้วย radio/checkbox และ :has, :checked

  • อินเทอร์แอ็กชันที่ซับซ้อนอย่างแท็บ, accordion, toggle ก็ ทำได้โดยไม่ใช้ JavaScript
  • ปุ่มวิทยุ สามารถจัดสไตล์เองได้ด้วย :checked และ :has
    • ตัวอย่าง: label:has(input:checked) เพื่อกำหนดสไตล์ของปุ่มที่ถูกเลือก
    • ซ่อน input ด้วย opacity: 0 แต่ยังคงการเข้าถึงสำหรับโปรแกรมอ่านหน้าจอไว้ได้
  • องค์ประกอบ details เหมาะสำหรับสร้าง เมนู accordion อย่าง FAQ
    • ใช้แอตทริบิวต์ name เพื่อควบคุมให้เปิดได้ครั้งละรายการเดียว
    • สามารถเพิ่มแอนิเมชันตามสถานะ [open] ได้

การตรวจสอบข้อมูลนำเข้าและการสะท้อนสถานะ

  • การใช้แอตทริบิวต์ HTML เช่น pattern, required ร่วมกับ CSS pseudo-class (:valid, :invalid, :user-valid ฯลฯ) ช่วยให้ ตรวจสอบแบบเรียลไทม์และแสดงผลตอบกลับทางภาพ ได้
  • ปรับปรุงประสบการณ์ผู้ใช้ด้วยการเปลี่ยนสไตล์ outline/border ของช่องกรอกข้อมูล เป็นต้น
  • ใช้ แอตทริบิวต์ pattern ของ HTML เพื่อตรวจสอบความถูกต้องของช่องกรอกข้อมูล
    • ตัวอย่าง: \w{3,16} อนุญาตตัวอักษร/ตัวเลข/ขีดล่าง 3–16 ตัว
  • ใช้ :valid และ :invalid ของ CSS เพื่อจัดสไตล์ตามสถานะความถูกต้อง
    • :user-valid และ :user-invalid จะใช้สไตล์ก็ต่อเมื่อผู้ใช้ได้ป้อนข้อมูลแล้วเท่านั้น
  • ใช้ selector :has เพื่อจัดสไตล์องค์ประกอบอื่นตามสถานะของ input ได้
  • ในบางกรณี (เช่น เงื่อนไขอินพุตที่ซับซ้อน) อาจยังต้องใช้ JS แต่ส่วนใหญ่ CSS/HTML ก็เพียงพอ

วิธีใช้หน่วย viewport ให้ถูกต้อง

  • หน่วย vw/vh มี ปัญหาความแม่นยำ บนมือถือเมื่อแถบที่อยู่ (navigation bar) ปรากฏหรือซ่อน
  • แนะนำให้ใช้หน่วย viewport รุ่นใหม่อย่าง lvh/svh/dvh (largest/smallest/dynamic viewport height)
    • lvh: สำหรับเต็มหน้าจอ (เช่น พื้นหลังเต็มจอ)
    • svh: เหมาะกับปุ่มหรือลิงก์ที่ต้องมองเห็นบนหน้าจอเสมอ
    • dvh: จัดสรรขนาดแบบยืดหยุ่นตามการเปลี่ยนแปลง เช่น การเลื่อนหน้าจอ
  • การซ้อนทับของคีย์บอร์ดจัดการได้ด้วยพร็อพเพอร์ตี interactive-widget หรือ VirtualKeyboard API
    • &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, interactive-widget=resizes-content&quot;&gt;
    • ในเบราว์เซอร์ที่ใช้ Chromium สามารถใช้ navigator.virtualKeyboard.overlaysContent = true

Wishlist ของ CSS (สิ่งที่ยังน่าเสียดายหรืออยากให้มี)

  • บล็อกที่นำกลับมาใช้ซ้ำได้: ใช้คลาสอื่นภายในคลาส (เช่น @apply border)
  • selector ของ media query ที่รวมกันได้: ผสาน @media กับ class selector
  • ตัวแปร nth-child: span { --nth: nth-child(); } สำหรับจัดสไตล์แบบไดนามิก
  • selector nth-letter: จัดสไตล์อักษรบางตัวโดยเฉพาะ (เช่น p::nth-letter(2))
  • การลบหน่วย: สร้างค่าที่ไม่มีหน่วยด้วย calc(100vw / 1px)
  • ฟังก์ชัน image(): รองรับสีสำรองและชิ้นส่วนภาพ
  • แท็ก style ภายใน body: หากรองรับเป็นมาตรฐานทางการ จะช่วยบรรเทาปัญหา FOUC

ปิดท้าย: CSS และความเป็นศิลปะของเว็บ

  • CSS ไม่ใช่แค่เครื่องมือ แต่เป็นสื่อของ การแสดงออกเชิงสร้างสรรค์
  • เครื่องมือ AI หรือ build chain (linter, เครื่องมือ minify) อาจจำกัดความคิดสร้างสรรค์ได้
  • CSS ตอบโจทย์ได้พร้อมกันทั้ง ประสิทธิภาพ, การเข้าถึง, และ การแสดงออกทางศิลปะ
  • บทความนี้เขียนด้วย HTML/CSS ที่ไม่มี JavaScript ขนาดประมาณ 49kB
    • วิดเจ็ตแบบโต้ตอบและองค์ประกอบภาพทั้งหมดทำขึ้นด้วยมือ
    • ตัวอย่าง: เกมคลิกด้วย CSS แสดงให้เห็นถึงความเป็นไปได้ของ CSS ในฐานะภาษาการเขียนโปรแกรม

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น