يحتوي هذا المستند على تحليل متعمق لجميع حلول CSS-in-JS الحالية ، والتي تدعم عرض جانب الخادم و typecript .
المرجع الأساسي الذي سنستخدمه للمقارنة هو نهج وحدات 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 ، والبحث عن اسم فئة معين ، وعدم القدرة على "الانتقال إلى الأسلوب" ، هو عيب في الإنتاجية مهم.
يتطلب التصميم الزائفة والاستعلامات على وسائل الإعلام تكرار المحدد
حقيقة أخرى محبط هي الحاجة إلى تكرار فصول CSS لدينا عند تحديد فصول وعناصر الزائفة ، أو الاستعلامات الإعلامية . يمكننا التغلب على هذه القيود باستخدام معالج مسبق CSS مثل Sass ، Less أو Stylus ، الذي يدعم محدد & ، مما يتيح التصميم السياقي .
. 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. كما أنه يجعل إعادة البناء مرهقة للغاية ، بسبب عدم وجود أمان.
إن استخدام الرموز المميزة للتصميم الآمن في CSS غير تافهة
لا يمكن استخدام أي رموز تصميم محددة في JS/TS (للاستفادة من سلامة النوع) مباشرة في CSS.
هناك ما لا يقل عن حلتين لهذه القضية ، لا يوجد أي منهما أنيقة:
.module.css ..css .هناك أهداف محددة نبحث عنها في هذا التحليل:
في الحصول على أكثر تحديداً ، أردنا تجربة استخدام حلول CSS-in-JS المختلفة فيما يتعلق:
props المكونة (AKA. المتغيرات المكونة) ، أو من إدخال المستخدميهدف هذا التحليل إلى أن يكون موضوعيًا وغير معقول :
؟ ماذا لن تجد هنا؟
؟ ماذا ستجد هنا؟
لا يتم تقديم المكتبات بأي ترتيب معين. إذا كنت مهتمًا بتاريخ موجز لـ CSS-in-JS ، فيجب عليك الخروج من الماضي والحاضر ومستقبل CSS-in-JS Seefful Talk من Max Stoiber.
| 1. التوظيف المشترك | 2. DX | 3. tag` ` | 4. { } | 5 | 6. & CTX | 7. التعشيش | 8. موضوع | 9 .css | 10. <style> | 11. الذرية | 12. className | 13. <Styled /> | 14. css | 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 |
القدرة على تحديد الأنماط داخل نفس الملف مثل المكون. لاحظ أنه يمكننا أيضًا استخراج الأنماط في ملف منفصل واستيرادها ، في حال كنا نفضل ذلك.
⬆ لمحة عامة
يشير إلى تجربة المطور التي تتضمن جانبين رئيسيين:
⬆ لمحة عامة
tag` ` (قوالب موسومة)دعم تحديد الأنماط كسلاسل ، باستخدام قوالب الموسومة ES:
kebab-case لأسماء الممتلكات ، تمامًا مثل بناء جملة CSS العادي ؛string عادي ؛⬆ لمحة عامة
{ } (أنماط الكائن)دعم تحديد الأنماط ككائنات ، باستخدام كائنات JavaScript العادية:
camelCase لأسماء الممتلكات ، كما سنفعل في React Native ؛⬆ لمحة عامة
دعم TypeScript ، إما مدمج ، أو عبر حزمة @types ، والتي يجب أن تشمل:
Props الأدوية ، عند الاقتضاء (احصل على إمكانية الوصول الآمن إلى أنواع الدعائم المكونة عند تحديد الأنماط الديناميكية) ؛⬆ لمحة عامة
& CTX (أنماط سياقية)دعم أنماط السياق التي تسمح لنا بتحديد الفصول والعناصر الزائفة بسهولة والاستعلامات الإعلامية دون الحاجة إلى تكرار المحدد ، كما هو مطلوب في CSS العادي:
& Parent Selector ؛⬆ لمحة عامة
دعم المختارين المتداخلين التعسفي :
⬆ لمحة عامة
الدعم المدمج للرسومات أو إدارة الرموز لنظام التصميم.
لم نختبر هذه الميزة ، لذلك نحن فقط نلاحظ أن المكتبات تعبر عن دعمها في مستنداتها.
⬆ لمحة عامة
.css (استخراج CSS ثابتة) يتم استخراج الأنماط المحددة كملفات .css ثابتة:
⬆ لمحة عامة
<style> علامة يتم حقن الأنماط المحددة داخل <style> العلامات في المستند <head> :
⬆ لمحة عامة
القدرة على توليد فئات CSS الذرية ، وبالتالي زيادة قابلية إعادة استخدام الأسلوب ، وتقليل الازدواجية:
⬆ لمحة عامة
className تُرجع API لمكتبة string التي يتعين علينا إضافتها إلى مكوننا أو عنصرنا ؛
⬆ لمحة عامة
<Styled /> يقوم API بإنشاء مكون Wrapper (أو Styled ) يتضمن className (S) الذي تم إنشاؤه:
StyledButton أو StyledList بدلاً من الثوابت مثل button_styles أو list_styles ، لذلك فيما يتعلق بتسمية الأمر نفسه إلى حد كبير ؛⬆ لمحة عامة
css يتيح أنماط تمرير باستخدام دعامة css خاصة ، مماثلة لكيفية تحديد الأنماط المضمنة ، لكن المكتبة تولد اسم فئة CSS فريد خلف الكواليس:
⬆ لمحة عامة
يسمح الاستخدام بدون ، أو مع أي إطار عمل. تم تصميم بعض المكتبات خصيصًا للرد فقط.
ملاحظة : تتفاعل بعض المكتبات مثل الغرز أو وثيقة العاطفة الاستخدام فقط ، على الرغم من أن لديها جوهرًا لا يلحق به إطار.
⬆ لمحة عامة
الفرق الإجمالي لحجم الصفحة في KB (نقل Gzipped و MINISED / غير مضغوط ومُعدل) مقارنةً بوحدات CSS ، لبناء إنتاج صفحات الفهرس بالكامل باستخدام NEXT.JS:
ملاحظة: تم إجراء جميع عمليات الإنشاء باستخدام Next.js 11.1.0 والقيم مأخوذة من علامة تبويب شبكة Chrome DevTools ، والتي تم نقلها عبر حجم الشبكة مقابل حجم المورد.
⬆ لمحة عامة
تنطبق الملاحظات التالية على جميع الحلول (مع استثناءات طفيفة مدببة).
سيتم تجميع المكونات المستخدمة فقط في طريق معين فقط لهذا الطريق. هذا شيء يقوم به next.js خارج الصندوق.
توفر جميع الحلول طريقة لتحديد الأنماط العالمية ، بعضها مع واجهة برمجة تطبيقات مخصصة.
تقدم جميع الحلول دعمًا لتقديم جانب الخادم ومن السهل الاندماج مع Next.js.
جميع الحلول تضيف تلقائيًا بادئات محددة من البائعين خارج الصندوق.
جميع الحلول تولد أسماء فئة فريدة من نوعها ، مثل وحدات CSS. تختلف الخوارزمية المستخدمة لإنشاء هذه الأسماء كثيرًا بين المكتبات:
Card التي تتطلب المزيد من الحوسبة .heading ولكنها تؤدي إلى أسماء غير معروفة (على سبيل .Card_heading_h7Ys5 :..heading-0-2-1 ، .input-0-2-2 ) ، أو الحروف الأبجدية ( a, b, c, ... aa, ab, ac ، إلخ) ، مما يجعل هذا النهج أكثر أداءً ، ولكنه يؤدي إلى أسماء فئة غير معطمة (لا يمكن معرفة ذلك إذا كان ذلك له أي عربات محتملة أو لا) ؛ لا يولد أي من الحلول أنماطًا مضمّنة ، وهو نهج أقدم ، يستخدمه Radium & Glamour. النهج أقل أداء من فئات CSS ، ولا ينصح به كطريقة أساسية لتحديد الأنماط. وهذا يعني أيضًا استخدام معالجات أحداث JS لإطلاق فصول زائفة ، لأن الأنماط المضمنة لا تدعمهم. على ما يبدو ، ابتعدت جميع الحلول الحديثة في الوقت الحاضر عن هذا النهج.
تدعم جميع الحلول معظم خصائص CSS التي ستحتاجها: فصول وعناصر Pseudo ، واستعلامات الوسائط وإطارات المفاتيح هي تلك التي قمنا باختبارها.
معظم الحلول تسوق نفسها على أنها قادرة على "استخراج CSS الحرجة" خلال SSR. يرجى ملاحظة أن هذا لا يشير إلى استخراج CSS الحرجة أعلاه ، كما اعتقدنا في البداية.
ماذا يفعلون بالفعل:
مع CSS ثابتة 100 ٪ ، لن يكون هناك في الواقع فائدة. من خلال الصفحات الديناميكية التي تجعل عناصر قليلة جدًا على الخادم ، ويتم تقديم معظم المكونات ديناميكيًا على العميل ، تزداد الفوائد.
الاستثناء : المكتبات التي تستخدم استخراج CSS ثابت.
إن فهم كيفية تأثير هذه الميزات على شبكة الإنترنت الأساسية ومقاييس الأداء بشكل عام هو عامل مهم للغاية يجب مراعاته ، والطريقة التي يتم بها تسليم الأنماط إلى العميل على الأرجح تأثير أكبر ، لذلك دعونا نحلل ذلك بالتفصيل.
أيضًا ، هناك سيناريوهان مختلفتان نحتاج إلى مراعاته:
.js ، .css ، الوسائط ، إلخ) ؛ .css الحلول التي تنشئ ملفات .css ثابتة ، والتي عادة ما تتضمنها ككلام <link> > العلامات) في <head> من صفحتك ، هي في الأساس موارد لحجب. هذا يؤثر بشكل كبير على FCP و LCP وأي مقياس آخر يليه.
؟ ذاكرة التخزين المؤقت الفارغة
إذا كان لدى المستخدم ذاكرة التخزين المؤقت الفارغة ، فيجب حدوث ما يلي ، مما يؤثر سلبًا على FCP و LCP :
<body> ، حتى لو تم تحميل HTML بأكمله بالفعل ، وقد يتم تحليله بفارغ الصبر ، وبعض الموارد التي تم جلبها بالفعل مقدمًا ؛ صحيح أنه يمكنك جلبه بشكل موازٍ <head> الأخرى (ملفات .css أو .js إضافية) ، ولكن هذه ممارسة سيئة بشكل عام ؛
؟ ذاكرة التخزين المؤقت الكاملة
ومع ذلك ، في الزيارات اللاحقة ، سيتم تخزين مورد .css بأكمله ، لذلك سيتأثر FCP و LCP بشكل إيجابي.
النقاط الرئيسية
يبدو أن هذا الحل أكثر ملاءمة عندما:
.css شائع يمكن تخزينه مؤقتًا عند زيارة الصفحات الأخرى ؛<style> أنماط حقن العلامة أثناء SSR ، ستتم إضافة الأنماط كعلامات <style> TAG (S) في <head> للصفحة. ضع في اعتبارك أن هذه عادة لا تتضمن جميع الأنماط اللازمة للصفحة ، لأن معظم المكتبات تؤدي استخراج CSS الحرجة ، لذلك يجب أن تكون هذه styles أصغر عادةً من الملف الثابت .css الذي تمت مناقشته مسبقًا.
؟ ذاكرة التخزين المؤقت الفارغة
نظرًا لأننا نشحن أقل بايت CSS ، ويتم ضمها داخل ملف .html ، فإن هذا سيؤدي إلى أسرع FCP و LCP :
.css ، لذلك لم يتم حظر المتصفح ؛.js الأخرى إلى نهاية المستند ، فلن يقوم <head> بأي طلبات ، لذلك سيحدث العرض بسرعة فائقة ؛.css ثابت:.js جنبًا إلى جنب مع المكونات ، أثناء الترطيب (يتضمن ذلك جميع CSS الحرجة التي يتم شحنها بالفعل داخل <style> علامة + أخرى) ؛ ؟ ذاكرة التخزين المؤقت الكاملة
عندما تكون ذاكرة التخزين المؤقت للمستخدم ممتلئة ، لن تتطلب ملفات .js الإضافية الجلب ، حيث تم تخزينها مؤقتًا بالفعل.
ومع ذلك ، إذا كانت الصفحة SSRED ، فسيتم تنزيل CSS الحرجة المضمّنة في <style> من الوثيقة مرة أخرى ، ما لم نتعامل مع HTML ثابتة يمكن تخزينها أيضًا ، أو نتعامل مع التخزين المؤقت لـ HTML على البنية التحتية الخاصة بنا.
ولكن ، بشكل افتراضي ، سنقوم بشحن بايت إضافي على كل طلب HTTP ، بغض النظر عما إذا كان مخبأة أم لا.
النقاط الرئيسية
يبدو أن هذا الحل أكثر ملاءمة عندما:
تقول معظم الحلول أنها تزيل التعليمات البرمجية/الأنماط غير المستخدمة . هذا ليس سوى نصف الحقوق .
من الصعب بالفعل تراكم الشفرة غير المستخدمة ، خاصة إذا قارنتها بملفات .css العادية كما اعتدنا على الكتابة قبل عقد من الزمان . ولكن عند مقارنتها بوحدات CSS ، فإن الاختلافات ليست كبيرة. أي حل يوفر خيار تحديد المحددات التعسفية أو الأنماط المتداخلة سيقوم بتجميعها ، بغض النظر عما إذا كانت تستخدم أو لا داخل مكوننا. لقد تمكنا من شحن أنماط SSR غير المستخدمة مع جميع الحلول التي تم اختبارها.
من الصعب تنفيذ إزالة الكود غير المستخدمة الكاملة والكاملة ، لأن بناء جملة CSS غير محدد ، ولا يمكن تحليله بشكل ثابت. أيضا ، فإن الطبيعة الديناميكية للمكونات تجعلها مستحيلة عملياً في سيناريوهات معينة ، خاصةً عندما يتم تقديم الترميز ديناميكيًا:
& span : عناصر أحفاد ؛&:nth-child() : محددات معينة زائفة ؛& .bg-${color} : Dynamic Selectors ؛.parent & : محددات الوالدين ؛في الأساس ، ما نحصل عليه هو إزالة الكود عندما نحذف المكون ، أو لم نعد نستورده بعد الآن. هذا سلوك ضمني ، لأن الأنماط هي تبعية مباشرة للمكون. عندما يختفي المكون ، وكذلك أنماطه.
هناك طريقتان لحقن CSS في DOM وتحديثه من JavaScript:
<style> العلامات (s) يشير هذا النهج إلى إضافة واحد أو أكثر <style> علامات (نمط) في DOM (إما في <head> أو في مكان ما في <body> ) ، باستخدام .appendChild () لإضافة <style> العقدة (S) ، بالإضافة إلى إما .TextContent ، .innerhtml لتحديث العلامة <style> .
<style> وتحديث محتوىه بالكامل ، قد يكون بطيئًا في تحديث DOM بأكمله عندما قمنا بالفعل بتغيير مجموعة صغيرة فقط من قواعد (قواعد) CSS ؛DEVELOPMENT ، لأنه يوفر تجربة تصحيح أفضل ؛PRODUCTION أيضًا ؛ CSSStyleSheet تستخدم هذه الطريقة لأول مرة من قبل JSS ، وتستخدم CSSStyleSheet.insertRule() لحقن قواعد CSS مباشرة في CSSOM .
<style> فارغة ؛<style> ؛$0 في Chrome DevTools (أو احصل على إشارة إليها بأي طريقة أخرى ، باستخدام DOM API) ؛.sheet.cssRules على علامة <style> لرؤية مجموعة قواعد CSS التي تحتوي عليها ؛PRODUCTION ؛DEVELOPMENT أيضًا ؛ إذا تم استيراد نفس المكون بواسطة طريقين مختلفين ، فسيتم إرساله مرتين إلى العميل. هذا بالتأكيد قيود على نظام Bundler/Build ، في حالتنا Next.js ، ولا يتعلق بمحلول CSS-in-JS .
في Next.js ، يعمل تقسيم التعليمات البرمجية على مستوى المسار ، وتجميع جميع المكونات المطلوبة لمسار معين ، ولكن وفقًا لمدونتها الرسمية و Web.dev إذا تم استخدام مكون في أكثر من 50 ٪ من الصفحات ، فيجب تضمينه في حزمة commons . ومع ذلك ، في مثالنا ، لدينا صفحتان ، يقوم كل منهما باستيراد مكون Button ، ويتم تضمينه في كل حزمة صفحة ، وليس في حزمة commons . نظرًا لأن الرمز المطلوب للتصميم يتم تجميعه مع المكون ، فإن هذا القيد سيؤثر أيضًا على الأنماط أيضًا ، لذلك يجدر وضع ذلك في الاعتبار.
هذا هو نهج راسخ وناضج وصلب. بلا شك ، إنه تحسن كبير على BEM أو SMACCs أو OOCSS أو أي منهجية أخرى CSS القابلة للتطوير لتنظيم وتنظيم CSS لدينا ، وخاصة في التطبيقات القائمة على المكونات.
أطلقت في عام 2015 | العودة إلى نظرة عامة
✅ إكمال رمز الوعاء بالسياق
✅ إطار لاأدري
لا أنماط/مكون المشاركة في الموقع
لا يوجد دعم typeScript
لا CSS الذرية
لا دعم للالتهام
طريقة تعريف الأنماط
الأنماط التعشيش
تنطبق الأنماط
classNamestyledcss CSSأنماط الإخراج
.css استخراج ملف<style> حقن العلامةهذا هو خط الأساس الذي سنأخذ في الاعتبار عند مقارنة جميع حلول CSS-in-JS التالية. الخروج عن الدافع لفهم قيود هذا النهج بشكل أفضل الذي نحاول ملؤه.
| نقل / gzipped | غير مضغوط | |
|---|---|---|
| حجم صفحة الفهرس | 76.7 كيلو بايت | 233 كيلو بايت |
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
حل بسيط للغاية ، ليس لديه موقع ويب مخصص للتوثيق ، كل شيء على جيثب. إنه ليس شائعًا ، لكنه الحل المدمج في Next.js.
الإصدار: 4.0 | تحتفظ بها Vercel | أطلقت في عام 2017 | عرض المستندات | ... العودة إلى نظرة عامة
✅ الأنماط/الموقع المشترك المكون
؟ إكمال رمز الوعي بالسياق : للحصول على تمييز بناء الجملة وإكمال الكود ، يلزم امتداد المحرر
؟ دعم typeScript : يمكن تثبيت @types ، ولكن واجهة برمجة التطبيقات ضئيلة للغاية بحيث لا تتطلب ts
لا CSS الذرية
لا دعم للالتهام
لا إطار لاأدري
طريقة تعريف الأنماط
الأنماط التعشيش
تنطبق الأنماط
classNamestyledcss CSSأنماط الإخراج
.css استخراج الملف<style> حقن العلامة elements HTML أيضًا ، وينشئ أسماء فئة فريدة لهم (لست متأكدًا مما إذا كانت ممارسة جيدة ، رغم ذلك) بشكل عام ، شعرنا بأننا كتبت CSS العادي ، مع فائدة إضافية تتمثل في القدرة على تحديد الأنماط إلى جانب المكون ، لذلك لا نحتاج إلى ملف .css إضافي . في الواقع ، هذه هي فلسفة المكتبة: دعم بناء جملة CSS داخل ملف المكون. يمكننا استخدام أي ثوابت JS/TS من الوظائف مع الاستيفاء سلسلة. يعد العمل مع الأنماط الديناميكية أمرًا سهلاً للغاية لأنه JavaScript عادي في النهاية. نحصل على كل هذه الفوائد بسعر منخفض للغاية ، مع حزمة صغيرة جدًا.
الجوانب السلبية هي التجربة الشاملة لكتابة CSS العادي. بدون دعم تعشيش فصول/عناصر الزائفة والاستعلامات الإعلامية التي تحصل على مرهقة للغاية لإدارتها.
| نقل / gzipped | غير مضغوط | |
|---|---|---|
| حجم صفحة الفهرس | 79.5 كيلو بايت | 245 كيلو بايت |
| مقابل وحدات CSS | +2.8 كيلو بايت | +12 كيلو بايت |
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 | تحتفظ بها ماكس ستويبر والآخرين | أطلقت في عام 2016 | عرض المستندات | ... العودة إلى نظرة عامة
✅ الأنماط/الموقع المشترك المكون
✅ دعم TypeScript : يجب تثبيت @types ، عبر بالتأكيد
✅ دعم المدمج
✅ إطار لاأدري
؟ إكمال رمز الوعي بالسياق : يتطلب امتداد/مكون إضافي محرر
لا CSS الذرية
طريقة تعريف الأنماط
الأنماط التعشيش
تنطبق الأنماط
classNamestyledcssأنماط الإخراج
.css استخراج الملف<style> حقن العلامة Props ، إلخ) توفر المكونات المصممة نهجًا جديدًا لمكونات التصميم باستخدام الطريقة styled التي تنشئ مكونًا جديدًا بما في ذلك الأنماط المحددة. لا نشعر بأننا كتبت CSS ، لذلك قادمون من وحدات CSS ، سيتعين علينا أن نتعلم طريقة جديدة أكثر برمجية ، لتحديد الأنماط. نظرًا لأنه يتيح كل من string و object SYNTAX ، فهو حل مرن للغاية لترحيل أنماطنا الحالية ، ولبدء مشروع من نقطة الصفر. أيضا ، قام المشروعون بعمل جيد للغاية في مواكبة معظم الابتكارات في هذا المجال.
ولكن قبل تبنيه ، يجب أن ندرك أنه يأتي بتكلفة معينة لحجم حزمة لدينا.
| نقل / gzipped | غير مضغوط | |
|---|---|---|
| حجم صفحة الفهرس | 90.1 كيلو بايت | 272 كيلو بايت |
| مقابل وحدات CSS | +13.4 كيلو بايت | +39 كيلو بايت |
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
ربما الحل الأكثر شمولا ، كاملة و sofisticed. تبدو الوثائق التفصيلية ، التي تم تصميمها بالكامل باستخدام TypeScript ، ناضجة للغاية ، غنية بالميزات وصيانتها جيدًا.
الإصدار: 11.4 | تحتفظ بها ميتشل هاميلتون وآخرون | أطلقت في عام 2017 | عرض المستندات | ... العودة إلى نظرة عامة
✅ الأنماط/الموقع المشترك المكون
✅ دعم TypeScript
✅ دعم المدمج
✅ إكمال رمز الوعي السياق : لاستخدام نهج المكونات styled ، مطلوب مكون إضافي للمحرر
✅ إطار لاأدري
لا CSS الذرية
طريقة تعريف الأنماط
الأنماط التعشيش
تنطبق الأنماط
className (باستخدام @العاطفة/CSS)styledcssأنماط الإخراج
.css استخراج الملف<style> حقن العلامة css بيئة عمل كبيرة أثناء التطوير ، ومع ذلك يبدو أنه نهج أحدث ، استنادًا إلى React 17 New jsx ، وتكوينه ليس تافهاً ، ويختلف على الإعداد الخاص بك ، ويشير إلى بعض المرجل (الذي يجب أن يتغير قريبًا ويصبح أسهل) styled إلى إضافة 3 kB إلى حزمة لدينا ، لأنه يتم استيراده من حزمة منفصلةcss والمكونات styled ) يبدو أن المشاعر العامة هي نهج قوي ومرن للغاية. يوفر نهج Prob Novel css بيئة العمل المليئة بالمطورين. العمل مع الأنماط الديناميكية و typexcript سهلة للغاية وبديهية. دعم كل من strings objects عند تحديد الأنماط ، يمكن استخدامها بسهولة عند الترحيل من CSS العادي ، أو البدء من نقطة الصفر. الحزمة العلوية ليست ضئيلة ، ولكنها بالتأكيد أصغر بكثير من الحلول الأخرى ، خاصة إذا كنت تفكر في المجموعة الغنية من الميزات التي تقدمها.
يبدو أنه ليس له تركيز مخصص على الأداء ، ولكن أكثر على تجربة المطورين. يبدو وكأنه حل مثالي "مدورة".
| نقل / gzipped | غير مضغوط | |
|---|---|---|
| حجم صفحة الفهرس | 83.2 كيلو بايت | 253 كيلو بايت |
| مقابل وحدات CSS | +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: