CRA 안의 webpack 설정이 파일 확장자에 맞는 loader에게 위임
Style Loaders는 .css를 다룸
npx create-react-app style-loaders-example
cd style-loaders-example
npm run eject // webpack 설정이 어떻게 되어있는지 꺼내서 확인하기 위해
code. -r
config -> webpack.config.js
.css
검색
style로더에서 각 확장자를 어떻게 다루는지 확인할 수 있다.
css, scss를 import 하고 사용하기
src --> App.css
npm start
f12 -> elements에서
React는 컴포넌트 별로 style을 지정할 수 없다. 따라서 전역적으로 모든 컴포넌트에 스타일이 지정될 수 있으므로 규칙을 정해 클래스를 지정해서 컴포넌트 별로 스타일을 따로 지정해준다.
그로인해 BEM(block-elements-modifier)이라는 방법론 사용
https://getbem.com/naming/에서 확인
css -> scss 변경
npm i sass
npm start
cra 사이트에서 Adding css Modules 확인
css혹은 sass를 react에 사용하면 전역 스타일이 scope를 오염시킬 수 있으므로 module을 이용해 scope 적용
import styles from './App.module.css';
App.module.css 생성 App.css 내용을 복사
console.log(styles)
>> [filename]\_[classname]\_\_[hash] 형식으로 고유한 해쉬값으로 지정할 수있음 => scope
==> Module 해시값을 이용해 전역변수에 오염되지 않는 고유한 키값으로 스타일 적용
실습
src -> components 생성 => Button.jsx 생성
Button.jsx=>
import styles from './Button.modules.css';
const Button =props => <button className={styles['button']} {...props} />
export default Button
Button.modules.css 생성 =>
.button {
background :transparent;
border-radius : 3px;
border : 2px solid palevioletred;
color : palevioletred;
margin : 0 1em;
padding : 0.25em 1em;
font-size : 20px;
}
App.js에서 Button 사용해보기
App.js =>
import Button from './components/Button.jsx'
function App() {
return (
...
<Button>Button<Button>
)
}
만약 버튼을 눌렀을 때 잠시동안 로딩상태를 표현하기 위해
로딩이라는 스테이트에 로딩에 맞는 스타일을 적용하고 싶다
-> 조건부 클래스네임, 여러 클래스 네임을 한꺼번에 써야할때
Button.modules.css =>
.button {
...
}
.loading {
border : 2px solid grey;
color : grey;
}
Button.jsx=>
import styles from './Button.modules.css';
class Button extends React.Component {
state = {
loading : false
}
render () {
return <button onClick={this.startLoading}
className={this.state.loading
? `${styles['button']} ${styles['loading']}`
: styles['button']
}
{...this.props} />
}
startLoading = () => {
this.setState({
loading: true,
})
setTimeout( () => {
this.setState({
loading: false,
})
},1000)
}
}
export default Button
classnames : classname이 복잡해질 때 쓸수 있는 라이브러리
npm i classnames
npm start
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
const {loading} = this.state;
console.log(cx('button', 'loading') >> 해시값
//---------------//
className={this.state.loading }
? `${styles['button']} ${styles['loading']}`
: styles['button']
}
과
className= {classNames(cx('button', {loading})}
// -----------------//
classNames('button', 'loading') 는 같음
classNames({foo : true}, {baa : false}) >> foo
classNames(null, false, 'bar', undefined, 0, 1, {baz: null}, '' )
\>> bar 1
Styled Componenets : cra나 react가 아닌 별도의 라이브러리로 컴포넌트에 스타일을 지정하는 방법론
Styled Componenets를 지원하는 라이브러리
Styled Componenets
- npx create-react-app styled-components-example
- cd styled-components-example
- npm i styled-components
- code . -r
- npm start
src => components => StyledButton.jsx 생성
StyledButton.jsx =>
//스타일을 먹인 컴포넌트 만들기
import styled from 'styled-components
const StyledButton = styled.button``; // styled.[html elements]
export default StyledButton'
App.js=>
버튼에 클래스 지정을 안해도 클래스가 생성되어있음
StyledButton.jsx =>
//스타일을 먹인 컴포넌트 만들기
import styled from 'styled-components
const StyledButton = styled.button`
// css문법
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color : palevioletred;
margin :0 1em;
padding : 0.25em 1em;
font-size : 20px;
`; // styled.[html elements]
export default StyledButton'
App.js =>
import StyledButton from './components/StyledButton'
function App() {
return (
<StyledButton primary>버튼 </StyledButton>
)
}
StyledButton.jsx =>
import styled, {css} from 'styled-components
const StyledButton = styled.button`
// css문법
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color : palevioletred;
margin :0 1em;
padding : 0.25em 1em;
font-size : 20px;
// props를 전달받아 style적용
${props => props.primary &&
css`
background: palevioletred;
color : white;
` }
`
export default StyledButton
App.js ->
const PrimaryStyledButton = styled(StyledButton)`
// styled.[elements] 는 이미 있는 태그만가능
// 만든 태그를 쓰고싶으면 styled(만든태그)
background: palevioletred;
color : white;
`
function App() {
...
<PrimaryStyledButton>버튼</PrimaryStyledButton>
}
만든 태그의 스타일을 다른 태그에도 적용하고 싶다 => as 사용
<StyleedButton as= "a" href="/">
버튼
</StyleedButton>
// <StyleedButton />태그에 사용된 <button>태그가 <a>태그로 대체된것과 같음
as로 특정 elements가 아니라 특정 컴포넌트에 사용해서 스타일을 적용시킬 수도 있다.
App.js ->
const UppercaseButton = (props) => (
<button {...props} children={props.children.toUpperCase()} />
);
function App() {
...
<StyleedButton as{UppercaseButton}>Button</StyleedButton>
}
혹은
App.js ->
/* const UppercaseButton = (props) => (
<button {...props} children={props.children.toUpperCase()} />
);*/
const MyButton = props => <button {...props} children={`MyButton ${props.children} />
// const MyButton = props => <button className={props.className} children={`MyButton ${props.children} />
const StyledMyButton = styled(MyButton)`
background: transparent;
border-radius: 3px;
border: 2px solid ${props => props.color || 'palevioletred'};
color : palevioletred;
margin :0 1em;
padding : 0.25em 1em;
font-size : 20px;
:hover {
border : 2px solid red;
}
::before{
content: "@":
}
`
function App() {
...
// <StyleedButton as{UppercaseButton}>Button</StyleedButton>
<StyledMyButton color='green'>button<StyledMyButton />
}
App.js =>
import {createGlobalStyle} from 'styled-components'
const GlobalStyle =createGlobalStyle`
// scope적용된 button을 제외한 button의 전역스타일 지정
button {
color: yellow;
}
function App() {
return (
...
<GlobalStyle />
)
}
`
새 창에서 열기(target='_BLANK') 기능이 기본으로 있는 a태그 만들기
components => StyledA.jsx 생성
StyledA.jsx=>
import styled from 'styled-components'
const StyledA = styled.a.attrs( (props) => ({
target='_BLANK'
}))`
color: ${ (props) => props.color}
`
export default StyledA
App.js =>
function App() {
render (
...
<StyledA href="https://google.com">태그</StyledA>
)
}
웹 컴포넌트 : 표준
Shadow Dom : 본래 html과 영향을 주지 않는 별도의 html dom
shadow dom을 이용해서 전역 스타일에 의해 scope가 오염되지 않도록할 수 있다.
npx create-react-app react-shadow-example
cd react-shadow-example
npm i react-shadow
code . -r
npm start
src => index.css =>
p {
color :red;
}
=> App.js의 내용이 바뀜 => p태그의 영향을 받음
App컴포넌트 만의 Shadow Dom을 가지고 그 안에서만 스타일을 적용한다면 다른 곳의 스타일에 영향을 안받음
Apps.js =>
import root from 'react-shadow';
const styles = '
p {
color: yellow;
}
'
function App() {
return (
<root.div>
//...
<style type='text/css'>{styles}</style>
</root.div>
// root.div로 감싼 영역에만 스타일이 적용됨.
// 전역스타일에 오염되지 않지만 공통된 스타일을 항상 항상 가져와야하는 불편함
// 외부와 내부가 차단되어있어서 외부에서 지정된 값을 받아 사용할 때 제약이 있음.
// ==> <root.div>로 감싸진 부분은 외부 전역 스타일에 영향받지 않음
)
}
Ant Design : 이미 디자인된 컴포넌트의 모음
npx create-react-app antd-example
cd antd-example
npm i antd
code . -r
npm start
Ant design 사용하기
index.js =>
import 'antd/dist/antd.css'
antd를 전역적으로 가져오기
antd를 분할해서 가져오기
자동화해서 가져오기
npm install --save @ant-design/icons
Apps.js =>
import {GithubOutlined} from '@ant-design/icons'
function App() {
<GithubOutlined />
}
컴포넌트 라이브러리를 사용할 때는
가져올 컴포넌트의 api(props)를 확인해서 사용해야 데이터를 전달하기 좋다
// gutter = 컬럼사이에 gutter만큼 띄운다 gutter={16 + 8n의 정수}px
// offset : offset만큼 띄우고 span이 차지함
// 좌우정렬 : justify 위아래정렬 : align
type='flex'는 생략해도 됨