이 문서에는 서버 측 렌더링 및 타입 스크립트를 지원하는 모든 현재 CSS-in-JS 솔루션에 대한 심층 분석이 포함되어 있습니다.
우리가 비교에 사용할 기준 참조는 CSS 모듈 접근법입니다.
우리는 자원을 구축하기위한 SSR 프레임 워크로 Next.js를 사용하고 있습니다.
마지막으로 중요한 측면은 전체 타이프 스크립트 지원을 갖춘 유형 안전입니다.
? 마지막 업데이트 : 2021 년 8 월
? 짧은 개요를 얻으려면 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 클래스를 복제해야한다는 것입니다. 우리는 Sass, Less 또는 Stylus 와 같은 CSS 전 처리기를 사용하여 이러한 제한을 극복 할 수 있으며, & 선택기를 지원하여 상황에 맞는 스타일을 가능하게합니다.
. button {}
/* duplicated selector declaration for pseudo classes/elements */
. button : hover {}
. button :: after {}
@media ( min-width : 640 px ) {
/* duplicated selector declaration inside media queries */
. button {}
} 스타일 사용은 정의에서 분리됩니다
CSS 모듈을 사용하여 CSS 클래스가 component.css 파일에 정의 된 내용에 대해 지능을 얻지 못하면서 COPY-PASTE를 필요한 도구로 만들고 DX를 낮추십시오. 또한 안전 부족으로 인해 리팩토링이 매우 번거 롭습니다 .
CSS에서 타입 안전 디자인 토큰을 사용하는 것은 사소한 일입니다
JS/TS에 정의 된 설계 토큰 (유형 안전성으로부터 혜택)은 CSS에서 직접 사용할 수 없습니다.
이 문제에는 최소 2 개의 해결 방법이 있으며 그 중 어느 것도 우아하지 않습니다.
.module.css 에서 사용할 때는 여전히 지능 또는 유형 안전성을 얻지 못합니다..css 파일로 분할하십시오.이 분석에서 우리가 찾고있는 특정 목표가 있습니다.
보다 구체적으로, 우리는 다양한 CSS-in-JS 솔루션의 사용을 경험하고 싶었습니다.
props (일명 구성 요소 변형)을 기반으로 한 동적 스타일 또는 사용자 입력이 분석은 객관적 이고 무시되지 않기 위한 것입니다.
? 여기서 찾을 수없는 것은 무엇입니까?
? 여기서 무엇을 찾을 수 있습니까?
라이브러리는 특정 순서로 제시되지 않습니다. CSS-in-JS의 간단한 역사 에 관심이 있다면 Max Stoiber의 CSS-in-JS Insightful Talk의 과거, 현재 및 미래를 확인해야합니다.
| 1. 공동 위치 | 2. dx | 3. tag` ` | 4. { } | 5. TS | 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 사용합니다.string 처럼 보입니다.개요에 대한 바람
{ } (객체 스타일)일반 JavaScript 객체를 사용하여 스타일을 객체로 정의하는 지원 :
camelCase 사용합니다.개요에 대한 바람
내장 또는 @types 패키지를 통해 다음을 포함 해야하는 TypeScript 지원 : 다음을 포함해야합니다.
Props generic (동적 스타일을 정의 할 때 구성 요소 소품 유형에 대한 유형 안전 액세스);개요에 대한 바람
& ctx (맥락 스타일)일반 CSS에서 요구되는대로 선택기를 반복 할 필요없이 의사 클래스 및 요소 및 미디어 쿼리를 쉽게 정의 할 수있는 상황에 맞는 스타일을 지원합니다.
& Parent Selector를 지원할 수 있습니다.개요에 대한 바람
임의의 중첩 선택기 지원 :
개요에 대한 바람
설계 시스템을위한 테마 또는 관리에 대한 내장 지원.
우리는 이 기능을 테스트하지 않았으므로 도서관이 문서에서 지원을 표현하는 도서관 만 메모하고 있습니다.
개요에 대한 바람
.css (정적 CSS 추출) 정의 된 스타일은 정적 .css 파일로 추출됩니다.
개요에 대한 바람
<style> 태그 정의 된 스타일은 문서의 <head> 에 <style> 태그 내부에 주입됩니다.
개요에 대한 바람
원자 CSS 클래스를 생성하여 스타일 재사용 성을 높이고 중복을 줄이는 능력 :
개요에 대한 바람
className 라이브러리 API는 구성 요소 또는 요소에 추가 해야하는 string 반환합니다.
개요에 대한 바람
<Styled /> API는 생성 된 className 포함하는 래퍼 (또는 Styled ) 구성 요소를 만듭니다.
button_styles 또는 list_styles 와 같은 상수 대신 StyledButton 또는 StyledList 와 같은 구성 요소를 만들어냅니다.개요에 대한 바람
css 소품 특수 css 소품을 사용하여 스타일을 통과 할 수 있습니다. 유사한 스타일을 정의하는 방법과 유사하지만 라이브러리는 장면 뒤에서 고유 한 CSS 클래스 이름을 생성합니다.
개요에 대한 바람
프레임 워크없이 사용량을 허용합니다. 일부 라이브러리는 React 전용으로 특별히 구축됩니다.
참고 : 스티치 나 감정 문서와 같은 일부 라이브러리는 사용량 만 반응하지만 프레임 워크의 핵심은 비수적입니다.
개요에 대한 바람
CSS 모듈 에 비해 KB의 총 페이지 크기 차이 (전송 Gzippend & Minification / Unmpressed & Minied)는 다음 Indec.js를 사용하여 전체 색인 페이지 제작 빌드에 비해 다음을 사용합니다.
참고 : 모든 빌드는 Next.js 11.1.0 으로 수행되었으며 값은 Chrome DevTools 네트워크 탭에서 가져온 네트워크 대 리소스 크기로 전송됩니다.
개요에 대한 바람
다음 관찰은 모든 솔루션에 적용됩니다 (사소한 뾰족한 예외 포함).
특정 경로에서만 사용되는 구성 요소는 해당 경로에 대해서만 번들로 제공됩니다. 이것은 Next.js가 Box 외부에서 수행하는 것입니다.
모든 솔루션은 전용 API를 가진 글로벌 스타일을 정의하는 방법을 제공합니다.
모든 솔루션은 서버 측 렌더링 지원을 제공하며 Next.js와 쉽게 통합 할 수 있습니다.
모든 솔루션은 공급 업체 별 접두사를 자동으로 추가하여 상자 밖으로 추가합니다.
모든 솔루션은 CSS 모듈과 같은 고유 한 클래스 이름을 생성합니다. 이러한 이름을 생성하는 데 사용되는 알고리즘은 라이브러리마다 다릅니다.
Card 구성 요소의 .heading 스타일은 항상 .Card_heading_h7Ys5 hash);.heading-0-2-1 , .input-0-2-2 ) 또는 알파벳 문자 ( a, b, c, ... aa, ab, ac 등)를 기본적으로 증가 시켜이 접근법을보다 성능을 높이지만 비 이중 클래스 이름을 초래할 수 있습니다 (잠재적 인 단점이 있는지 여부를 알 수 없음). 솔루션 중 어느 것도 인라인 스타일을 생성하지 않으며, 이는 라듐 및 매력이 사용하는 오래된 접근 방식입니다. 이 접근 방식은 CSS 클래스보다 성능이 떨어지며 스타일을 정의하는 주요 방법으로 권장되지 않습니다. 또한 인라인 스타일이 지원하지 않기 때문에 JS 이벤트 처리기를 사용하여 의사 클래스를 트리거하는 것을 의미합니다. 분명히 모든 현대 솔루션은 오늘날이 접근법에서 멀어졌습니다.
모든 솔루션은 필요한 대부분의 CSS 속성을 지원합니다. 의사 클래스 및 요소 , 미디어 쿼리 및 키 프레임은 테스트 한 것입니다.
대부분의 솔루션은 SSR 동안 "중요한 CSS를 추출" 할 수있는 것으로 스스로 시장에 출시됩니다. 우리가 처음 생각했듯이 위에서 언급 한 CSS 추출을 의미하지는 않습니다 .
그들이 실제로하는 일 :
100% 정적 CS를 사용하면 실제로 이점이 없습니다. 서버에서 요소가 거의없고 대부분의 구성 요소가 클라이언트에서 동적으로 렌더링되는 동적 페이지를 사용하면 이점이 증가합니다.
예외 : 정적 CSS 추출을 사용하는 라이브러리.
이러한 기능이 핵심 웹 생명 및 성능 메트릭에 어떻게 영향을 미치는지 이해하는 것은 일반적으로 고려해야 할 매우 중요한 요소이며, 고객에게 스타일이 제공되는 방식은 아마도 가장 큰 영향을 미치므로 자세히 분석하겠습니다.
또한 고려해야 할 두 가지 시나리오가 있습니다.
.js , .css , media 등); .css 파일 추출 일반적으로 페이지의 <head> 에 <link> 태그로 포함되는 .css 정적 파일을 생성하는 솔루션은 기본적으로 블로킹 리소스입니다. 이것은 FCP , LCP 및 다음의 다른 지표에 큰 영향을 미칩니다.
? 빈 캐시
사용자에게 빈 캐시가있는 경우 다음과 같은 경우 FCP 및 LCP 에 부정적인 영향을 미칩니다.
<body> 의 렌더링을 지연시킬 것입니다. 심지어 간절히 구문 분석 될 수도 있고 일부 자원은 이미 미리 미리 가져 왔습니다. 다른 <head> 리소스 (추가 .css 또는 .js 파일)를 병렬 로 가져올 수는 있지만 일반적으로 나쁜 관행입니다.
? 전체 캐시
그러나 후속 방문시 .css 리소스 전체가 캐시되므로 FCP 와 LCP에 긍정적 인 영향을 미칩니다.
핵심 요점
이 솔루션은 다음과 같이 더 적합한 것으로 보입니다.
.css 파일이 포함되어있을 수도 있습니다.<style> 태그 주입 스타일 SSR 동안 스타일은 페이지의 <head> 에 <style> 태그로 추가됩니다. 대부분의 라이브러리는 중요한 CSS 추출을 수행하기 때문에 일반적으로 페이지에 필요한 모든 스타일이 포함되어 있지 않으므로 이러한 styles 일반적으로 이전에 논의 된 전체 .css 정적 파일보다 일반적으로 작아야합니다.
? 빈 캐시
우리는 CSS 바이트를 적게 배송하고 .html 파일 내부에 상환되므로 FCP 및 LCP가 더 빠릅니다.
.css 파일에 대한 추가 요청이 필요하지 않으므로 브라우저가 차단되지 않습니다..js 파일 요청을 문서 끝으로 이동하면 <head> 요청을하지 않으므로 렌더링은 매우 빠르게 발생합니다..css 추출에는 필요하지 않은 추가 바이트를 배송 할 것입니다..js 파일에 번들로 제공됩니다 (여기에는 <style> 태그 + 기타 내부에 이미 배송 된 모든 중요한 CSS가 포함됨); ? 전체 캐시
사용자의 캐시가 가득 차면 추가 .js 파일은 이미 캐시되었으므로 가져 오는 것이 필요하지 않습니다.
그러나 페이지가 ssRed 인 경우 문서의 <style> 태그로 렌더링 된 상감 된 중요한 CS는 캐싱 될 수있는 정적 HTML을 처리하거나 인프라에서 HTML 캐싱을 처리하지 않는 한 다시 다운로드됩니다.
그러나 기본적으로 캐시 된 여부에 관계없이 모든 페이지 http 요청에 추가 바이트를 배송합니다.
핵심 요점
이 솔루션은 다음과 같이 더 적합한 것으로 보입니다.
대부분의 솔루션에 따르면 사용되지 않은 코드/스타일을 제거합니다 . 이것은 단지 반야 입니다.
사용하지 않은 코드는 실제로 축적하기가 더 어렵습니다. 특히 10 년 전에 작성했던 것처럼 일반 .css 파일과 비교하는 경우. 그러나 CSS 모듈과 비교할 때 차이는 크지 않습니다. 임의의 선택기 또는 중첩 스타일을 정의하는 옵션을 제공하는 모든 솔루션은 구성 요소 내부에 사용 되든 없든 상관없이 묶습니다. 우리는 모든 테스트 된 솔루션으로 미사용 SSR 스타일을 배송했습니다.
CSS 구문이 유형 확인되지 않거나 정적으로 분석 할 수 없으므로 True & Full Uned Code 제거는 구현하기가 어렵습니다. 또한 구성 요소의 동적 특성은 특히 마크 업이 동적으로 렌더링 될 때 특정 시나리오에서 실제로 불가능합니다.
& span : 자손 요소;&:nth-child() : 특정 의사 선택기;& .bg-${color} : 동적 선택기;.parent & : 부모 선택기;기본적으로, 우리가 얻는 것은 구성 요소를 삭제하거나 더 이상 가져 오지 않을 때 코드 제거입니다. 스타일은 구성 요소의 직접적인 의존성이기 때문에 암시 적 행동입니다. 구성 요소가 사라지면 스타일도 마찬가지입니다.
CSS를 DOM에 주입하고 JavaScript에서 업데이트하는 두 가지 방법이 있습니다.
<style> 태그 사용 이 접근법은 .appendchild ()를 사용하여 <tyletcontent, .innerhtml과 함께 <style> 노드를 추가하여 <style> 태그를 추가하여 <style> 노드 (들)를 추가하기 위해 .appendChild ()를 사용하여 dom ( <head> 또는 <body> 의 어딘가)에 하나 이상의 <style> 태그를 추가하는 것을 의미합니다.
<style> 태그 만 사용하고 전체 컨텐츠를 업데이트하면 작은 CSS 규칙 세트 만 실제로 변경했을 때 전체 DOM을 업데이트하는 데 속도가 느릴 수 있습니다.DEVELOPMENT 모드에서 사용합니다. 더 나은 디버깅 경험을 제공하기 때문입니다.PRODUCTION 에서도 사용합니다. CSSStyleSheet API 사용 JSS 에서 처음 사용하는이 방법은 CSSStyleSheet.insertRule() 사용하여 CSS 규칙을 CSSOM 에 직접 주입합니다.
<style> 태그를 가리킬 수 있기 때문입니다.<style> 태그를 선택해야합니다.$0 를 통해 액세스 할 수 있습니다 (또는 DOM API를 사용하여 다른 방법으로 참조하십시오)..sheet.cssRules <style> 태그의 CSS 규칙 배열을 보려면;PRODUCTION 에서 사용합니다.DEVELOPMENT 모드에서도 사용합니다. 동일한 구성 요소가 2 개의 다른 경로로 가져 오면 클라이언트에게 두 번 보내집니다. 이것은 분명히 Bundler/Build System의 한계이며, 다음은 CSS-in-JS 솔루션과 관련이 없습니다 .
Next.js에서 코드 분할은 경로 수준에서 작동하여 특정 경로에 필요한 모든 구성 요소를 번들로 만들지 만 공식 블로그 및 Web.dev에 따르면 구성 요소가 페이지의 50% 이상 을 사용하는 경우 commons 번들에 포함되어야합니다. 그러나이 예에는 2 페이지가 있으며 각각 Button 구성 요소를 가져 오며 commons 번들이 아닌 각 페이지 번들에 포함되어 있습니다. 스타일링에 필요한 코드는 구성 요소와 번들로 이루어 지므로이 제한은 스타일에도 영향을 미치므로이를 염두에 두어야합니다.
이것은 잘 확립되고 성숙하고 견고한 접근법입니다. 의심 할 여지없이 BEM, SMACCS, OOCSS 또는 기타 확장 가능한 CSS 방법론에 비해 크게 개선되어 CSS, 특히 구성 요소 기반 애플리케이션을 구성하고 구성합니다.
2015 년 에 시작 | 개요로 돌아갑니다
conte 컨텍스트 인식 코드 완료
framework 프레임 워크의 불가지론
스타일/구성 요소 공동 위치가 없습니다
TypeScript 지원이 없습니다
원자 CS가 없습니다
테마 지원이 없습니다
스타일 정의 방법 (들)
스타일 중첩
스타일 적용 방법
classNamestyled 구성 요소css 소품스타일 출력
.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에 의해 유지 | 2017 년 에 출시 | 문서 | ... 개요로 돌아갑니다
✅ 스타일/구성 요소 공동 위치
? 컨텍스트 인식 코드 완료 : 구문 강조 및 코드 완료를 얻으려면 편집기 확장이 필요합니다.
? TypeScript 지원 : @types 추가로 설치할 수 있지만 API가 너무 미미하지 않아 TS가 필요합니다.
원자 CS가 없습니다
테마 지원이 없습니다
프레임 워크가 아닙니다
스타일 정의 방법 (들)
스타일 중첩
스타일 적용 방법
classNamestyled 구성 요소css 소품스타일 출력
.css 파일 추출<style> 태그 주입 elements 도 타겟팅 할 수 있으며 고유 한 클래스 이름을 생성 할 수 있습니다 (그래도 좋은 관행인지 확실하지 않음). 전반적으로, 우리는 구성 요소와 함께 스타일을 정의 할 수 있다는 이점이 추가 된 일반 CSS를 작성하는 것처럼 느껴졌으므로 추가 .css 파일이 필요하지 않습니다 . 실제로 이것은 라이브러리의 철학입니다 : 구성 요소 파일 내부의 CSS 구문 지원. 스트링 보간과 함께 JS/TS 함수 상수를 사용할 수 있습니다. 다이나믹 스타일로 작업하는 것은 결국 평범한 JavaScript이기 때문에 매우 쉽습니다 . 우리는 매우 작은 번들 오버 헤드 로 이러한 모든 혜택을 매우 저렴한 가격으로 얻습니다.
단점은 일반 CSS를 작성하는 전반적인 경험입니다. 중첩 지원 지원 의사 클래스/요소 및 미디어 쿼리는 관리하기가 매우 번거 롭습니다.
| 전송 / 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 및 기타에 의해 유지됨 | 2016 년 에 시작 | 문서 | ... 개요로 돌아갑니다
✅ 스타일/구성 요소 공동 위치
✅ TypeScript 지원 : @types 확실히 설치해야합니다.
✅ 내장 테마 지원
framework 프레임 워크의 불가지론
? 컨텍스트 인식 코드 완료 : 편집기 확장/플러그인이 필요합니다
원자 CS가 없습니다
스타일 정의 방법 (들)
스타일 중첩
스타일 적용 방법
classNamestyled 구성 요소css 소품스타일 출력
.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 & Others에 의해 유지됨 | 2017 년 에 출시 | 문서 | ... 개요로 돌아갑니다
✅ 스타일/구성 요소 공동 위치
typeScript 지원
✅ 내장 테마 지원
Context-AWARE 코드 완료 : styled 구성 요소 접근 방식을 사용하려면 추가 편집기 플러그인이 필요합니다.
framework 프레임 워크의 불가지론
원자 CS가 없습니다
스타일 정의 방법 (들)
스타일 중첩
스타일 적용 방법
className ( @epitions/css 사용)styled 구성 요소css 소품스타일 출력
.css 파일 추출<style> 태그 주입 css Prop은 개발 중에 훌륭한 인체 공학을 제공하지만 React 17 New jsx 변환을 기반으로 한 최신 접근 방식 인 것 같습니다. 구성하는 것은 사소하지 않으며 설정에 따라 다르며 일부 보일러 플레이트를 의미합니다 (곧 변경되고 쉬워야 함). styled 접근 방식을 사용하면 별도의 패키지에서 가져 오기 때문에 번들에 3 kB 추가됩니다.css 소품 및 styled 구성 요소에도 동일). 전반적인 감정은 매우 견고하고 유연한 접근 방식으로 보입니다. 소설 css Prop 접근법은 개발자에게 훌륭한 인체 공학을 제공합니다. 동적 스타일과 타입 스크립트로 작업하는 것은 매우 쉽고 직관적입니다. 스타일을 정의 할 때 strings 과 objects 모두 지원하면 일반 CSS에서 마이그레이션 할 때 또는 처음부터 시작할 때 쉽게 사용할 수 있습니다. 번들 오버 헤드는 무시할 수는 없지만 다른 솔루션보다 훨씬 작습니다. 특히 제공하는 풍부한 기능 세트를 고려할 경우.
성능에 중점을 두지 않고 개발자 경험에 더 중점을 두지 않는 것 같습니다. 완벽한 "다재다능한"솔루션처럼 보입니다.
| 전송 / Gzipped | 압축되지 않은 | |
|---|---|---|
| 인덱스 페이지 크기 | 83.2 KB | 253 KB |
| 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: