import './App.css' // css 파일 import
// src/styles/utils.scss
// 변수 사용하기
$red: #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
// 믹스인 만들기 (재사용되는 스타일 블록을 함수처럼 사용 할 수 있음)
@mixin square($size) {
$calculated: 32px * $size;
width: $calculated;
height: $calculated;
}
// utils.cscc를 불러와서 사용할 scss
@import 'styles/utils';
.SassComponent {
display: flex;
background: $red;
.box {
background: red;
cursor: pointer;
transition: all 0.3s ease-in;
}
}
npm run eject
라고 입력하면 세부 설정을 밖으로 꺼낼 수 있다. 명령어 입력 전에 모든 파일을 커밋해야한다.// sassRegex 로 검색하여 아래 부분을 찾는다.
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap
},
'sass-loader'
),
sideEffects: true
},
// 위 부분을 아래와 같이 수정
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap
}
).concat(
{
loader: require.resolve('sass-loader'),
options: {
sassOptions: {
includePaths: [paths.appSrc + '/styles']
},
sourceMap: isEnvProduction && shouldUseSourceMap,
prependData: `@import 'utils';`
// 모든 Sass 파일에 utils를 import 하는 옵션
}
}
),
sideEffects: true
},
npm run eject
입력 후 서버가 재시작 되지 않으면, node_modules 디렉토리를 삭제 후 npm install
npm start
명령어를 입력해야한다.// 라이브러리는 상대경로로 불러와야 한다.
@import '../../../node_modules/library/style';
// ~ 을 사용하면 편하게 해당 디렉토리에 접근 가능
@import '~library/style';
npm i --save craco-alias @craco/craco
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
}
// 절대경로 설정 정보를 갖고 있는 파일
// paths 형식 : path_alias: [실제경로]
// path_alias로 상대경로가 아닌 절대경로 사용가능
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"styles/*": ["src/styles/*"], // src/style 내부에 있는 파일은 이제 style로 접근 가능
"components/*": ["src/components/*"]
}
}
}
{
"extends": "./tsconfig.paths.json",
"comilerOptions": {
// 생략...
}
// 생략...
}
const CracoAlias = require('craco-alias');
module.exports = {
plugins: [
{
plugin: CracoAlias,
options: {
source: 'tsconfig',
baseUrl: './', // tsconfig.paths.json에 있는 baseUrl 경로값과 동일하게 설정.
tsConfigPath: 'tsconfig.paths.json',
},
},
],
};
[파일 이름]_[클래스 이름]_[해시값]
형태의 고윳값으로 만들어 클래스 이름이 중첩되는 현상을 방지한다..module.css
확장자로 저장하면 CSS Module가 적용된다.:global
키워드를 앞에 입력하면 된다./* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용가능*/
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
/* 글로벌 CSS 를 작성하고 싶다면 */
:global {
// :global {} 로 감싸기
.something {
font-weight: 800;
color: aqua;
}
}
import React from 'react';
import styles from './CSSModule.module.scss';
const CSSModule = () => {
return ( // 클래스 이름을 두 개 이상 적용 시 템플릿 리터럴 사용
<div className={`${styles.wrapper} ${styles.box}`}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
npm install classnames
로 라이브러리 설치import classNames from 'classnames';
// 함수의 매개변수에 원하는 클래스 이름 전달
classNames('one', 'two'); // one, two
// 객체를 매개변수로 전달 - 조건부 클래스 설정
classNames('one', { two: true}); // one, two
classNames('one', { two: false}); // one
// 배열을 매개변수로 전달
classNames('one', [ 'two', 'three']); // one, two, three
// 외부 변수를 매개변수로 전달
const myClass = 'hello'
classNames('one', myClass, { myCondition: true }) // one, hello, myCondition
// props 값에 따른 스타일링
const MyComponent = ({ highlighted, them }) => (
<div className={ classNames('MyComponent', { highlighted }, them) }>
Hello
</div>
)
bind
함수를 사용하면 클래스를 넣어줄 때 마다 style.[클래스 이름]
형식으로 코드를 작성하지 않아도 된다. 사전에 미리 style 객체에서 클래스를 받아 온 후 사용하게끔 설정해두고 cx('클래스1', '클래스2')
형식으로 사용할 수 있다.import React from 'react';
import classNames from 'classnames/bind';
import styles from './CSSModule.module.scss';
const cx = classNames.bind(styles); // 미리 styles 에서 클래스를 받아오도록 설정하고
const CSSModule = () => {
return (
<div className={cx('wrapper', 'inverted')}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
.module.scss
로 저장하면 CSS Module를 사용할 수 있다.npm i styled-components
[object Object]
로 변환되고, 함수는 함수 내용이 그대로 문자열화 되어 나타난다.`hello ${{foo: 'bar'}} ${() => 'world'}`;
// 결과 : "hello [object Object] () => 'world'"
function tagged(...args) { console.log(args); }
tagged`hello ${{foo: 'bar'}} ${() => 'world'}`;
import styled from 'styled-components'; // 1. styled 불러오기
// 2. styled.태그명 형식으로 메소드 호출
// 3. Tagged 템플릿 리터럴 문법을 통해 역따옴표 안에 스타일 작성
const MyComponent = stlyed.div`
font-size: 2rem;
`;
// 위 스타일이 적용된 div로 이뤄진 리액트 엘리먼스 생성
// 4. 생성된 엘리먼트를 아래와 같은 형태로 사용
<MyComponent>Hello</MyComponent>
// div가 아닌 다른 엘리먼트에 스타일을 입히고 싶다면 styled.button, styled.input 형식으로
// styled.태그명을 사용하면된다.
// 태그의 타입을 styled 함수의 인자로 전달
const MyInput = styled('input')`
background: gray;
`;
// 컴포넌트를 styled 함수의 인자로 전달
// 이 방식을 사용할 경우 해당 컴포넌트에 className props를 최상위 DOM의 className 값으로 설정해야 한다.
const MyComponent = ({className}) => {
return <div className={className}>Hello</div>;
};
const StyledMyComponent = styled(MyComponent)`
color: red;
font-size: 2rem;
`;
const Box = styled.div`
/* props로 넣어준 값을 직접 전잘해줄 수 있다. */
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
`;
// JSX에서 사용 시 color 값을 props로 넣어준다.
<Box color="red"></Box>
import styled, { css } from 'styled-components';
// 단순 변수의 형태가 아니라 여러 줄의 스타일 구문을 조건부로 설정하는 경우
// styled-components의 css를 불러와야한다.
const Button = styled.button`
background: black;
color: white;
border-radius: 4px;
padding: 0.5rem;
/* & 를 사용하여 sass처럼 자기자신 선택 가능 */
&:hover { background: rgba(255, 255, 255, 0.9); }
/* inverted 값이 true일 경우 특정 스타일 부여 */
${ props =>
props.inverted &&
css`
background: white;
border: 2px solid black;
&:hover {
background: white;
color: black;
}
`
}
`;
// JSX
<Button>Hello</Button>
<Button invertes={true}>태두리만</Button>
// 스타일 코드 여러줄을 props에 따라 넣어주어야 할 경우 styled-components의 css가 필요하다.
// css 없이 바로 아래와 같이 문자열을 넣어도 작동은한다.
// 하지만 해당 내용이
${ props =>
props.inverted &&
`
background: none;
border: 2px solid white;
&:hover {
background: white;
color: black;
}
`
}
`;
const Box = styled.div`
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
width: 1024px;
margin: 0 auto;
@media (max-width: 1024px) { width: 768px; }
@medis (max-width: 768px) { width: 100%; }
`;
import styled, { css } from 'styled-components';
const sizes = {
desktop: 1024,
tablet: 768
};
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`
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
width: 1024px;
margin: 0 auto;
${media.desktop`width: 768px;`};
${media.tablet`width: 100%;`};
`;