Styling Methods
react에는 여러가지 styling method가 있다.
- Radium
- Styled component
- CSS module
Radium
일반적으로 변수에 css 속성을 설정하고 JSX의 Style attribute에 설정하면 되지만
media query나 pseudo class등의 동적인 css는 적용되지 않는다.
이를 해결하기 위한 third party app이 “Radium”이다.
import Radium, {StyleRoot} from "radium"
class App extends Component {
state = {
persons: [
{id: "1", name: ""}
],
otherValue: "for the Test"
}
changePersonNameHandler = (event) => {
let persons = [...this.state.persons]
let input = event.target.value;
let id = event.target.id;
let targetPersonIndex = persons.findIndex(el => el.id === id);
if(targetPersonIndex !== -1){
persons[targetPersonIndex].name = input;
}else{
const randomId = Math.floor(Math.random() * 1000);
const newOb = {
id: randomId,
name: input
}
persons.push(newOb);
}
this.setState({
persons: persons
});
}
render() {
const style = {
backgroundColor:'green',
color: "white",
font: "inherit",
border: "1px solid blue",
padding: "8px",
cursor: "pointer",
//원래는 text-align이지만 JSX의 법칙에 따라 camel case로 작성
textAlign: "center",
//1. 여기서 직접 적용해도 되고
":hover": {
backgroundColor: "lightgreen",
color: "black"
}
}
//2. 밖에서 수정해 적용하는 것도 가능하다.
style.background = "red";
style[":hover"]: {
backgroundColor: "lightgreen",
color: "black"
}
//mediaQuery
const mediaStyle = {
"@media (min-width: 500px)": {
width: "450px"
}
};
return (
//!!! meidaQuery 같은 동적인 css를 적용하기 위해선 <StyleRoot>로 반드시 감싸줘야한다.
<StyleRoot>
<div className="App">
{
this.state.persons.map((person, index) => {
return (<div>
<PersonInput key={person.id} id={person.id} change={this.changePersonNameHandler} style={mediaStyle}></PersonInput>
</div>);
})
}
<button style={style} onClick={this.plusPersonDivHandler}>Plus more person div</button>
</div>
</StyleRoot>
);
}
}
//Radium 사용법 : export시에 이렇게 Radium으로 감싸줘야한다.(style을 먹이고 싶은 component 모두에 이렇게 하면 된다.)
export default Radium(App);
Styled Component
React에서 가장 널리쓰이는 것으로 css문법을 그대로 사용할 수 있고 적용한 것이 head tag에 적용되기 때문에 적용을 원하는 component나 tag에 똑같이 중복적용할 수 있다.
JS 내부에서 스타일을 정의한다.
import styled from "styled-components";
class App extends Component {
width = "60%";
//div tag안에 적용될 css를 css문법 그대로 적어 넣는다.
//sass문법도 적용된다.
//JS의 string 전략도 적용 가능핟.
StyledDiv = styled.div`
width: ${this.width},
margin: 16px auto;
border: 1px solid black;
box-shadow: 0 2px 3px black;
padding: 16px;
text-align: center;
&: hover: {
background-color: red;
color: black;
}
@media(min-width: 500px) {
width: 450px;
}
`
render() {
return (
//위에 css를 적용한 div를 이곳에 그대로 적용한다는 뜻이다.
<StyledDiv>
<p>styled component</p>
</StyledDiv>
);
}
}
export default App;
CSS Module
CSS 클래스를 만들면 자동으로 고유적인 클래스네임을 만들어서 스코프를 지역적으로 제한하는 방식
즉, 특정 component에만 .css를 적용 시키고 싶을 때 사용한다.(css를 import하면 같은 page안에 같은 class 이름이 있을 경우 해당 css를 모두에게 적용시킨다.)
특이하게 이건 install이 필요없이 webpack configure만 바꾸어 사용이 가능하다. 구체적으로 웹팩의 css-loader 를 통하여 불러오는 방식
Web-pack configuration
!! react-script v.2 이상이라면 person.module.css로 css파일을 만들고 import하여 그대로 사용하면 eject하여 configure해줄 필요가 없이 자동으로 CSS Module을 적용시켜준다.
사용하기에 앞서 설정을 해주어야한다.
우선 npm run eject 으로 web-pack config를 보이게 하고 config/webpack.config.dev.js를 열어 css-loader를 찾는다.
보통은 이렇게 되어있다.
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
//이곳이 수정할 곳!
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
위의 3가지 loder들은
- style-loader 가 스타일들을 불러와서 페이지에서 활성화 해주는 역할
- css-loader 는 css 파일에서 import 와 url(…) 문들을 webpack 의 require 기능을 통하여 처리해주는 역할
- postcss-loader 의 경우에는, 우리가 입력한 CSS 구문이 모든 브라우저에서 제대로 작동할 수 있도록 자동으로 -webkit, -mos, -ms 등의 접두사를 붙여준다.
이 중 css-loader에 집중! option에서 CSS Module을 사용하도록 아래 두가지를 option에 설정해주면 된다.
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
//필수적인것을 포함했다면 형식은 마음대로 설정할 수 있다!
//localIdentName: '[name]__[local]__[hash:base64:5]'
첫번째 속성은 CSS Module 을 활성화, 두번째 속성 localIdentName 은 CSS Module 에서 고유적으로 생성되는 클래스네임의 형식을 정해준다. 해당 형식에 따라 random하게 이름이 붙는다.
webpack.config.dev.js와 마친가지로 webpack.config.prod.js에도 동일하게 적용!
webpack.config.dev.js 는 우리가 개발 할 때 사용하는 웹팩 개발 서버 전용 설정이며, webpack.config.prod.js 는 나중에 리액트 프로젝트를 완성하고 배포하게 될 때 빌드하는 과정에서 사용되는 환경설정 파일이다.
이제 적용해보면!
.box {
display: inline-block;
color: white;
font: inherit;
border: 1px solid blue;
padding: 8px;
cursor: pointer
}
.inner {
background-color: green;
}
import style from './App.css'
class App extends Component {
render() {
//이렇게 class를 합쳐 여러 css를 한번에 적용시킬 수도 있다.
const assignedClass = [style.box, style.inner].join(" ");
return (
//broser에서 ClassName을 보면 random으로 생성된걸 확인할 수 있다.
<div>
<p className={style.box}>styled component</p>
<div className={assignedClass}></div>
</div>
);
}
}
export default App;
ref: https://velopert.com/3447