.SassComponent {
display: flex;
background-color: $oc-gray-2; // SassComponent의 배경색을 open-colors 팔레트 라이브러리에서 불러온 후 설정
@include media('<768px') { // 화면 가로 크기가 768px 미만이 되면 배경색을 어둡게 바꿔줌
background: $oc-gray-9;
}
.box { // 일반 CSS 에서는 .SassComponent .box와 마찬가지
background: red;
cursor: pointer;
transition: all 0.3s ease-in;
&.red {
// .red 클래스가 .box와 함께 사용되었을 때
background: $red;
@include square(1);
}
&.orange {
background: $orange;
@include square(2);
}
&.yellow {
background: $yellow;
@include square(3);
}
&.green {
background: $green;
@include square(4);
}
&.blue {
background: $blue;
@include square(5);
}
&.indigo {
background: $indigo;
@include square(6);
}
&.violet {
background: $violet;
@include square(7);
}
&:hover {
// .box에 마우스를 올렸을 때
background: black;
}
}
}
node_modules에서 라이브러리 불러오기 예시 실행 결과 - 크기를 줄이면 색이 바뀜
3.CSS Module
CSS Module?
- CSS를 불러와서 사용할 때 클래스 이름을 고유한 값으로 자동으로 만들어서 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지해 주는 기술 - 형태: [파일 이름]_[클래스 이름]_[해시 값] - v2 버전 이상부터는 따로 설정할 필요 없이 .module.css 확장자로 파일을 저장하면 CSS Module이 적용됨 - 만든 클래스(class)는 스타일을 직접 불러온 컴포넌트 내부에서만 작동함
3-1. CSS Module 사용하기
CSS Module 사용 예시 -src/CSSModule.module.css
/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
/* 글로벌 CSS를 작성하고 싶다면 - global: 특정 클래스가 웹 페이지에서 전역적으로 사용되는 경우 사용 */
:global .something {
font-weight: 800;
color: aqua;
}
CSS Module 사용 예시 -src/CSSModule.js
import styles from "./CSSModule.module.css";
const CSSModule = () => {
console.log(styles);
/* 출력결과 - wrapper: "CSSModule_wrapper__MKjbW
CSS Module이 적용된 스타일 파일을 불러오면 객체를 하나 전달받게 되는데 CSS Module에서 사용한 클래스 이름과 해당 이름을 고유화한 키-값이 형태로 들어있음
파일이름: CSSModule, 클래스: wrapper, 해시값:MKjbW */
return (
<div className={styles.wrapper}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
CSS Module 사용 예시 -src/App.js
import { Component } from "react";
import CSSModule from "./CSSModule";
class App extends Component {
render() {
return (
<div>
<CSSModule />
</div>
);
}
}
export default App;
CSS Module 사용 예시 실행 결과console.log(styles); 결과
CSS Module 사용 예시2(클래스 여러개) -src/CSSModule.module.css
/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
.inverted {
color: black;
background: white;
border: 1px solid black;
}
/* 글로벌 CSS를 작성하고 싶다면 - global: 특정 클래스가 웹 페이지에서 전역적으로 사용되는 경우 사용 */
:global .something {
font-weight: 800;
color: aqua;
}
CSS Module 사용 예시2(클래스 여러개) -src/CSSModule.js
import styles from "./CSSModule.module.css";
const CSSModule = () => {
console.log(styles); // 출력결과 - wrapper: "CSSModule_wrapper__MKjbW / {wrapper: 'CSSModule_wrapper__MKjbW', inverted: 'CSSModule_inverted__YwyLv'}
// CSS Module이 적용된 스타일 파일을 불러오면 객체를 전달받게 되는데 CSS Module에서 사용한 클래스 이름과 해당 이름을 고유화한 키-값이 형태로 들어있음
// 파일이름: CSSModule, 클래스: wrapper, 해시값:MKjbW
return (
<div className={`${styles.wrapper} ${styles.inverted}`}>
{/* className={[styles.wrapper, styles.inverted].join(' ')} 와 동일*/}
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
CSS Module 사용 예시2(클래스 여러개) -src/App.js
import { Component } from "react";
import CSSModule from "./CSSModule";
class App extends Component {
render() {
return (
<div>
<CSSModule />
</div>
);
}
}
export default App;
CSS Module 사용 예시2 실행 결과
3-2. classnames로 간편화
classnames란?
- css 클래스를 조건부로 설정할 때 매우 유용한 라이브러리 - CSS Module 사용 시 이 라이브러리를 사용하면 여러 클래스를 적용할 때 매우 편리함
CSS Module을 사용할 때 클래스를 여러 개 설정하거나, 또는 조건부로 클래스를 설정할 때 classnames의 bind를 사용하면 훨씬 편리하게 작성이 가능해집니다.
classnames로 bind 사용 예시-src/CSSModule.js
import classNames from "classnames/bind";
import styles from "./CSSModule.module.css";
const cx = classNames.bind(styles); // classnames에 내장되어 있는 bind 함수를 사용하면 클래스를 넣어 줄 때마다 styles.[클래스 이름] 형태를 사용할 필요가 없습니다.
// 사전에 미리 styles에서 받아 온 후 사용하게끔 설정해두고, cx('클래스 이름', '클래스 이름2') 형태로 사용할 수 있습니다.
const CSSModule = () => {
return (
<div className={cx("wrapper", "inverted")}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
나머지 코드는 아래와 동일하며 실행결과도 3-1.CSS Module 사용 예시2(클래스 여러개) 와 같습니다.
CSS Module 사용 예시2(클래스 여러개) -src/CSSModule.module.css
CSS Module 사용 예시2(클래스 여러개) -src/App.js
classnames로 bind 사용 예시 & Sass(scss)와 함께 사용하기- src/CSSModule.module.scss
/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
&.inverted {
// inverted가 .wrapper와 함께 사용되었을 때만 적용
color: black;
background: white;
border: 1px solid black;
}
}
/* 글로벌 CSS를 작성하고 싶다면 - global: 특정 클래스가 웹 페이지에서 전역적으로 사용되는 경우 사용 */
:global {
.something {
font-weight: 800;
color: aqua;
}
}
classnames로 bind 사용 예시& Sass(scss)와 함께 사용하기 -src/CSSModule.js
import classNames from "classnames/bind";
import styles from "./CSSModule.module.scss";
const cx = classNames.bind(styles); // classnames에 내장되어 있는 bind 함수를 사용하면 클래스를 넣어 줄 때마다 styles.[클래스 이름] 형태를 사용할 필요가 없습니다.
// 사전에 미리 styles에서 받아 온 후 사용하게끔 설정해두고, cx('클래스 이름', '클래스 이름2') 형태로 사용할 수 있습니다.
const CSSModule = () => {
return (
<div className={cx("wrapper", "inverted")}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
나머지 코드는 아래와 동일하며 실행결과도3-1.CSS Module 사용 예시2(클래스 여러개)와 같습니다.
CSS Module 사용 예시2(클래스 여러개) -src/App.js
3-3. css파일에서 CSS Module 사용하기
/* CSS Module이 아닌 일반 .css, .scss 파일에서도 :local을 사용하여 CSS Module을 사용할 수 있음 */
:local .wrapper {
}
4. styled-components
컴포넌트 스타일링의 방식 중 하나로 자바스크립트 파일 안에 스타일을 선언하는 방식이 있습니다.(CSS-IN-JS)
CSS-IN-JS 라이브러리는 많은 종류가 있는데, 그 중에 개발자의 선호도가 가장 높은 styled-components에 대해 알아보겠습니다. 그 외 emotion 등이 있습니다.
styled-components를 사용하면 자바스크립트 파일 하나에 스타일까지 작성이 가능합니다. 따라서 .css 또는 scss 확장자를 가진 스타일 파일을 따로 만들지 않아도 되는 장점이 있습니다.
styled-components와 일반 classNames를 사용하는 CSS/Sass를 비교했을 때, styled-components의 가장 큰 장점은 props 값으로 전달해주는 값을 쉽게 스타일에 적용할 수 있다는 점입니다.
styled-components 설치 명령어
yarn add styled-components
styled-components 설치 명령어 실행 결과
+vscode 스타일 확장 프로그램
vscode-styled-components
4-1. Tagged 템플릿 리터럴
4. styled-components 사용 예시 코드를 보면 스타일 작성 시 `(백틱)을 사용해 만든 문자열에 스타일 정보를 넣어주었습니다. 이러한 문법을 Tagged 템플릿 리터럴이라 부릅니다.
즉, 템플릿 안에 자바스크립트 객체나 함수를 전달할 때 온전히 추출할 수 있다는 장점이 있습니다.
styled-components는 이러한 속성을 사용해 styled-components로 만든 컴포넌트의 props를 스타일 쪽에서 쉽게 조회할 수 있도록 해줍니다.
4-2. 예시
styled-components 사용 예시 -src/StyledComponent.js
import styled, { css } from "styled-components";
// 단순 변수의 형태가 아니라 여러 줄의 스타일 구문을 조건부로 설정해야 하는 경우에는 css를 불러와야 합니다
// 반응형 디자인 함수화 하기 => styled-components 매뉴얼에서 제공하는 유틸 함수를 따라 사용
const sizes = {
desktop: 1024,
tablet: 768,
};
// 위에 있는 size 객체에 따라 자동으로 media 쿼리 함수를 만들어 줍니다.
// 참고: https://www.styled-components.com/docs/advanced#media-templates
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (...args) => css`
@media (max-width: ${sizes[label] / 16}em) {
${css(...args)};
}
`;
return acc;
}, {});
const Box = styled.div`
/* props로 넣어 준 값을 직접 전달해 줄 수 있습니다. */
background: ${(props) => props.color || "blue"};
padding: 1rem;
display: flex;
${media.desktop`width:768px`}
${media.tablet`width: 100%`};
/* 반응형 디자인 */
/* 기본적으로는 가로 크기 1024px에 가운데 정렬을 하고
가로 크기가 작아짐에 따라 크기를 줄이고
768px 미만이 되면 꽉 채웁니다 */
/* width: 1024px;
margin: 0 auto;
@media (max-width: 1024px) {
width: 768px;
}
@media (max-width: 768px) {
width: 100%;
} */
`;
const Button = styled.button`
// 스타일 작성 시 백틱을 사용해 만든 문자열에 스타일 정보를 넣어줌 => Tagged 템플릿 리터럴 문법임
// styled.태그명 으로 구현함. styled.button 뒤에 Tagged 템플릿 리터럴 문법을 통해 스타일을 넣으면, 해당 스타일이 적용된 button으로 이루어진 리액트 컴포넌트가 생성됨.
// 나중에 <Button>Hello</Button>으로 사용 가능
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
/* & 문자를 사용하여 Sass처럼 자기 자신 선택 가능*/
&:hover {
background: rgba(255, 255, 255, 0.9);
}
/* 다음 코드는 inverted 값이 true일 때 특정 스타일을 부여해 줍니다. */
${(props) =>
props.inverted &&
css`
/* 스타일 코드 여러 줄을 props에 따라 넣어 주어야 할 때는 CSS를 styled-components에서 불러와야 합니다
여기서 css+백틱이 아닌 그냥 백틱으로 바로 문자열을 넣어도 동작하기는 합니다.
css를 지우게 되면, VS Code 확장 프로그램에서 syntax 하이라이팅이 제대로 이루어지지 않는다는 단점이 있습니다.
더욱 치명적인 단점은 Tagged 템플릿 리터럴이 아니기 때문에 함수를 받아 사용하지 못해 해당 부분에서는 props 값을 사용하지 못합니다.
만약 조건부 스타일링을 할때 props를 참조하지 않는다면 굳이 CSS를 불러올 필요는 없습니다. */
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
// 사용해야 할 태그명이 유동적이거나 특정 컴포넌트 자체에 스타일링 해주고 싶은 경우
// // 태그의 타입을 styled 함수의 인자로 전달
// const MyInput = styled("input")`
// background: gray;
// `;
// // 특정 컴포넌트에 스타일링을 해주고 싶은 경우에는(컴포넌트를 styled의 파라미터에 넣는 경우)
// // 해당 컴포넌트에 className props를 최상위 DOM의 className 값으로 설정하는 작업이 내부적으로 되어있어야 함
// const Sample = ({ className }) => {
// return <div className={className}>Sample</div>;
// };
// // 아예 컴포넌트 형식의 값을 넣어 줌
// const StyledLink = styled(Link)`
// color: blue;
// `;
const StyledComponent = () => (
<Box color="black">
<Button>안녕하세요</Button>
<Button inverted={true}>테두리만</Button>
</Box>
);
export default StyledComponent;
styled-components 사용 예시 -src/App.js
import { Component } from "react";
import StyledComponent from "./StyledComponent";
class App extends Component {
render() {
return (
<div>
<StyledComponent />
</div>
);
}
}
export default App;