react로 개발을 하면 SPA이기 때문에 class나 id를 제대로 구분하지 않으면 css가 겹쳐버리는 현상이 발생한다.
그래서 styled-components를 사용하면 알아서 임의의 id 또는 class로 구분시켜주기 때문에 css가 겹치지 않고 사용이 가능하다.
npm install styled-components
import React from 'react';
const Test = () => {
return (
<div>
<div>
반갑습니다.
<div>
<span>안녕하세요</span>
</div>
</div>
</div>
);
};
export default Test;
이런식으로 있다고 가정했을 때 원래는 새로운 css를 만들어서 맨 위에서 import를 해와야 했을 것이다. 하지만 styled-components를 쓰면 다른 방식으로 할 수 있다.
import React from 'react';
import styled from 'styled-components'; // stlyed-components를 불러온다
// styled. 뒤에 자신이 사용하고 싶은 jsx tag를 입력한다. 현재 코드에서 TestDiv라는 변수로 div처럼 이용 가능하다. 그 밑에 css 코드를 적는다.
const TestDiv = styled.div`
background : yellow;
& div {
color : red;
& span {
color : blue;
}
}
`;
const Test = () => {
return (
<TestDiv>
<div>
반갑습니다.
<div>
<span>안녕하세요</span>
</div>
</div>
</TestDiv>
);
};
export default Test;
React Component 만들듯이 대문자로 시작하는 변수명으로 만들어주고 styled.div 뒤에 backtick을 붙여주고 그 안에 css 코드를 적는다. 그냥 적으면 TestDiv의 css를 수정하는 것이다. &은 자기 자신을 뜻하고 & div를 하면 자신 자식, 손자 등 모든 div의 css를 수정하는 것이다. 그리고 &은 자기 자신을 가리키는데 블록 scope를 갖기 때문에 {} 마다 가리키는 태그가 바뀐다. 잘 보고 사용해야한다!!
위 코드를 실행하게 되면 이런식으로 나오게 된다. 만약에 jsx 태그 말고 antd 같은 ui framework의 css를 덮어 씌우고 싶다면
import styled from 'styled-components';
import { Button } from 'antd';
const TestDiv = styled(Button)`
background : yellow;
`;
이런식으로 사용해야한다.
문제: 처음에 css가 적용하지 않은 채로 잠시 나왔다가 css가 적용된다. 뭔가 보기가 안 좋다.
해결 : styled-components에 ssr을 적용하면 처음부터 css가 적용 된 상태로 나오게 된다.
import React from "react";
import Document, { Main, NextScript, Head } from "next/document"; //next의 html과 나머지 기타 기능들을 넣어주는 Main과 NextScript
import Helmet from "react-helmet"; // head태그에 넣을 정보를 jsx로 작성할 수 있게 도와준다.
import { ServerStyleSheet, createGlobalStyle } from "styled-components";
// _document.js는 index.html을 꾸며주는거다라고 생각하면 된다.
// class형으로 밖에 못 하는게 조금 아쉽다.
// ServerStyleSheet을 사용하여 서버사이드렌더링을 하게 할 수 있다.
// 전체적으로 css를 주고 싶은 부분은 createGlobalStyle을 사용하여 가능하다.
const GlobalStyles = createGlobalStyle`
html, body {
height: 100%;
overflow: auto;
}
#__next {
height: 100%;
}
`;
class MyDocument extends Document {
static getInitialProps(context) {
const sheet = new ServerStyleSheet(); // 서버사이드 렌더링 할 수 있게함.
const page = context.renderPage(App => props =>
sheet.collectStyles(
<>
<GlobalStyles />
<App {...props} />
</>
)
); // 아래의 스타일들을 모아서 페이지를 그려준다. 원래는 <GlobalStyles/> 없이 하는데 글로벌 스타일을 지정해주기 위해 저렇게 적었다.
const styleTags = sheet.getStyleElement();
return { ...page, helmet: Helmet.renderStatic(), styleTags };
}
render() {
const { htmlAttributes, bodyAttributes, ...helmet } = this.props.helmet; // helmet으로 부터 받아온다.
const htmlAttrs = htmlAttributes.toComponent();
const bodyAttrs = bodyAttributes.toComponent();
return (
//html이랑 head, body 부분에 각각 props들을 넣어준다
<html {...htmlAttrs}>
<Head>
{this.props.styleTags}
{Object.values(helmet).map(el => el.toComponent())}
</Head>
<body {...bodyAttrs}>
<Main />
<NextScript />
</body>
</html>
);
}
}
export default MyDocument;
이런식으로 작성을 하게 되면 페이지들이 서버로부터 그려져 나와서 처음부터 css가 적용이 된 페이지를 볼 수 있을 것이다!!