เอกสารนี้มีการวิเคราะห์เชิงลึกของโซลูชัน CSS-in-JS ปัจจุบันทั้งหมดซึ่งรองรับ การแสดงผลด้านเซิร์ฟเวอร์ และ typeScript
การอ้างอิงพื้นฐานที่เราจะใช้สำหรับการเปรียบเทียบเป็นวิธี โมดูล CSS
เราใช้ next.js เป็นกรอบ SSR สำหรับการสร้างทรัพยากร
สิ่งสำคัญสุดท้ายคือประเภทความปลอดภัยที่มีการรองรับ typescript แบบเต็ม
- อัปเดตล่าสุด: ส.ค. 2021
- ในการรับภาพรวมที่สั้นลงคุณสามารถชำระเงิน บทความเกี่ยวกับเคล็ดลับ CSS :
https://css-tricks.com/a-thorough-analysis-of-css-in-js/
- หากคุณต้องการวิดีโอแทนคุณสามารถเช็คเอาต์ การพูดคุยของฉันจาก ngpartycz :
https://www.youtube.com/watch?v=C7UWGHRAX9A
โปรดชำระเงินเป้าหมายและข้อจำกัดความรับผิดชอบของเราก่อนที่จะข้ามไปสู่ข้อสรุป
โมดูล ภาษา CSS และ CSS มีข้อ จำกัด บางประการโดยเฉพาะอย่างยิ่งหากเราต้องการมีรหัสประเภทที่ปลอดภัย ข้อ จำกัด เหล่านี้บางอย่างมีวิธีแก้ปัญหาที่ เปลี่ยนแปลง ไป
สไตล์ไม่สามารถอยู่ร่วมกับส่วนประกอบได้
นี่อาจเป็นเรื่องน่าหงุดหงิดเมื่อเขียนส่วนประกอบเล็ก ๆ จำนวนมาก แต่ไม่ใช่ตัวทำลายข้อตกลง อย่างไรก็ตามประสบการณ์ในการย้ายไปมาระหว่างไฟล์ component.js และไฟล์ component.css ค้นหาชื่อชั้นเรียนที่กำหนดและไม่สามารถ "ไปที่คำจำกัดความสไตล์" ได้อย่างง่ายดายเป็นข้อเสียในการผลิตที่สำคัญ
สไตล์ pseudos และการสืบค้นสื่อต้องมีการทำซ้ำตัวเลือก
ข้อเท็จจริงที่น่าผิดหวังอีกประการหนึ่งคือความจำเป็นในการทำซ้ำคลาส CSS ของเราเมื่อกำหนด คลาสและองค์ประกอบหลอก หรือ การสืบค้นสื่อ เราสามารถเอาชนะข้อ จำกัด เหล่านี้ได้โดยใช้ตัวประมวลผล preprocessor CSS เช่น SASS น้อยกว่าหรือสไตลัส ที่รองรับ & ตัวเลือกหลักช่วยให้ การออกแบบตามบริบท
. button {}
/* duplicated selector declaration for pseudo classes/elements */
. button : hover {}
. button :: after {}
@media ( min-width : 640 px ) {
/* duplicated selector declaration inside media queries */
. button {}
} การใช้งานสไตล์ถูกตัดการเชื่อมต่อจากคำจำกัดความของพวกเขา
เราไม่ได้รับ IntelliSense ด้วยโมดูล CSS ของคลาส CSS ที่กำหนดไว้ในไฟล์ component.css ทำให้ การคัดลอก เป็นเครื่องมือที่จำเป็นลด DX นอกจากนี้ยังทำให้ refactoring ยุ่งยากมาก เนื่องจากขาดความปลอดภัย
การใช้โทเค็นการออกแบบประเภทที่ปลอดภัยใน CSS นั้นไม่ใช่เรื่องสำคัญ
โทเค็นการออกแบบใด ๆ ที่กำหนดไว้ใน JS/TS (เพื่อรับประโยชน์จากประเภทความปลอดภัย) ไม่สามารถใช้โดยตรงใน CSS
มีวิธีแก้ปัญหาอย่างน้อย 2 ข้อสำหรับปัญหานี้ทั้งคู่ไม่มีความสง่างาม:
.module.css.cssมีเป้าหมายเฉพาะที่เรากำลังมองหาด้วยการวิเคราะห์นี้:
มีความเฉพาะเจาะจงมากขึ้นเราต้องการสัมผัสกับการใช้โซลูชั่น CSS-in-JS ต่างๆเกี่ยวกับ:
props ส่วนประกอบ (aka. ตัวแปรส่วนประกอบ) หรือจากอินพุตของผู้ใช้การวิเคราะห์นี้มีวัตถุประสงค์เพื่อ วัตถุประสงค์ และ ไม่ได้รับการแนะนำ :
- สิ่งที่คุณไม่พบที่นี่?
- คุณจะพบอะไรที่นี่?
ห้องสมุดจะไม่ถูกนำเสนอในลำดับใด ๆ หากคุณสนใจ ประวัติย่อของ CSS-in-JS คุณควรชำระเงินในอดีตปัจจุบันและอนาคตของการพูดคุยอย่างลึกซึ้งของ CSS-in-JS โดย Max Stoiber
| 1. ตำแหน่งร่วม | 2. DX | 3. tag` ` | 4. { } | 5. TS | 6. & CTX | 7. การทำรัง | 8. ธีม | 9. .css | 10. <style> | 11. อะตอม | 12. className | 13. <Styled /> | 14. css Prop | 15. ไม่เชื่อเรื่องพระเจ้า | 16. ขนาดหน้าเดลต้า | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| โมดูล CSS | - | |||||||||||||||
| JSX สไตล์ | - | - | +2.8 kB / +12.0 kB | |||||||||||||
| ส่วนประกอบสไตล์ | - | +13.4 kB / +39.0 kB | ||||||||||||||
| อารมณ์ | +6.5 kB / +20.0 kB | |||||||||||||||
| รูปแบบ | - | +2.1 kB / +8.0 kB | ||||||||||||||
| ฟีลา | - | - | - | +11.9 kB / +43.0 kB | ||||||||||||
| เย็บแผล | - | +5.3 kB / +17.0 kB | ||||||||||||||
| JSS | - | - | +18.2 kB / +60.0 kB | |||||||||||||
| คนโง่ | - | +1.1 kB / +4.0 kB | ||||||||||||||
| ซึ่งรวบรวม | - | +3.5 kB / +9.0 kB | ||||||||||||||
| ประเทศลิเนียเรีย | +2.7 kB / +6.0 kB | |||||||||||||||
| วานิลลา-สกัด | - | +0.0 kB / -2.0 kB |
ความสามารถในการกำหนดรูปแบบภายในไฟล์เดียวกับส่วนประกอบ โปรดทราบว่าเราสามารถแยกรูปแบบออกเป็นไฟล์แยกต่างหากและนำเข้าได้ในกรณีที่เราชอบ
⬆ถึงภาพรวม
หมายถึง ประสบการณ์นักพัฒนา ซึ่งรวมถึง 2 ด้านหลัก:
⬆ถึงภาพรวม
tag` ` (เทมเพลตที่ติดแท็ก)สนับสนุนการกำหนด รูปแบบเป็นสตริง โดยใช้เทมเพลต ES Tagged:
kebab-case สำหรับชื่อคุณสมบัติเช่นเดียวกับไวยากรณ์ CSS ธรรมดาstring ธรรมดา⬆ถึงภาพรวม
{ } (รูปแบบวัตถุ)สนับสนุนการกำหนด รูปแบบเป็นวัตถุ โดยใช้วัตถุจาวาสคริปต์ธรรมดา:
camelCase สำหรับชื่อคุณสมบัติเช่นที่เราทำใน React Native;⬆ถึงภาพรวม
การสนับสนุน TypeScript ทั้งในตัวหรือผ่าน @types แพ็คเกจซึ่งควรรวมถึง:
Props ทั่วไปที่เกี่ยวข้อง (รับการเข้าถึงประเภทที่ปลอดภัยสำหรับส่วนประกอบอุปกรณ์ประกอบฉากเมื่อกำหนดรูปแบบไดนามิก);⬆ถึงภาพรวม
& CTX (สไตล์บริบท)สนับสนุน สไตล์บริบท ช่วยให้เราสามารถกำหนด คลาสและองค์ประกอบหลอก และ การสืบค้นสื่อ ได้อย่างง่ายดายโดยไม่จำเป็นต้องทำซ้ำตัวเลือกตามที่ต้องการใน CSS ธรรมดา:
& Parent Selector;⬆ถึงภาพรวม
สนับสนุน ตัวเลือกที่ซ้อนกันโดยพลการ :
⬆ถึงภาพรวม
การสนับสนุนในตัวสำหรับการจัดการหรือจัดการโทเค็นสำหรับระบบการออกแบบ
เรา ยังไม่ได้ทดสอบคุณสมบัตินี้ ดังนั้นเราจึงจดบันทึกว่าห้องสมุดที่แสดงการสนับสนุนในเอกสารของพวกเขาเท่านั้น
⬆ถึงภาพรวม
.css (สกัด CSS แบบคงที่) รูปแบบที่กำหนดจะถูกแยกออกเป็นไฟล์ .css แบบคงที่:
⬆ถึงภาพรวม
<style> แท็ก รูปแบบที่กำหนดจะถูกฉีดเข้าไปในแท็ก <style> ในเอกสารของเอกสาร <head> ::
⬆ถึงภาพรวม
ความสามารถในการสร้าง คลาส Atomic CSS ซึ่งจะเป็นการเพิ่มความสามารถในการใช้ซ้ำสไตล์และลดการทำซ้ำ:
⬆ถึงภาพรวม
className Library API ส่งคืน string ที่เราต้องเพิ่มลงในองค์ประกอบหรือองค์ประกอบของเรา
⬆ถึงภาพรวม
<Styled /> API สร้างส่วนประกอบ wrapper (หรือ Styled ) ซึ่งรวมถึง className ที่สร้างขึ้น:
StyledButton หรือ StyledList แทนที่จะเป็นค่าคงที่เช่น button_styles หรือ list_styles ดังนั้นเกี่ยวกับการตั้งชื่อมันเป็นสิ่งเดียวกัน⬆ถึงภาพรวม
css Prop อนุญาตให้ผ่านสไตล์โดยใช้เสา css พิเศษคล้ายกันว่าเราจะกำหนดสไตล์อินไลน์ แต่ไลบรารีสร้างชื่อคลาส CSS ที่ไม่ซ้ำกันเบื้องหลัง:
⬆ถึงภาพรวม
อนุญาตให้ใช้งานโดยไม่ต้องหรือด้วยกรอบใด ๆ ห้องสมุดบางแห่งถูกสร้างขึ้นโดยเฉพาะสำหรับการตอบสนองเท่านั้น
หมายเหตุ : ห้องสมุดบางแห่งเช่น การเย็บแผล หรือเอกสาร ทางอารมณ์ เพียงแค่ตอบสนองการใช้งานเท่านั้นแม้ว่าพวกเขาจะมี แกนกลาง ที่ไม่เชื่อฟังเฟรมเวิร์ก
⬆ถึงภาพรวม
ความแตกต่างของขนาดหน้าทั้งหมดใน KB (ถ่ายโอน gzipped & minified / unpressed & minified) เมื่อเทียบกับ โมดูล CSS สำหรับการผลิตหน้าดัชนีทั้งหมดโดยใช้ Next.js:
หมายเหตุ: การสร้างทั้งหมดทำด้วย next.js 11.1.0 และค่าที่นำมาจากแท็บเครือข่าย Chrome Devtools ถ่ายโอนผ่านเครือข่ายกับขนาดทรัพยากร
⬆ถึงภาพรวม
การสังเกตต่อไปนี้ใช้สำหรับการแก้ปัญหาทั้งหมด (มีข้อยกเว้นเล็กน้อย)
ส่วนประกอบที่ใช้ในเส้นทางที่เฉพาะเจาะจงจะถูกรวมเข้าด้วยกันสำหรับเส้นทางนั้นเท่านั้น นี่คือสิ่งที่ next.js ทำงานนอกกรอบ
โซลูชั่นทั้งหมดเสนอวิธีการกำหนดรูปแบบระดับโลกบางอย่างด้วย API เฉพาะ
โซลูชันทั้งหมดให้การสนับสนุนการเรนเดอร์ฝั่งเซิร์ฟเวอร์และง่ายต่อการรวมเข้ากับ Next.js
โซลูชันทั้งหมดจะเพิ่มคำนำหน้าเฉพาะของผู้ขายโดยอัตโนมัตินอกกรอบ
โซลูชันทั้งหมดสร้างชื่อคลาสที่ไม่ซ้ำกันเช่นโมดูล CSS อัลกอริทึมที่ใช้ในการสร้างชื่อเหล่านี้แตกต่างกันมากระหว่างไลบรารี:
.heading จากส่วนประกอบ Card มักจะมี .Card_heading_h7Ys5 แฮช);.heading-0-2-1 , .input-0-2-2 0-2-2) หรือตัวอักษรตัวอักษร ( a, b, c, ... aa, ab, ac , ฯลฯ ) ทำให้วิธีการนี้มีประสิทธิภาพมากขึ้น ไม่มีวิธีแก้ปัญหาใด ๆ ที่สร้างสไตล์อินไลน์ซึ่งเป็นวิธีการเก่าที่ใช้โดยเรเดียมและความเย้ายวนใจ วิธีการนี้มีประสิทธิภาพน้อยกว่าคลาส CSS และไม่แนะนำให้เป็นวิธีหลักสำหรับการกำหนดรูปแบบ นอกจากนี้ยังหมายถึงการใช้ตัวจัดการเหตุการณ์ JS เพื่อกระตุ้นคลาสเทียมเนื่องจากสไตล์อินไลน์ไม่รองรับพวกเขา เห็นได้ชัดว่าโซลูชั่นที่ทันสมัยทั้งหมดทุกวันนี้ย้ายออกไปจากวิธีการนี้
โซลูชันทั้งหมดสนับสนุนคุณสมบัติ CSS ส่วนใหญ่ที่คุณต้องการ: คลาสและองค์ประกอบหลอก และ การค้นหาสื่อ และ keyframes เป็นสิ่งที่เราทดสอบ
โซลูชั่นส่วนใหญ่ทำการตลาดตัวเองว่าสามารถ "แยก CSS ที่สำคัญ" ในระหว่าง SSR โปรดทราบว่าสิ่งนี้ ไม่ได้อ้าง ถึงการสกัด CSS ที่สำคัญข้างต้นตามที่เราคิดไว้ในตอนแรก
สิ่งที่พวกเขาทำจริง:
ด้วย CSS แบบคงที่ 100% จะไม่มีประโยชน์ ด้วยหน้าแบบไดนามิกที่แสดงองค์ประกอบน้อยมากบนเซิร์ฟเวอร์และส่วนประกอบส่วนใหญ่จะแสดงผลแบบไดนามิกบนไคลเอนต์ผลประโยชน์จะเพิ่มขึ้น
ข้อยกเว้น : ห้องสมุดที่ใช้การสกัด CSS แบบคงที่
การทำความเข้าใจว่าคุณสมบัติเหล่านี้มีผลต่อการวัดเว็บหลักและตัวชี้วัดประสิทธิภาพโดยทั่วไปเป็นปัจจัยสำคัญอย่างยิ่งที่จะต้องพิจารณาและวิธีการส่งสไตล์ให้กับลูกค้าอาจมีผลกระทบมากที่สุดดังนั้นลองวิเคราะห์รายละเอียดนี้กันดีกว่า
นอกจากนี้ยังมีสถานการณ์ที่แตกต่างกัน 2 สถานการณ์ที่เราต้องพิจารณา:
.js , .css , สื่อ ฯลฯ ); .css การสกัดไฟล์ โซลูชันที่สร้างไฟล์ .css คงที่ซึ่งโดยปกติคุณจะรวมเป็นแท็ก <link> ใน <head> ของหน้าของคุณโดยทั่วไปแล้วการแสดงผลทรัพยากรที่ปิดกั้น สิ่งนี้ส่งผลกระทบอย่างมากต่อ FCP , LCP และตัวชี้วัดอื่น ๆ ที่ตามมา
- แคชเปล่า
หากผู้ใช้มีแคชที่ว่างเปล่าสิ่งต่อไปนี้จะต้องเกิดขึ้นส่งผล เสียต่อ FCP และ LCP :
<body> แม้ว่า HTML ทั้งหมดจะถูกโหลดไปแล้วและมันอาจจะแยกวิเคราะห์อย่างกระตือรือร้นและทรัพยากรบางอย่างถูกนำมาล่วงหน้าแล้ว มันเป็นความจริงที่คุณสามารถดึงข้อมูล คู่ขนาน อื่น ๆ <head> (ไฟล์ .css หรือไฟล์ .js เพิ่มเติม) แต่โดยทั่วไปแล้วจะเป็นวิธีปฏิบัติที่ไม่ดี
- แคชเต็มรูปแบบ
อย่างไรก็ตามในการเข้าชมครั้งต่อไปทรัพยากร .css ทั้งหมดจะถูกแคชดังนั้น FCP และ LCP จะได้รับผลกระทบในเชิงบวก
ประเด็นสำคัญ
โซลูชันนี้ดูเหมือนจะเหมาะสมกว่าเมื่อ:
.css ทั่วไปที่สามารถแคชได้เมื่อเยี่ยมชมหน้าอื่น ๆ<style> แท็กสไตล์การฉีด ในระหว่าง SSR รูปแบบจะถูกเพิ่มเป็นแท็ก <style> ใน <head> ของหน้า โปรดทราบว่าสิ่งเหล่านี้มักจะไม่รวมทุกรูปแบบที่จำเป็นสำหรับหน้าเว็บเพราะไลบรารีส่วนใหญ่ทำการสกัด CSS ที่สำคัญดังนั้น styles เหล่านี้ควรจะเล็กกว่าไฟล์ .css ทั้งหมดที่กล่าวถึงก่อนหน้านี้
- แคชเปล่า
เนื่องจากเราจัดส่ง CSS Bytes น้อยลงและพวกเขาจะถูก inlined ภายในไฟล์ .html สิ่งนี้จะส่งผลให้ FCP และ LCP เร็วขึ้น:
.css ดังนั้นเบราว์เซอร์จึงไม่ถูกบล็อก.js อื่น ๆ ทั้งหมดไปยังจุดสิ้นสุดของเอกสาร <head> จะไม่ทำคำขอใด ๆ ดังนั้นการแสดงผลจะเกิดขึ้นอย่างรวดเร็ว.css แบบคงที่:.js พร้อมกับส่วนประกอบระหว่างความชุ่มชื้น (ซึ่งรวมถึง CSS ที่สำคัญทั้งหมดที่จัดส่งภายในแท็ก <style> + อื่น ๆ ); - แคชเต็มรูปแบบ
เมื่อแคชของผู้ใช้เต็มไฟล์ .js เพิ่มเติมจะไม่ต้องดึงข้อมูลเนื่องจากแคชแล้ว
อย่างไรก็ตามหากหน้านั้นเป็น SSRED CSS ที่สำคัญที่ Inlined จะแสดงในแท็ก <style> ของเอกสารจะถูกดาวน์โหลดอีกครั้งเว้นแต่ว่าเราจะจัดการกับ HTML แบบคงที่ที่สามารถแคชได้เช่นกันหรือเราจัดการกับการแคช HTML ในโครงสร้างพื้นฐานของเรา
แต่โดยค่าเริ่มต้นเราจะจัดส่งไบต์พิเศษในทุกหน้าคำขอ HTTP ไม่ว่าจะแคชหรือไม่ก็ตาม
ประเด็นสำคัญ
โซลูชันนี้ดูเหมือนจะเหมาะสมกว่าเมื่อ:
โซลูชั่นส่วนใหญ่บอกว่าพวกเขา ลบรหัส/สไตล์ที่ไม่ได้ใช้ นี่เป็นเพียง ครึ่งจริง
รหัสที่ไม่ได้ใช้นั้นยากที่จะสะสมโดยเฉพาะอย่างยิ่งถ้าคุณเปรียบเทียบกับไฟล์ .css ธรรมดาที่เราเคยเขียน เมื่อสิบปีก่อน แต่เมื่อเปรียบเทียบกับโมดูล CSS ความแตกต่างก็ไม่ใหญ่ วิธีการแก้ปัญหาใด ๆ ที่เสนอตัวเลือกในการกำหนด ตัวเลือกโดยพลการ หรือ รูปแบบที่ซ้อนกัน จะรวมกันไม่ว่าจะใช้หรือไม่อยู่ในส่วนประกอบของเรา เราจัดการเพื่อจัดส่งสไตล์ SSR ที่ไม่ได้ใช้งานด้วยโซลูชันที่ทดสอบทั้งหมด
การกำจัดรหัสที่ไม่ได้ใช้จริงและเต็มรูปแบบนั้นยากที่จะนำไปใช้เนื่องจากไวยากรณ์ CSS ไม่ได้ตรวจสอบประเภทหรือวิเคราะห์แบบคงที่ นอกจากนี้ธรรมชาติของส่วนประกอบที่มีพลังทำให้เป็นไปไม่ได้ในบางสถานการณ์โดยเฉพาะอย่างยิ่งเมื่อมาร์กอัปถูกแสดงผลแบบไดนามิก:
& span : องค์ประกอบลูกหลาน;&:nth-child() : ตัวเลือก Pseudo บางตัว;& .bg-${color} : ตัวเลือกแบบไดนามิก;.parent & : ตัวเลือกหลัก;โดยพื้นฐานแล้วสิ่งที่เราได้รับคือการลบรหัสเมื่อเราลบส่วนประกอบหรือเราไม่นำเข้าอีกต่อไป นั่นคือพฤติกรรมโดยนัยเพราะสไตล์เป็นการพึ่งพาโดยตรงของส่วนประกอบ เมื่อส่วนประกอบหายไปสไตล์ของมันก็เช่นกัน
มี 2 วิธีในการฉีด CSS ลงใน DOM & อัปเดตจาก JavaScript:
<style> แท็ก (s) วิธีการนี้หมายถึงการเพิ่มแท็ก <style> หนึ่งแท็กหรือมากกว่าใน DOM (ไม่ว่าจะเป็น <head> หรือที่ไหนสักแห่งใน <body> ) โดยใช้. APPENDCHILD () เพื่อเพิ่มโหนด <style> นอกเหนือจาก. <style> , .innerHTML
<style> เพียงหนึ่งแท็กและอัปเดตเนื้อหาทั้งหมดอาจช้าในการอัปเดต DOM ทั้งหมดเมื่อเราเปลี่ยนกฎ CSS ชุดเล็ก ๆ เท่านั้นDEVELOPMENT เพราะให้ประสบการณ์การดีบักที่ดีขึ้นPRODUCTION ด้วย CSSStyleSheet API ใช้ครั้งแรกโดย JSS วิธีนี้ใช้ CSSStyleSheet.insertRule() เพื่อฉีดกฎ CSS ลงใน CSSOM โดยตรง
<style> ที่ว่างเปล่า<style>$0 ใน Chrome Devtools (หรือรับการอ้างอิงด้วยวิธีอื่นโดยใช้ DOM API);.sheet.cssRules บนแท็ก <style> เพื่อดูอาร์เรย์ของกฎ CSS ที่มีอยู่PRODUCTIONDEVELOPMENT เช่นกัน หากส่วนประกอบเดียวกันนำเข้า 2 เส้นทางที่แตกต่างกันมันจะถูกส่งสองครั้งไปยังไคลเอนต์ นี่เป็นข้อ จำกัด ของระบบ Bundler/Build ในกรณีของเรา next.js และ ไม่เกี่ยวข้องกับโซลูชัน CSS-in-JS
ใน next.js การแยกรหัสทำงานในระดับเส้นทางรวมส่วนประกอบทั้งหมดที่จำเป็นสำหรับเส้นทางที่เฉพาะเจาะจง แต่ตามบล็อกอย่างเป็นทางการและ web.dev หากมีการใช้ส่วนประกอบใน มากกว่า 50% ของหน้าควรรวมอยู่ในมัดคอม commons อย่างไรก็ตามในตัวอย่างของเราเรามี 2 หน้าแต่ละพวกเขานำเข้าองค์ประกอบ Button และรวมอยู่ในชุดแต่ละหน้าไม่ใช่ในชุด commons เนื่องจากรหัสที่จำเป็นสำหรับการจัดแต่งทรงผมนั้นมาพร้อมกับส่วนประกอบข้อ จำกัด นี้จะส่งผลกระทบต่อสไตล์เช่นกันดังนั้นจึงควรคำนึงถึงสิ่งนี้
นี่เป็นวิธีการที่เป็นที่ยอมรับเป็นผู้ใหญ่และมั่นคง ไม่ต้องสงสัยเลยว่ามันเป็นการปรับปรุงที่ดีกว่า BEM, SMACCS, OOCSS หรือวิธีการ CSS ที่ปรับขนาดได้อื่น ๆ เพื่อจัดโครงสร้างและจัดระเบียบ CSS ของเราโดยเฉพาะอย่างยิ่งในการใช้งานที่ใช้องค์ประกอบ
เปิดตัวใน ปี 2558 | กลับไปที่ภาพรวม
✅ การกรอกรหัสบริบทให้เสร็จสิ้น
✅ เฟรมเวิร์กไม่เชื่อเรื่องพระเจ้า
ไม่มีรูปแบบ/ส่วนประกอบร่วม
ไม่มีการรองรับ typescript
ไม่มี CSS อะตอม
ไม่มีการสนับสนุนรูปแบบ
วิธีการกำหนดสไตล์วิธีการ
สไตล์การทำรัง
รูปแบบใช้วิธีการ
classNamestyledcssรูปแบบเอาต์พุต
.css การสกัดไฟล์<style> การฉีดแท็กนี่คือพื้นฐานที่เราจะพิจารณาเมื่อเปรียบเทียบโซลูชัน CSS-in-JS ต่อไปนี้ทั้งหมด ชำระเงินแรงจูงใจเพื่อทำความเข้าใจข้อ จำกัด ของวิธีการนี้ที่เราพยายามเติมให้ดีขึ้น
| ถ่ายโอน / gzipped | ไม่บีบอัด | |
|---|---|---|
| ขนาดหน้าดัชนี | 76.7 KB | 233 kb |
Page Size First Load JS
┌ ○ / 2.19 kB 68.7 kB
├ └ css/1d1f8eb014b85b65feee.css 450 B
├ /_app 0 B 66.5 kB
├ ○ /404 194 B 66.7 kB
└ ○ /other 744 B 67.2 kB
└ css/1c8bc5a96764df6b92b4.css 481 B
+ First Load JS shared by all 66.5 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.40892d.js 555 B
├ chunks/webpack.ddd010.js 822 B
└ css/a92bf2d3acbab964f6ac.css 319 B
โซลูชันที่ง่ายมากไม่มีเว็บไซต์เฉพาะสำหรับเอกสารทุกอย่างอยู่ใน GitHub มันไม่ได้รับความนิยม แต่เป็นโซลูชันในตัวใน Next.js
เวอร์ชัน: 4.0 | ดูแลโดย Vercel | เปิดตัวใน ปี 2560 | ดูเอกสาร | ... กลับไปที่ภาพรวม
✅ สไตล์/ส่วนประกอบร่วม
- การกรอกรหัสบริบทให้เสร็จสมบูรณ์ : เพื่อให้ได้การไฮไลต์ไวยากรณ์และรหัสเสร็จสมบูรณ์จำเป็นต้องมีส่วนขยายตัวแก้ไข
- Typescript Support : @types สามารถติดตั้งเพิ่มเติมได้ แต่ API นั้นน้อยเกินไปที่จะต้องใช้ TS
ไม่มี CSS อะตอม
ไม่มีการสนับสนุนรูปแบบ
ไม่ใช่กรอบการไม่เชื่อเรื่องพระเจ้า
วิธีการกำหนดสไตล์วิธีการ
สไตล์การทำรัง
รูปแบบใช้วิธีการ
classNamestyledcssรูปแบบเอาต์พุต
.css แยกไฟล์<style> การฉีดแท็ก elements HTML ด้วยและสร้างชื่อคลาสที่ไม่ซ้ำกันสำหรับพวกเขา (ไม่แน่ใจว่ามันเป็นวิธีปฏิบัติที่ดีหรือไม่) โดยรวมแล้วเรารู้สึกเหมือนเขียน CSS ธรรมดาด้วยประโยชน์เพิ่มเติมของความสามารถในการกำหนดสไตล์พร้อมกับส่วนประกอบดังนั้นเรา จึงไม่จำเป็นต้องมีไฟล์. .css เพิ่มเติม อันที่จริงนี่คือปรัชญาของห้องสมุด: สนับสนุนไวยากรณ์ CSS ภายในไฟล์ส่วนประกอบ เราสามารถ ใช้ค่าคงที่ JS/TS ใด ๆ ของฟังก์ชั่น ที่มีการแก้ไขสตริง การทำงานกับ สไตล์แบบไดนามิกนั้นค่อนข้างง่าย เพราะมันเป็นจาวาสคริปต์ธรรมดาในที่สุด เราได้รับผลประโยชน์เหล่านี้ทั้งหมดในราคาที่ต่ำมากโดยมี ค่าใช้จ่ายที่ค่อนข้างเล็ก
ข้อเสียคือประสบการณ์โดยรวมของการเขียน CSS ธรรมดา โดยไม่ต้องทำรังสนับสนุน ชั้นเรียน/องค์ประกอบ Pseudo และการสืบค้นสื่อได้รับความยุ่งยากในการจัดการ
| ถ่ายโอน / gzipped | ไม่บีบอัด | |
|---|---|---|
| ขนาดหน้าดัชนี | 79.5 kb | 245 kb |
| กับโมดูล CSS | +2.8 kb | +12 kb |
Page Size First Load JS
┌ ○ / 2.65 kB 72.6 kB
├ /_app 0 B 70 kB
├ ○ /404 194 B 70.2 kB
└ ○ /other 1.18 kB 71.2 kB
+ First Load JS shared by all 70 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.a4b061.js 4.12 kB
└ chunks/webpack.61f1b6.js 778 B
แน่นอนว่าหนึ่งในโซลูชั่นที่ได้รับความนิยมและเป็นผู้ใหญ่มากที่สุดพร้อมเอกสารที่ดี มันใช้เทมเพลตที่ติดแท็กเพื่อกำหนดรูปแบบตามค่าเริ่มต้น แต่สามารถใช้วัตถุได้เช่นกัน นอกจากนี้ยังเป็นที่นิยมของวิธีการ styled ซึ่งสร้างส่วนประกอบใหม่พร้อมกับสไตล์ที่กำหนดไว้
เวอร์ชัน: 5.3 | ดูแลโดย Max Stoiber & อื่น ๆ | เปิดตัวใน ปี 2559 | ดูเอกสาร | ... กลับไปที่ภาพรวม
✅ สไตล์/ส่วนประกอบร่วม
✅ การสนับสนุน typescript : @types ต้องติดตั้งเพิ่มเติมผ่านทางแน่นอน
✅ สนับสนุนการสนับสนุนในตัว
✅ เฟรมเวิร์กไม่เชื่อเรื่องพระเจ้า
- การกรอกรหัสบริบทให้เสร็จ : ต้องมีส่วนขยาย/ปลั๊กอินตัวแก้ไข
ไม่มี CSS อะตอม
วิธีการกำหนดสไตล์วิธีการ
สไตล์การทำรัง
รูปแบบใช้วิธีการ
classNamestyledcss propรูปแบบเอาต์พุต
.css แยกไฟล์<style> การฉีดแท็ก Props ฯลฯ ) ส่วนประกอบสไตล์นำเสนอวิธีการใหม่ในการจัดแต่งทรงผมโดยใช้วิธี styled ซึ่งสร้างส่วนประกอบใหม่รวมถึงสไตล์ที่กำหนดไว้ เราไม่รู้สึกอยากเขียน CSS ดังนั้นมาจากโมดูล CSS เราจะต้องเรียนรู้วิธีการใหม่และโปรแกรมใหม่ ๆ เพื่อกำหนดสไตล์ เนื่องจากช่วยให้ทั้ง string และไวยากรณ์ object จึงเป็นโซลูชันที่ยืดหยุ่นได้ทั้งคู่สำหรับการย้ายรูปแบบที่มีอยู่ของเราและสำหรับการเริ่มต้นโครงการตั้งแต่เริ่มต้น นอกจากนี้ผู้ดูแลยังทำงานได้ดีมากในการติดตามนวัตกรรมส่วนใหญ่ในสาขานี้
อย่างไรก็ตามก่อนที่จะใช้มันเราต้องระวังว่ามันมาพร้อมกับค่าใช้จ่ายที่กำหนดสำหรับขนาดชุดของเรา
| ถ่ายโอน / gzipped | ไม่บีบอัด | |
|---|---|---|
| ขนาดหน้าดัชนี | 90.1 kb | 272 kb |
| กับโมดูล CSS | +13.4 kb | +39 kb |
Page Size First Load JS
┌ ○ / 2.52 kB 83.1 kB
├ /_app 0 B 80.6 kB
├ ○ /404 194 B 80.8 kB
└ ○ /other 1.06 kB 81.7 kB
+ First Load JS shared by all 80.6 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.731ace.js 14.7 kB
└ chunks/webpack.ddd010.js 822 B
อาจเป็นทางออกที่ครอบคลุมที่สุดและสมบูรณ์ที่สุด เอกสารรายละเอียดที่สร้างขึ้นอย่างเต็มที่ด้วย typeScript ดูเป็นผู้ใหญ่มากมีคุณสมบัติและได้รับการดูแลอย่างดี
เวอร์ชัน: 11.4 | ดูแลโดย Mitchell Hamilton & อื่น ๆ | เปิดตัวใน ปี 2560 | ดูเอกสาร | ... กลับไปที่ภาพรวม
✅ สไตล์/ส่วนประกอบร่วม
✅ การสนับสนุน typescript
✅ สนับสนุนการสนับสนุนในตัว
✅ การกรอกรหัสบริบทให้เสร็จ : สำหรับการใช้วิธีการ styled จำเป็นต้องใช้ปลั๊กอินตัวแก้ไขเพิ่มเติม
✅ เฟรมเวิร์กไม่เชื่อเรื่องพระเจ้า
ไม่มี CSS อะตอม
วิธีการกำหนดสไตล์วิธีการ
สไตล์การทำรัง
รูปแบบใช้วิธีการ
className (ใช้ @ementic/css)styledcss propรูปแบบเอาต์พุต
.css แยกไฟล์<style> การฉีดแท็ก css Prop นำเสนอการยศาสตร์ที่ยอดเยี่ยมในระหว่างการพัฒนาอย่างไรก็ตามดูเหมือนว่าจะเป็นวิธีการใหม่โดยใช้ React 17 การแปลง jsx ใหม่และการกำหนดค่าไม่สำคัญแตกต่างกันไปตามการตั้งค่าของคุณ styled จะเพิ่ม 3 kB ให้กับชุดของเราเพราะนำเข้าจากแพ็คเกจแยกต่างหากcss Prop & styled ) โดยเฉพาะ) อารมณ์โดยรวมดูเหมือนจะเป็นวิธีที่แข็งแกร่งและยืดหยุ่นมาก วิธีการ css Prop นวนิยายนำเสนอการยศาสตร์ที่ยอดเยี่ยมสำหรับนักพัฒนา การทำงานกับรูปแบบไดนามิกและ typescript นั้นค่อนข้างง่ายและใช้งานง่าย รองรับทั้ง strings และ objects เมื่อกำหนดรูปแบบสามารถใช้งานได้ง่ายทั้งสองเมื่อย้ายจาก CSS ธรรมดาหรือเริ่มต้นจากศูนย์ ค่าใช้จ่ายชุดมัดนั้นไม่ได้มีน้อยมาก แต่เล็กกว่าโซลูชันอื่น ๆ โดยเฉพาะอย่างยิ่งถ้าคุณพิจารณาชุดคุณสมบัติที่หลากหลายที่มีให้
ดูเหมือนว่ามันจะไม่ได้มุ่งเน้นไปที่ประสิทธิภาพโดยเฉพาะ แต่มีประสบการณ์มากขึ้นเกี่ยวกับนักพัฒนา ดูเหมือนวิธีแก้ปัญหา "รอบด้านที่ดี" ที่สมบูรณ์แบบ
| ถ่ายโอน / gzipped | ไม่บีบอัด | |
|---|---|---|
| ขนาดหน้าดัชนี | 83.2 kb | 253 kB |
| vs. CSS Modules | +6.5 kB | +20 kB |
Page Size First Load JS
┌ ○ / 2.5 kB 76.4 kB
├ /_app 0 B 73.9 kB
├ ○ /404 194 B 74.1 kB
└ ○ /other 1.07 kB 74.9 kB
+ First Load JS shared by all 73.9 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.6cb893.js 23.3 kB
├ chunks/pages/_app.b6d380.js 7.68 kB
└ chunks/webpack.ddd010.js 822 B
Minimal library, focused only on type-checking. It is framework agnostic, that's why it doesn't have a special API for handling dynamic styles. There are React wrappers available, but the typings feels a bit convoluted.
Version: 2.1 | Maintained by Basarat | Launched in 2017 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Framework agnostic
- Built-in Theming support : uses TS namespaces to define theming, which is not a recommended TS feature even by the author himself, or by TS core team member Orta Therox.
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection <style> tag with all the styles, and replaces it on update, and apparently it doesn't use insertRule() , not even in production builds, which might be an important performance drawback in large & highly dynamic UIs Overall TypeStyle seems a minimal library, relatively easy to adopt because we don't have to rewrite our components, thanks to the classic className approach. However we do have to rewrite our styles, because of the Style Object syntax. We didn't feel like writting CSS, so there is a learning curve we need to climb.
With Next.js or React in general we don't get much value out-of-the-box, so we still need to perform a lot of manual work. The external react-typestyle binding doesn't support hooks, it seems to be an abandoned project and the typings are too convoluted to be considered an elegant solution.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 78.8 kB | 241 kB |
| vs. CSS Modules | +2.1 kB | +8 kB |
Page Size First Load JS
┌ ○ / 2.44 kB 72.1 kB
├ /_app 0 B 69.7 kB
├ ○ /404 194 B 69.9 kB
└ ○ /other 975 B 70.7 kB
+ First Load JS shared by all 69.7 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.5b0422.js 3.81 kB
└ chunks/webpack.61f1b6.js 778 B
It appears to be a mature solution, with quite a number of users. The API is intuitive and very easy to use, great integration for React using hooks.
Version: 11.6 | Maintained by Robin Weser | Launched in 2016 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ Built-in Theming support
✅ Atomic CSS
✅ Framework agnostic
- TypeScript support : it exposes Flow types, which work ok, from our (limited) experience
- Context-aware code completion : styles defined outside the component require explicit typing to get code completion
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection a , b , ...)Fela looks to be a mature solution, with active development. It introduces 2 great features which we enjoyed a lot. The first one is the basic principle that "Style as a Function of State" which makes working with dynamic styles feel super natural and integrates perfectly with React's mindset. The second is atomic CSS class names, which should potentially scale great when used in large applications.
The lack of TS support however is a bummer, considering we're looking for a fully type-safe solution. Also, the scaling benefits of atomic CSS should be measured against the library bundle size.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 88.6 kB | 276 kB |
| vs. CSS Modules | +11.9 kB | +43 kB |
Page Size First Load JS
┌ ○ / 2.84 kB 81.7 kB
├ /_app 0 B 78.9 kB
├ ○ /404 194 B 79 kB
└ ○ /other 1.43 kB 80.3 kB
+ First Load JS shared by all 78.9 kB
├ chunks/framework.2191d1.js 42.4 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.32bc1d.js 12.6 kB
└ chunks/webpack.ddd010.js 822 B
Very young library, solid, modern and well-thought-out solution. The overall experience is just great, full TS support, a lot of other useful features baked in the lib.
Version: 0.2.5 (beta) | Maintained by Modulz | Launched in 2020 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Built-in Theming support
✅ Framework agnostic : (available with @stitches/core )
Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss prop (used only to override styled components)Styles output
.css file extraction<style> tag injection variants (for predefined styles), or styles created inside the component to get access to the propsStitches is probably the most modern solution to this date, with full out-of-the-box support for TS. Without a doubt, they took some of the best features from other solutions and put them together for an awesome development experience. The first thing that impressed us was definitely the documentation. The second, is the API they expose which is close to top-notch. The features they provide are not huge in quantity, but are very well-thought-out.
However, we cannot ignore the fact that it's still in beta. Also, the authors identify it as "near-zero runtime" , but at +9 kB gzipped it's debatable.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 82.0 kB | 250 kB |
| vs. CSS Modules | +5.3 kB | +17 kB |
Page Size First Load JS
┌ ○ / 2.43 kB 75.2 kB
├ /_app 0 B 72.8 kB
├ ○ /404 194 B 73 kB
└ ○ /other 984 B 73.8 kB
+ First Load JS shared by all 72.8 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.ff82f0.js 6.93 kB
└ chunks/webpack.61f1b6.js 778 B
Probably the grandaddy around here, JSS is a very mature solution being the first of them, and still being maintained. The API is intuitive and very easy to use, great integration for React using hooks.
Version: 10.7 | Maintained by Oleg Isonen and others | Launched in 2014 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ Built-in Theming support
✅ Framework agnostic
✅ TypeScript support
✅ Context-aware code completion
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled component (available with additional plugin)css propStyles output
.css file extraction<style> tag injection react-jss package, which is used with React/Next.js, depends on jss-preset-default, which includes many plugins by default, so you don't need to manually add some of the plugins;react-jss uses className by default. There's also styled-jss that uses Styled Components approach, but it has no types, and couldn't make it work on top of react-jss ;injectSheet API (or we couldn't find it anywhere);The API is similar in many ways to React Native StyleSheets, while the hooks helper allows for easy dynamic styles definition. There are many plugins that can add a lot of features to the core functionality, but attention must be payed to the total bundle size, which is significant even with the bare minimum only.
Also, being the first CSS-in-JS solution built, it lacks many of the modern features that focuses on developer experience.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 94.9 kB | 293 kB |
| vs. CSS Modules | +18.2 kB | +60 kB |
Page Size First Load JS
┌ ○ / 2.45 kB 88 kB
├ /_app 0 B 85.6 kB
├ ○ /404 194 B 85.8 kB
└ ○ /other 992 B 86.6 kB
+ First Load JS shared by all 85.6 kB
├ chunks/framework.2191d1.js 42.4 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.5f0007.js 19.2 kB
└ chunks/webpack.9c89cc.js 956 B
A very light-weight solution, with a loads of features.
Version: 2.0 | Maintained by Cristian Bote | Launched in 2019 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ Built-in Theming support
✅ TypeScript support
✅ Context-aware code completion
✅ Framework agnostic
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled component ( see details below )css prop ( is supported, but requires a separate babel plugin )Styles output
.css file extraction<style> tag injection <style> tag with all the styles, and appends to it on update, and apparently it doesn't use insertRule() , not even in production builds, which might be an important performance drawback in large & highly dynamic UIs Looking at Goober you cannot ask yourself what kind of magic did Cristian Bote do to fit all the features inside this tiny library. It is really mind blowing. It is marketed as being "less than 1KB" , which is not entirely accurate, but still... it's the smallest library we've tested.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 77.8 kB | 237 kB |
| vs. CSS Modules | +1.1 kB | +4 kB |
Page Size First Load JS
┌ ○ / 2.77 kB 71.1 kB
├ /_app 0 B 68.3 kB
├ ○ /404 194 B 68.5 kB
└ ○ /other 2.39 kB 70.7 kB
+ First Load JS shared by all 68.3 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.5ee014.js 2.42 kB
└ chunks/webpack.61f1b6.js 778 B
A rather new library, having the huge Atlassian platform supporting and probably using it. Many existing features, even more in development, or planned for development.
Version: 0.6 | Maintained by Atlassian | Launched in 2020 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Atomic CSS
Not Framework agnostic
No Built-in Theming support (at least at the moment, but it is planned)
Styles definition method(s)
Styles nesting
Styles apply method(s)
className (only supported with a custom ClassNames component)styled componentcss propStyles output
.css file extraction (currently under development, will be shipped in 2021)<style> tag injection css prop is seamless and trivial, not requiring any special setup (unlike Emotion) <head> during SSR - instead they are placed right before the element using them in the <body> , which could potentially provide slightly faster Paint metrics, such as FCP, or LCP, because the browser can start rendering the body faster and incrementally, not waiting for the entire block of styles to be parsedClassNames API, which enables us to apply styles as class name strings, is a bit convoluted and weird at first sight. Compiled is a very promising library. Considering that it offers both atomic CSS, and it plans to support static .css extraction, with excellent TypeScript support and style co-location, it would be quite unique (having only style9 as a direct competitor).
Also, we cannot ignore that is has Atlassian supporting its development, which puts a (slightly) bigger weight on the confidence level.
The total bundle overhead is pretty small, the runtime library being quite light-weight. With static .css file extraction, this could potentially become even smaller.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 80.2 kB | 242 kB |
| vs. CSS Modules | +3.5 kB | +9 kB |
Page Size First Load JS
┌ ○ / 2.11 kB 71.8 kB
├ /_app 0 B 66.5 kB
├ ○ /404 194 B 66.7 kB
└ ○ /other 888 B 70.6 kB
+ First Load JS shared by all 66.5 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.ebe095.js 576 B
├ chunks/webpack.ddd010.js 822 B
└ css/a92bf2d3acbab964f6ac.css 319 B
Linaria is all about static CSS extraction and avoiding any runtime overhead.
Version: 3.0 (beta) | Maintained by Callstack | Launched in 2018 | View Docs | ... back to Overview
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Framework agnostic
✅ Built-in Theming support
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection Linaria is highly inspired from Astroturf, combining various features from other libraries.
Version 3 is currently in Beta, not sure what the changelog is compared to v2. It's still in development by the React/Native geeks at Callstack.io , but we couldn't find which of the big players use it in production.
It seems to have a slightly larger overall page size ( 2.9 KB ), but we didn't investigate where does this come from. Also, there's an open question if this overhead is fixed or if it scales.
PS: thanks to Daniil Petrov for his PR with the Next.js integration
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 79.4 kB | 239 kB |
| vs. CSS Modules | +2.7 kB | +6 kB |
Page Size First Load JS
┌ ○ / 4.99 kB 71.5 kB
├ └ css/16f3e95ede28dcc048f2.css 423 B
├ /_app 0 B 66.5 kB
├ ○ /404 194 B 66.7 kB
└ ○ /other 3.59 kB 70.1 kB
└ css/3064299bff08067ec7dd.css 427 B
+ First Load JS shared by all 66.5 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.98e8c3.js 598 B
├ chunks/webpack.ddd010.js 822 B
└ css/7739287c04a618ea0c54.css 295 B
Modern solution with great TypeScript integration and no runtime overhead. It's pretty minimal in its features, straightforward and opinionated. Everything is processed at compile time, and it generates static CSS files. Successor of Treat, also be called "Treat v3", is developed and maintained by the same authors.
Version: 1.2 | Maintained by Seek OSS | Launched in 2021 | View Docs | ... back to Overview
✅ TypeScript support
✅ Built-in Theming support
✅ Context-aware code completion
✅ Framework agnostic
- Atomic CSS : can be achieved with Sprinkles
No Styles/Component co-location : styles must be placed in an external .css.ts file
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection & > span ), which might be seen as a downside, but it actually discourages bad-practices like specificity wars , which should be avoided when scaling CSS (however, this is impossible to be statically type-checked without pattern matching , so it will throw a runtime exception)variants based on predefined types, or inline styles for user-defined styles We felt a lot like using CSS Modules: we need an external file for styles, we place the styles on the elements using className , we handle dynamic styles with inline styles , etc. However, we don't write CSS, and the overall experience with TypeScript support is magnificent, because everything is typed, so we don't do any copy-paste . Error messages are very helpful in guiding us when we do something we're not supposed to do.
vanilla-extract is built with restrictions in mind, with a strong user-centric focus, balacing the developer experience with solid TypeScript support. It's also worth mentioning that Mark Dalgleish, co-author of CSS Modules, works at Seek and he's also a contributor.
The authors vision is to think of vanilla-extract as a low-level utility for building higher-level frameworks, which will probably happen in the future.
| Transferred / gzipped | Uncompressed | |
|---|---|---|
| Index page size | 76.7 kB | 231 kB |
| vs. CSS Modules | +0.0 kB | -2 kB |
Page Size First Load JS
┌ ○ / 2.09 kB 68.5 kB
├ └ css/37c023369f5e1762e423.css 370 B
├ /_app 0 B 66.4 kB
├ ○ /404 194 B 66.6 kB
└ ○ /other 611 B 67 kB
└ css/a56b9d05c6da35ff125f.css 386 B
+ First Load JS shared by all 66.4 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.700159.js 23.1 kB
├ chunks/pages/_app.bfd136.js 565 B
├ chunks/webpack.61f1b6.js 778 B
└ css/23b89d9ef0ca05e4b917.css 286 B
We know there are a lot of other libraries out there, besides the ones covered above. We're only covered the ones that have support for React , support for SSR , an easy integration with Next.js , good documentation and a sense of ongoing support and maintenance . Please checkout our goals.
Treat was initially included in the analysis with v1.6, but removed for a few reasons:
The main difference between vanilla-extract and Treat is that the latter supports IE and legacy browsers as well.
Style9 is a new library, inspired by Facebook's own CSS-in-JS solution called stylex. Style9 is unique because it's the only open source library that supports both .css static extraction + atomic CSS, and/or styles co-location. It has TS support and easy to integrate with Next.js.
However, it has quite a few limitations (at least as of Feb 2021) that makes it practically unusable in a real production application that we would want to scale, both in code & team size:
Enum or POJO , only constant primitives are supported, which is a big deal breaker ;classNames lib, but not dynamically/computed/expression based;Some upsides:
As a conclusion, it wants to be a powerful solution with very interesting and unique set of features, but it's not mature yet. As far as we see, it's currently mostly designed towards more static solutions. Dynamic styling seems to be difficult to handle, at least for the moment.
Not an actual CSS-in-JS library, more like a replacement for traditional CSS styling. It uses atomic CSS classes (some of them having multiple properties) that we attach to html elements. We don't write CSS, instead we use a different DSL to specify styles, pseudo classes, media queries, etc.
The reason we didn't include it in our thorough review is because it doesn't fully meet our goals:
.ts files to include them in tailwind.config (cannot import any file, cannot require .ts )tailwind.config directly offers no type-safety when importing it, or using resolveConfigrounded , place-self/content , divide , ring )::after pseudo elements are trickySome upsides:
tailwind.configTailwind seems to be more than a styling tool , it also offers some out-of-the-box utils + a ready-made design system that you can use right away.
It's not a popular solution, the approach is similar to React Native StyleSheets way of styling components. Has built-in TypeScript support and a simple API.
I got it started with Next.js, but it feels fragile. The Glamor official example throws an error regarding rehydrate . When commenting it out, it works, but not sure what the consequences are.
Didn't manage to start it with Next.js + TypeScript. The official example uses version 3, while today we have version 6. The example doesn't work, because the API has changed.
The solution looked interesting, because it is supposed to be very light-weight.
Didn't manage to start it with Next.js + TypeScript. There was an official example that used an older version of Next.js, but the example if not there anymore.
The solution is not that popular, but it was the first to use .css extraction with collocated styles.
Looks promising, atomic css and light-weight. It has a working Next.js example, but we didn't consider it because it lacks any documentation.
It looks like a not so popular solution, which also lacks support for TypeScript. It looks like the maintainers work at Uber and they use it internally. It focused on generating unique atomic CSS classes, which could potentially deduplicate a lot of code.
The project was put in Maintenance Mode. They recommend other solutions.
The project was discontinued in favor of Emotion.
Each implementation sits on their own branch, so we can have a clear separation at built time.
# install dependencies
yarn
# for development
yarn dev
# for production
yarn build
yarn startTo get in touch, my DMs are open @pfeiffer_andrei.
Special thanks and appreciations go to everyone that helped putting this document together, and making it more accurate: