CSS 모듈(Module)
CSS 모듈은 CSS를 모듈화 하여 사용하는 방식입니다. CSS 클래스를 만들면 자동으로 고유한 클래스네임을 만들어서 scope를 지역적으로 제한합니다. 모듈화된 CSS를 번들러로 불러오면 다음과 같이 사용자가 정의했던 클래스네임과 고유한 클래스네임으로 이뤄진 객체가 반환됩니다.
CSS 모듈은 동일 프로젝트 소스 안에 CSS 클래스 이름이 중복되어도
새로운 이름이 입혀져 중복 및 관리의 위험성이 적고 CSS 네이밍 규칙이 간소화 됩니다
곳에서 모든 것을 작성하지 않기 때문에 별도로 많은 CSS 파일을 만들어 관리해야 한다
Sass/SCSS
less
Stylus
PostCSS
모두 개념 자체는 동일하지만 약간의 Syntax 가 다르다.
전처리기를 위한 도구 필요
퍼블리셔나 디자이너가 개발에 대한 역할과 요소 접목으로 개발적인 요소 알아야함
개발자에 한해서만 Learning curve 낮음
하나씩 살펴보자
SASS: Syntactically Awesome Style Sheets
SCSS: Sassy CSS
둘의 차이점을 구문을 통해 알아보자
SASS
$font-color: #fff $bg-color: #00f #box color: $font-color background: $bg-color
SCSS
$font-color: #fff; $bg-color: #00f; #box{ color: $font-color; background: $bg-color; }
두 코드 모두 컴파일되면
#box { color: #fff; background: #00f; }
같은 CSS 코드로 변환된다.
Sass와 SCSS는 기능적으로 봤을때 유의미한 차이가 없으며, 문법적인 방식에서 차이가 있다.
Sass와 SCSS의 핵심적인 차이는 {}(중괄호)와 ;(세미콜론)의 유무이다.
셀렉터 중첩 기능으로 선택자를 중복사용, 과용하는 걸 줄일 수 있고 구조 파악에도 용이하다.
조건문, 반복문, 함수 등 프로그래밍적 요소들을 지원한다.
웹에서 동작 가능한 표준 CSS로 컴파일해서 동작시킴(웹에서는 CSS만 동작)
변수/함수/상속 개념을 활용하여 재사용 가능하다
디버깅의 어려움이 있음
컴파일한 CSS 파일이 거대해짐
작업이 크고 고도화 될수록 유지 보수에 더 많은 시간과 비용을 발생시킴
front end 개발을 하다보면 한번은 아니 여러번 들어봤을 법한 프레임워크다.
Bootstrap은 Sass 로 작성되었다. 버전 3까지는 Bootstrap이 LESS로 작성되었지만 Bootstrap 4는 Sass를 채택하여 인기를 높였다고 한다.
그렇다면 LESS는 뭔데?
Sass는 Ruby로 작성되었지만 LESS는 JavaScript로 작성되었다. 실제로 LESS는 믹스인, 변수, 중첩 및 규칙 집합 루프를 사용하여 기본 바닐라 CSS의 기능을 확장하는 JavaScript 라이브러리다.
스타일러스는 Node로 작성되었으며 JavaScript 스택에 완벽하게 맞다.
Stylus는 여전히 Node 개발자에게 인기가 있지만 자체적으로 상당한 점유율을 확보하지 못했다. Sass 또는 LESS에 비해 Stylus의 한 가지 장점은 매우 강력한 내장 기능으로 무장하고 무거운 컴퓨팅을 처리할 수 있다.
구문
@font-color: #fff; @bg-color: #00f #box{ color: @font-color; background: @bg-color; }
사실상 요즘 트렌드는 CSS-in-JS이다
그렇다면 왜?
중복되지 않는 class 이름을 고려할 필요가 없다.
JS 코드와 CSS가 상태 값을 공유할 수 있다.
컴포넌트와 스타일 코드를 쉽게 오갈 수 있다.
자동으로 vendor-prefix을 붙여준다.
⇒ 개발 친화적!! DX ( Developer Experience )
css-in-js의 동작 방식은 크게 runtime, zero-runtime 으로 나눠진다.
javascript runtime에서 필요한 CSS를 동적으로 만들어 적용한다.
대표적으로 잘 알려진 styled-component, emotion 이 있다.
CSS를 컴포넌트 안으로 캡슐화(모듈화)
JavaScript로 작성된 컴포넌트에 바로 삽입하는 스타일 기법
(Javascript 환경을 최대한 활용)
->css-loader가 필요 없다 : css파일을 생성하지 않기에 webpack에서 css-loader가 필요 없다.
자유로운 CSS 커스텀 컴포넌트를 만들 수 있음
Sass 라이브러리 설치 없이 Sass 문법을 사용
네이밍이나 최적화를 신경 쓸 필요가 없음
코드 경량화
빠른 페이지 로드에 불리, 느린 성능을 보여줄 수 있음
별도의 라이브러리를 설치해야 하므로 번들 크기가 커짐
CSS를 줄 태그를 전부 컴포넌트로 만들어야함
들어는 보았지만 한번도 사용본적이 없다. 이번 기회에 알아보자
styled-components와 전반적인 스타일 기능은 같다. 둘다 sass문법을 사용하기에 스타일 문법에도 차이가 없다.
styled-componets가 더 많이 사용되고 있으나 npm 다운로드 횟수를 보면 emotion이 더 많다.
성능상 둘은 유의미하게 차이가 나지 않는다.
emotion의 퍼포먼스가 전반적으로 더 좋게 나오고 있고 라이브러리 버전에 따라서 차이가 발생할 수 있다.
css props 기능
인라인 스타일을 작성하지만 클래스가 되는 매직 ✨
<div style={{color: "red"}}/>
기존 style 속성은 HTML 인라인 스타일로 주입이 된다.
스타일 우선순위를 다루기 어렵고 스타일 재활용도 힘들다.
<div css={{color: "red"}} />
{/* 혹은 */}
<div css={css`color: red`} />
emotion jsx에서 제공해주는 css 속성을 활용하면 이를 클래스로 변환해준다.
기존 인라인으로 사용할 수 없었던 media query, pseudo selector, nested selector 등을 사용할 수 있다.
css props를 결합하여 복잡한 스타일링을 진행할 수 있다.
<div css={[style, themes[theme], sizes[size]]} />
const themes = {
primary: css`
color: red;
`,
secondary: css`
color: blue;
`
}
const sizes = {
small: css`
fontSize: 0.75rem;
`,
medium: css`
fontSize: 1rem;
`
}
위와 같이 css 변수를 조립하여 컴포넌트 스타일링을 진행할 수 있다.
type ThemeType = keyof typeof themes;
type SizeType = keyof typeof size;
typescript로 자동 타입지정까지 할 수 있는 이점이 있다.
css override는 덤
SSR
SSR에서 별도의 설정 없이 동작이 된다.
반면 styled-components 같은 경우 ServerStyleSheet을 설정 해야 한다.
결론
다음 플젝 때 한번 써볼까 오호
run time으로 동작되는 위 아이들은
사용자들의 여러 동작들로 인해 동적으로 추가되는 스타일링은 parse ,compile 과정 등등이 추가적으로 일어나게 되었다
UI 렌더링이 지연되기도 하였다 (많은 js들이 실행되고 난뒤 실행되서)
자바스크립트 실행에 실패하면 스타일들이 제대로 렌더되지않았다. (JavaScript errors are a lot more probable than CSS or HTML errors.)
이런 문제점들이 발생할 수 있다고 한다. 그래서 이를 개선하고자 zero runtime에 관심이 높아지고 있다.
그런데, 빌드시 css파일이 생기는 예전으로 회귀하는게 아닌가..? 사실 Zero Runtime CSS 라는 것은 예전에도 있었다..! 하지만 과거에는 prop이나 state에 의한 동적 스타일링을 지원하지 않은 채로, 단순한 정적 스타일 파일을 빌드 시간에 생성하는 것에 그쳤다.
생긴건 emotion/styled 나 styled-components랑 비슷한데 뭐가 다른가?
간단히 말해, Emotion 및 Styled Components와 같은 JS 라이브러리의 CSS는 브라우저에서 페이지가 로드될 때 스타일을 구문을 분석해 적용하고(runtime) Linaria는 프로젝트를 빌드할 때(예: webpack) CSS 파일에 스타일을 추출하고 CSS 파일이 로드되는 방식 (zero runtime) 이다.
그러면 기존의 동적 스타일링은 구현할 수 없는가?
그렇지 않다.
Linaria는 Babel Plugin과 Webpack Loader를 사용해서 빌드될 때 별도의 CSS 파일을 생성하게 되는 데 이 파일 안에서 prop이나 state 등에 의한 값들을 CSS Variable로 정의하고 CSS Variable의 값을 변경시킴으로써 동적 스타일링을 구현할 수 있다.
JS 코드 상에서 Linaria에 넘겨주는 Prop을 변경하게 되면 inline-style로 CSS 변수값이 변경
그러면 CSS 스타일 내에서 해당 변수를 참조하고 있기 때문에 해당 요소에 적용되고 있는 스타일이 변하고 이로써 동적 스타일링이 구현한다.
Styled Component가 새로운 스타일 클래스를 만들고 그 클래스의 이름을 요소의 class 속성으로 넣어줌으로써 동적 스타일을 구현했다면 Linaria는 CSS 변수값만 바꿔줌으로써 이를 구현
장점
zero runtime css-in-js는 run time css-in-js에서의 DX는 유지하면서, 웹성능 문제가 상충하는 상황도 해결하려 노력했다
CSS가 JS와 동일한 번들에 있는 runtime css-in-js와 달리 CSS와 JavaScript를 병렬로 로드할 수 있으므로 로드 시간이 향상
CSS 구문 분석과 같은 추가 작업이 런타임에 수행될 필요가 없기 때문에 런타임 성능이 향상
개인적으로 공부하고 싶었던 css 네이밍 규칙에 대해 적어보려한다.
BEM은 Block, Element, Modifer의 줄인 말로 일종의 네이밍 컨벤션입니다. 컴포넌트 기반의 웹 개발론 중 하나라고 보면 된다.
BEM 규칙을 이용해 만든 네이밍은 직관적이고, 재사용성이 좋고, 중복을 방지할 수 있다.
항상 영어 소문자만을 사용합니다. 카멜 케이스 등은 사용하지 않습니다.
일반적으로 한 요소는 하이픈으로 연결합니다. (예를 들면 input-text, button-submit, modal-alert 등등.. )
네이밍의 조합은 형태-의미-순서-상태 순으로 사용합니다. (예시 button-submit-03-disable)
언더스코어는 파일, 폴더, 이미지 등에만 사용합니다(image_elysia_asset_01.png)
숫자를 사용할 때는 확장성을 고려해 1, 2 이런 식으로 표현하지 않고 01, 02, 03… 혹은 001, 002, 003처럼 사용합니다. 앞에 0을 붙이지 않으면, 이미지 정렬 시 1 다음에 2가 오지 않고 10이 오는 등, 정렬 순서가 엉망이 될 수 있기 때문입니다.
Block
블록은 기능적으로 독립되어 재사용될 수 있는 컴포넌트
입니다.
Good!
<button class="button"> ... </button>
<header class="header"> ... </header>
<div class="modal"> ... </div>
<textarea class="textarea"> ... </textarea>
Bad
<p class="red-text"> ... </p>
<input type="radio" class="big-radio-button"> ... </input>
<button class="deep-blueable-awesome-thing"> ... </button>
Element
요소는 블록에서 분리되어 사용할 수 없는, 블록의 일부분입
니다. 요소는 서로 중첩될 수 없습니다.
두 개의 밑줄(underscore, __)로 표현됩니다.
<div class="qna-form">
<p class="qna-form__text">
....
</p>
<div>
Modifier
속성(Modifier)은 block이나 element 행동이나 상태 또는 외양을 정의
하는 객체입니다.
속성의 경우 한개의 밑줄(_) 또는 하이픈(-)을 추가하여 표시합니다.
<!-- 굳이 enable을 지정하진 않고, 따로 Modifier를 붙이지 않습니다 -->
<div class="modal__button--disable"> </div>
<!-- 키와 값을 하이픈으로 연결합니다 -->
<div class="image--theme-ocean"> </div>
<div class="button--color-deep-blueable"> </div>
각 태그들의 컴포넌트 명
컴포넌트들을 묶어주는 컴포넌트 명
참고
https://velog.io/@heyiminhye/CSS-전처리기-프레임워크-정리
https://ideveloper2.dev/blog/2022-01-25--emotion%EC%9C%BC%EB%A1%9C-%ED%8C%8C%EC%95%85%ED%95%B4%EB%B3%B4%EB%8A%94-css-in-js%EC%9D%98-%EC%9D%B4%EB%AA%A8%EC%A0%80%EB%AA%A8/#zero-runtime