React Component Styling
01. Style Loaders
style-loader, css-loader가 .css나 .scss를 컴파일링해서 빌드함
eject 설정
웹팩설정을 꺼내서 설정을 하기위해 npm run eject
한번해야한다.
커밋하기
eject는 아직 git에 커밋되지 않은 변화가 있다면 진행되지 않아서 먼저 커밋해줘야한다.
git add .
git commit -m "commit before eject
config/webpack.config.js 설정
config/webpack.config.js 열어본다.
임포트 절대경로 설정방법
기존에 상대경로 임포트를 절대경로로 사용하기위해 설정할 수 있는 방법이다.@import '../../../styles/utils';
를@import utiles.scss;
로 사용하기 위해
config/webpack.config.js에서 다음으로 수정한다.
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders({
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap
}).concat({ // 여기부터 추가설정
loader: require.resolve('sass-loader'),
options: {
sassOptions: {
includePath: [path.appSrc + '/styles']
},
sourceMap: isEnvProduction && shouldUseSourceMap,
prependData: `@import 'utils';` // 이부분 추가시 매번 import하지 않아도된다.
}
}),
sideEffects: true
},
컴포넌트 스타일링 4가지 방법
import './App.css';
CSSimport styles from './App.module.css';
CSS Moduleimport './App.scss';
SCSSimport './App.sass';
SASSimport styles from './App.module.scss';
import styles from './App.module.sass';
SASS Module
네가지 종류에 대해서 알아볼거임!
02. CSS, SASS
네이밍규칙BEM 방법론 사용
css를 쓰면 React자체적으로 scoping이 되지는 않아 내부적인 체계가 필요하다.
BEM (block element modifier)방법론으로 네이밍 규칙을 정할 수 있음
BEM 방법론이란
sass설치
App.css 를 App.scss로 수정후 클래스를 중첩하여(SCSS문법은 패스) 수정해주면 컴파일에러가 뜬다.
SASS를 설치해주면 완료npm i sass
03. CSS module, SASS module
module이란?
모듈방식은 몰까?
css파일과 scss파일을 임포트시 전역적으로 적용되어 스코프가 오염되는 문제가 있다.
그런 단점을 피하고자 웹팩을 이용해 모듈을 임포트할때 오염되지않게 추가할 수 있다.
.module.css를 임포트하면 아래와 같이 원래 작성했던 이름과 다르게 변경된 클래스이름을 매칭하여 사용한다.
CSS module 써보기
간단한 Button 컴포넌트를 만들어 CSS모듈을 써볼거임Button.module.css
.button {
background:#fff;
border-radius: 3px;
border: 1px solid red;
}
.loading {
border: 2px solid gray;
color: gray;
}
Button.jsx
import styles from "./Button.module.css";
import React from "react";
// const Button = (props) => <button className={styles["button"]} {...props} />
class Button extends React.Component {
state = {
loading: false,
};
render() {
return <button
className={this.state.loading ? `${styles["button"]} ${styles["loading"]}` : styles["button"]}
onClick={this.startLoading}
{...this.props}
/>;
}
startLoading = () => {
this.setState({
loading: true,
});
console.log(this.state.loading);
setTimeout(() => {
this.setState({
loading: false,
})
}, 5000);
}
}
export default Button;
classnames 라이브러리
클래스를 조건부로 사용할때 유용한 classnames라는 라이브러리를 써볼것이다.
설치 npm i classnames
사용법은 import후 className={classNames('one', 'two')}
처럼 클래스에 사용한다.
classNames("apple", "banana")
// apple bananaclassNames({apple: true}, {banana: false})
// appleclassNames(null, false, "bar", undefined, 0 ,1, {apple :null})
// bar 1classNames(classNames(styles["button"]), classNames(styles["loading"]))
// 각 고유한 classname 나옴
이렇게 truthy한 값만 출력되니까 boolean prop을 받아서 조건부로 사용할 수 있다.
삼항연산자를 간단하게 만들어보자.
// 1. 기존
...
className={this.state.loading ? `${styles["button"]} ${styles["loading"]}` : styles["button"]}
...
// 2. bind하기(classnames에 내장되어 있는 bind함수 사용)
import classNames from "classnames/bind";
const cx = classNames.bind(styles); // 미리 styles에서 클래스를 받아오도록 설정
...
render() {
const {loading} = this.state;
return <button
className={cx("button", {loading})}
onClick={this.startLoading}
{...this.props}
/>;
}
...
classnames에 내장되어 있는 bind함수 사용하면 매번 styles.클래스이름
으로 사용할 필요가 없어진다. 사전에 미리 styles에서 받아온 후 사용하게끔 설정해서 cx("클래스이름", "클래스이름2")
로 사용가능하다.
sass 모듈도 css모듈과 같이 styles객체를 반환하기땜에 똑같이 쓸수 있음! 문법만 sass로 바꿔주면된다.
04. Styled Components (1)
리액트나 create-react-app이 아니라 별도의 라이브러리를 이용해서 편하게 관리할 수있다.
가장 대표적인 라이브러리인 Styled Components다. 두번째는 emotion이 잘 사용된다.
설치
npm i styled-components
사용법
src/components/StyledButton.jsx
import styled from 'styled-components';
const StyledButton = styled.button`
background: blue;
`; // 이사이에 스타일 넣을수있음
export default StyledButton;
겹치지않게 관리해서 클래스를 넣어주고,
스타일을 자동으로 만들어주고,
클래스이름도 자동으로 만들어주고,
그것을 컴포넌트에 추가해주는것이
Styled Components의 역할!
문자열로 들어가서 오타같은것이 났을때 알기 어려워서 신중하게 작성해야한다.
05. Styled Components (2)
props전달받아 스타일 적용하기
StyledCButton.jsx
import styled, { css } from "styled-components";
const StyledButton = styled.button`
background: transparent;
border: 2px solid yellow;
color: yellow;
padding: 10px 20px;
font-size: 24px;
border-radius: 4px;
margin: 10px;
${(props) =>
props.primary &&
css`
background: yellow;
color: #000;
`}
`; // 이사이에 스타일 넣을수있음
export default StyledButton;
부모 컴포넌트에서 직접 커스텀해서 사용하기
App.js
import logo from './logo.svg';
import './App.css';
import StyledButton from "./components/StyledButton";
import styled, { css } from "styled-components";
const PrimaryStyledButton = styled(StyledButton)`
background: yellow;
color: #000;
`;
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<StyledButton>Click</StyledButton>
<StyledButton primary>버튼</StyledButton>
<PrimaryStyledButton>버튼</PrimaryStyledButton>
</header>
</div>
);
}
export default App;
컴포넌트를 다른 element로 만들어 쓰기
<StyledButton as="a" href="/">버튼</StyledButton>
-> a태그로 StyledButton컴포넌트를 만듦
특정 컴포넌트를 만들어 스타일 땡겨(?)쓰기
...
const UppercaseButton = (props) => <button {...props} children={props.children.toUpperCase()} />;
...
<StyledButton as={UppercaseButton}>button</StyledButton>
...
일반적으로 이렇게 쓴다.
const MyButton = (props) => (
<button {...props} children={`MyButton ${props.children}`} />
// 원래 className={props.className}써야 먹혔는데 {...props}해도 됨
);
const StyledMyButton = styled(MyButton)`
background: transparent;
color: ${(props) => props.color || "yellow"};
border: 2px solid ${(props) => props.color || "yellow"};
&:hover { // &을 안쓰면 공백이 들어가서 sass문법으로 써야 먹힘
border: 2px solid red;
}
&::before {
content: "@";
}
`;
...
<StyledMyButton color="green">button</StyledMyButton>
전역으로는 스타일 적용
import styled, { createGlobalStyle } from "styled-components";
// 5. 전역적 사용시 다르게
const GlobalStyle = createGlobalStyle`
button {
color: pink;
}
`;
<GlobalStyle /> // 최상위 바로 아래에 보통 두기
attribute 매번 주기 귀찮을때 일괄적용하기
StyledA.jsx
const StyledA = styled.a.attrs(props => ({
target: "_BLANK"
}))`
color: ${(props) => props.color};
`;
<StyledA href="http://www.google.com">구글</StyledA>
이렇게 사용하면 컴포넌트의 target attribute를 매번 쓰지 않아도된다.
06. React Shadow
HTML안에 원래 HTML에 영향을 주지 않는 별도의 HTML
웹 컴포넌트란?
웹 컴포넌트는 그 기능을 나머지 코드로부터 캡슐화하여 재사용 가능한 커스텀 엘리먼트를 생성하고 웹 앱에서 활용할 수 있도록 해주는 다양한 기술들의 모음
Shadow DOM
캡슐화된 "그림자" DOM 트리를 엘리먼트 — 메인 다큐먼트 DOM 으로부터 독립적으로 렌더링 되는 — 를 추가하고 연관된 기능을 제어하기 위한 JavaScript API 의 집합. 이 방법으로 엘리먼트의 기능을 프라이빗하게 유지할 수 있어, 다큐먼트의 다른 부분과의 충돌에 대한 걱정 없이 스크립트와 스타일을 작성할 수 있습니다.
react-shadow 설치
npm i react-shadow
컴포넌트를 shadowDOM으로 작업하여 다른곳에 있는 CSS영향 받지 않게 만들기
(스코프 격리 ? )
단점 : style이 보통 공통적으로 쓰는게 많아서 매번 써야함.
외부와 내부가 차단되어있기때문에 값을 받아쓰는데 제약이 있다.
그러므로...
css, styled component, shadowDOM 등 상황에 맞게 적절히 사용해야한다.
import logo from './logo.svg';
import root from 'react-shadow';
const styles = `
(App.css내용)
`;
function App() {
return (
<root.div>
{/* index의 css 영향 받지않게 */}
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
<style type="text/css">{styles}</style>
</root.div>
);
}
export default App;
07. Ant Design
Ant Design 바로가기
이미디자인된것을 가지고 만들수 있다.
Ant Design 설치
npm i antd
기본적으로 만들어진 컴포넌트를 사용하면 만들어진 스타일도 적용됨
전역 css를 제공하고 있어서 임포트 적용해야함
import 'antd/dist/antd.css';
해야된다고 하는데 하니까 에러나서 삭제해줬더니 정상작동됨. 버전 바뀌면서 수정되었나보다..
원래 이렇게 각 컴포넌트 css도 따로 가져와야 적용됐는데 이점을 개선하고자 자동화 하기위해 eject했어야했다.. (권장X 방법)
그런데 이제 하지 않아도 적용 잘 되는듯!!
Ant Design Icons
백오피스 등 만들때, 간단한 홈페이지 만들때 사용하기 좋음npm install --save @ant-design/icons
따로 설치 필요함
컴포넌트 사용시 props를 제일 많이 중요시해야함
API 문서 잘 보기
그리드 시스템
그리드시스템도 제공하고있으니 사용하면 좋을것같다.
gutter는 16+8n의 정수
span의 총합은 24
offset은 띄어진 크기라 offset과 span의 합이 24가 되어야함
'Frontend > React' 카테고리의 다른 글
[React] 포켓몬도감 만들기2 (0) | 2023.12.08 |
---|---|
[React] 포켓몬도감 만들기1 (1) | 2023.12.08 |
[emotion] 이모션을 styled-component처럼 사용하기(@emotion/styled) (0) | 2023.09.05 |
react component event handling (0) | 2021.10.12 |
리액트 컴포넌트 Props와 State (0) | 2021.10.12 |