Webpack을 사용하여 자바스크립트 파일에서 import 키워드로 불러온 CSS 파일은 모든 자바스크립트 파일에 적용되는 CSS 파일입니다.
즉, 프로젝트 내 작성된 CSS 파일들은 모든 자바스크립트 파일에 적용되는 "전역 스타일"로서 사용됩니다.
CSS 파일이 하나의 자바스크립트 파일에만 적용되도록 하는 다양한 기법이 있습니다. 여기서는 두 가지 방법에 대해서 알아보겠습니다.
"styled-components"는 특정 "스타일이 첨부된 리액트 엘리먼트"를 빌드하는 것을 도와주는 패키지입니다. 작성한 스타일은 첨부된 리액트 엘리먼트에만 영향을 미치고, 다른 컴포넌트에는 영향을 주지 않습니다. 즉, 리액트 엘리먼트에게 고유한 스타일이 적용됩니다.
먼저 "styled-components"를 사용하려면 패키지를 설치해야합니다. 터미널에 사용할 프로젝트로 디렉토리를 이동한 다음에 아래와 같은 명령어를 입력하여 "styled-components" 패키지를 설치합니다.
npm install --save styled-components
그리고 컴포넌트 파일에서 styled-components 패키지의 "styled" 객체를 import 합니다.
import styled from 'styled-components;
styled 객체에서 "메서드를 호출"하는 형식으로 컴포넌트를 정의합니다. 메서드로는 "모든 html 태그 이름"으로 메서드가 존재합니다(styled.p
,styled.div
, styled.button
,,,).
즉, 메서드 이름으로 작성된 리액트 엘리먼트를 반환하는 컴포넌트가 반환됩니다.
메서드를 호출할 때 괄호()
을 사용하지 않고 백틱( `` )
을 사용하여 호출합니다. 그리고 "백틱 안에는 엘리먼트에 적용될 스타일 코드"를 작성합니다. 메서드는 백틱안에 작성한 스타일이 첨부된 리액트 엘리먼트를 반환하는 컴포넌트입니다.
백틱 내 스타일을 작성할때 기본 CSS 문법과 다른 점으로는 선택자 없이 작성한 스타일 코드는 기본적으로 생성되는 엘리먼트에 적용되는 기본 스타일이며, &
를 사용하여 생성되는 엘리먼트를 선택자로서 사용할 수도 있습니다.
import styled from 'styled-componenets';
cosnt MyComponent = styled.div` // -> div 엘리먼트 생성
// 스타일 코드 작성
// 선택자 없는 스타일 코드는 생성될 div 엘리먼트에게 적용
width: 100px;
height: 100px;
background-color: #fff;
transition: all 3000ms ease-in-out;
// & -> 생성될 div 엘리먼트
&:hover {
width: 150px;
height: 150px;
background-color: #0066ff;
}
`;
export default MyComponent;
위 코드에서 MyComponent 변수에는 div 엘리먼트가 바인딩됩니다. 이때 바인딩되는 div 엘리먼트는 백틱 안에 작성된 "스타일이 첨부된" div 엘리먼트입니다.
내부적으로는 styled-components 패키지가 백틱 안에 작성된 스타일을 보고 "동적으로 고유한 클래스 이름을 생성"합니다. 생성된 클래스 이름으로 작성된 스타일을 래핑하고 이 클래스를 전역 CSS로 추가합니다. 그리고 엘리먼트에는 생성된 클래스 이름을 적용하여 스타일을 갖도록 합니다.
styled 객체의 메서드에 의해 반환되는 컴포넌트를 JSX 문법으로 작성할 때, html 어트리뷰트와 대응하는 어트리뷰트를 카멜 케이스로 작성하면 이는 생성되는 엘리먼트에게 적용되는 html 어트리뷰트로서 적용됩니다.
즉, 기존 html 태그 이름을 문자열로 JSX 문법을 사용할 때 html 어트리뷰트에 대응하는 어트리뷰트(onClick, htmlFor, className 등,,)를 작성하면 styled-components 패키지가 내부적으로 작성된 어트리뷰트가 적용된 엘리먼트를 생성해줍니다.
그리고 JSX 문법의 Content 영역에 작성한 내용들 또한 화면에 그대로 렌더링됩니다.
import styled from 'styled-components';
const Button = styled.button`
// css 스타일 코드,,,
`;
const clickHandler = (event) => { ,,, };
<Button type="submit" onClick={clickHandler}>click</Button>
위 Button 컴포넌트는 styled 객체의 button 메서드로 생성한 컴포넌트입니다. 이때 type, onClick 처럼 html 어트리뷰트와 대응하는 어트리뷰트들은 생성될 button 엘리먼트에 자동적으로 적용됩니다.
기존에는 컴포넌트를 JSX 문법으로 작성할 때 Content 영역에 작성한 내용들은 화면에 렌더링되지 않았지만 styled-components로 생성한 컴포넌트의 경우 Content 영역에 작성한 내용들이 화면에 렌더링됩니다.
즉, styled 객체의 메서드로 생성한 컴포넌트는 "html 태그 이름으로 JSX 문법을 사용하는 것과 사용법이 동일"합니다. JSX 문법을 사용할 때 html 어트리뷰트와 대응하는 어트리뷰트를 작성하여 엘리먼트를 설정할 수 있고, 태그 사이의 내용들도 화면에 렌더링됩니다. 단지 스타일이 첨부터된 리액트 엘리먼트로 볼 수 있습니다.
html 어트리뷰트와 대응하지 않는 어트리뷰트들은 백틱 내부에서 props 객체의 프로퍼티로 접근이 가능합니다.
백틱 내 스타일 프로퍼티 값으로 ${,,,}
내부에 "props 객체를 인수로 전달받는 함수"를 사용하여 동적으로 스타일링이 가능합니다. 해당 함수는 styled-components 패키기가 실행하며 인수로 props 객체를 전달받아 실행합니다.
정의한 함수는 CSS 프로퍼티 값을 문자열로 반환해야 합니다.
import styled from 'styled-componenets';
cosnt MyComponent = styled.div`
width: 100px;
height: 100px;
// 백틱 내부에서는 props 객체를 인수로 전달받는 함수를 정의하고
// 함수의 반환값으로 작성한 문자열로 동적 스타일링이 가능
background-color: ${props => props.invalid ? '#ffd7d7' : '#fff'};
transition: all 3000ms ease-in-out;
&:hover {
width: 150px;
height: 150px;
background-color: #0066ff;
}
`;
// invalid는 html 어트리뷰트와 대응하지 않음
// props객체에 invalid라는 프로퍼티로 전달
cosnt myCompnent = <MyComponent invalid={!isValid} />;
기본적으로 import한 모든 CSS 파일의 스타일 코드는 범위가 지정되지 않는 전역 스타일로서 사용됩니다. 이는 클래스 이름이 충돌되는 문제를 발생시킬 수도 있습니다.
이러한 문제, 즉 다른 컴포넌트의 스타일에 영향을 주지 않게 하기 위해서 "CSS Modules"이라는 기능을 사용할 수 있습니다.
CSS 파일에 작성한 스타일 코드를 "CSS 파일을 import하는 컴포넌트 파일로 범위가 제한"되도록 합니다.
먼저 CSS 파일의 이름을 "파일이름.module.css"
형태 사용해야 합니다. 이는 코드 변환이 이루어지 위해서 다음과 같은 형식의 이름을 사용합니다.
그리고 CSS 파일에서 객체를 import 합니다. 이때 import하는 객체 이름은 일반적으로 "styles" 또는 "classes"를 사용합니다.
import classes from '파일이름.module.css';
CSS 파일에서 import한 classes(styles) 객체에는 CSS 파일에서 작성한 "모든 클래스 선택자 이름"이 프로퍼티 키로 저장되어 있습니다.
즉, 우리는 classes.클래스이름
을 className 값으로 작성하여 스타일을 적용시킬 수 있습니다.
예를 들어, CSS 파일에 작성한 .invalid
라는 클래스 선택자는 classes.invalid
로 사용할 수 있습니다. 모든 클래스 이름을 이렇게 사용해야 합니다.
브라우저에 최종적으로 렌더링된 엘리먼트를 살펴보면 class 어트리뷰트의 값으로 "컴포넌트이름_클래스이름__고유해시"
형태로 적용되어 있습니다.
즉, CSS Module이 하는 일은 기본적으로 CSS 파일에서 CSS 클래스를 가져와서 "클래스 이름을 고유한 이름"으로 바꿔 줍니다. 우리는 단지 CSS Modules에 의해 생성된 변환된 클래스 이름을 추출하여 사용하는 것 뿐이지 이전과 큰 차이점은 없습니다.