React Component Styling

스카치·2023년 2월 16일
0

Style Loaders

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, SASS

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

CSS module, SASS module

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 Components

Styled Components (1)

Styled Componenets : cra나 react가 아닌 별도의 라이브러리로 컴포넌트에 스타일을 지정하는 방법론

Styled Componenets를 지원하는 라이브러리

  • Styled Componenets
  • Emotion

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'



StyledButton에 props를 전달해서 props에 맞는 디자인을 보여주고 싶을 때

방법1

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

방법2

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 />
}
  

Styled Components (2)

Styled Components를 이용해 전역적으로 스타일을 주는 방법

App.js =>

import {createGlobalStyle} from 'styled-components'

const GlobalStyle =createGlobalStyle`
	
	// scope적용된 button을 제외한 button의 전역스타일 지정
	
	button { 
    	color: yellow;
    }

function App() {
	return (
	...
	<GlobalStyle />
	)
}
`

태그에 특정 기능을 준 props를 기본설정하기

새 창에서 열기(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>
    )
}

React Shadow

웹 컴포넌트 : 표준
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

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를 분할해서 가져오기

자동화해서 가져오기

ant-design 아이콘 사용

npm install --save @ant-design/icons

Apps.js =>

import {GithubOutlined} from '@ant-design/icons'

function App() {
	<GithubOutlined />
}

컴포넌트 라이브러리를 사용할 때는
가져올 컴포넌트의 api(props)를 확인해서 사용해야 데이터를 전달하기 좋다



ant-design 레이아웃 잡기

// gutter = 컬럼사이에 gutter만큼 띄운다 gutter={16 + 8n의 정수}px

// offset : offset만큼 띄우고 span이 차지함

// 좌우정렬 : justify 위아래정렬 : align

type='flex'는 생략해도 됨

0개의 댓글