ReactJS

[NextJS] CSS Module & Styles JSX & Custom App Component

Gaeun Lee 2022. 9. 2. 17:37

(1) CSS Module

CSS module 사용법

1. 파일명.module.css 파일을 만든다

NavBar.module.css

 .nav {
    display: flex;
    justify-content: center;
    background-color: tomato;
 }

 

2. 생성한 module을 css를 사용하고자 하는 파일 상단에 import 하고 다음과 같이 사용한다

NavBar.js

import styles from "./NavBar.module.css"

export default function NavBar() {
    const router = useRouter()
    return (
        <nav className={styles.nav}>
            <Link href="/">
                <a>Home</a>
            </Link>
            <Link href="/about">
                <a>About</a>
            </Link>
        </nav>
    )
}

 

 

CSS Module의 장점

css.module 형식은 클래스 이름을 추가할 때 클래스 이름을 텍스트로 적는 것이 아니라 자바스크립트 오브젝트에서의 프로퍼티 형식으로 적는다

딸서 클래스 이름을 렌더링된 코드에서 살펴봤을 때 클래스 이름 뒤에 랜덤한 텍스트를 추가한 것을 알 수 있다

이는 클래스 이름 중복으로 인한 충돌을 방지한다

 

CSS Module에서의 복수의 Property 사용

NavBar.module.css

.link { text-decoration: none }
.active { color: tomato }

 

NavBar.js

1. 백틱 이용

import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"

export default function NavBar() {
    const router = useRouter()
    return (
        <nav className={styles.nav}>
            <Link href="/">
                <a className={`${styles.link} ${router.pathname === "/" ? styles.active : ""}`}>Home</a>
            </Link>
            <Link href="/about">
                <a className={`${styles.link} ${router.pathname === "/about" ? styles.active : ""}`}>About</a>
            </Link>
        </nav>
    )
}

 

2. 배열 이용

import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"

export default function NavBar() {
    const router = useRouter()
    return (
        <nav className={styles.nav}>
            <Link href="/">
                <a className={[styles.link, router.pathname === "/" ? styles.active : ""].join(" ")}>Home</a>
            </Link>
            <Link href="/about">
                <a className={[styles.link, router.pathname === "/about" ? styles.active : ""].join(" ")}>About</a>
            </Link>
        </nav>
    )
}

 

(2) Style JSX

1. 스타일을 추가하려는 js 파일에 <style> 태그를 연 후 jsx prop을 추가한다 그리고 스타일 태그 안에 중괄호를 열고 백틱을 입력한다

2. 백틱에 css 형식으로 style을 추가한다

* 주의 : style 태그가 return하는 코드의 가장 바깥 쪽에 있지 않게 한다

 

NavBar.js

import Link from "next/link"
import { useRouter } from "next/router"

export default function NavBar() {
    const router = useRouter()
    return (
        <nav>
            <Link href="/">
                <a>Home</a>
            </Link>
            <Link href="/about">
                <a>About</a>
            </Link>
            <style jsx>{`
                nav {
                    background-color: tomato;
                }
            `}</style>
        </nav>
    )
}

 

이렇게 jsx 형식으로 추가된 스타일이 적용된 태그의 클래스 이름을 확인하면 앞서 추가했던 module css보다 더 무작위한 클래스 이름이 지정되어 있는 것을 볼 수 있다

이는 return하는 component마다 독립적으로 스타일이 적용할 수 있게 하여 스타일 적용을 목적으로 하는 클래스 이름을 꼭 생각하지 않아도 되게 한다

 

 

(ex) Router의 상태에 따라 적용되는 Style

import Link from "next/link"
import { useRouter } from "next/router"

export default function NavBar() {
    const router = useRouter()
    return (
        <nav>
            <Link href="/">
                <a className={router.pathname === "/" ? "active" : ""}>Home</a>
            </Link>
            <Link href="/about">
                <a className={router.pathname === "/about" ? "active" : ""}>About</a>
            </Link>
            <style jsx>{`
                .active {
                    color: yellow
                }
            `}</style>
        </nav>
    )
}

 

 

jsx에서 style을 전역으로 적용하려면 <style>에 global prop을 추가하면 된다

그러나 여기서 주의할 점은 NextJS에서 작업을 할 때에는 CRA와 달리 페이지별로 생각해야 된다는 것이다

그러므로 jsx에서 전역으로 적용되는 style의 범위는 모든 페이지들이 아닌 jsx가 쓰여진 페이지일 뿐이다

 

모든 페이지들에 style을 적용하려면 NextJS가 모든 페이지를 렌더링할 수 있게 하는 App Component를 커스텀해야한다

 

 

Custom App Component

App component를 커스텀하기 위해서는 무조건적으로 pages 폴더 안에 _app.js라는 파일을 만들어야 한다

그러면 NextJS는 _app.js를기반으로 하여 index.js를 렌더링하는 것이다 

_app.js는 페이지의 구성을 설정할 수 있는 하나의 청사진이자 템플릿이라 할 수 있다

그리고 페이지나 컴포넌트에 import 가능한 style은 css module 뿐이지만 _app.js에서는 jsx의 global styles을 import할 수 있다

 

_app.js의 기본 레이아웃

export default function App({Component, pageProps}) {
    return (
        <>
        <Component {...pageProps}/>
        </>
    );
}

 

 

NavBar Component가 항상 나타나게 하려면 다음과 같이 추가한다

import NavBar from "../components/NavBar";

export default function App({Component, pageProps}) {
    return (
        <>
        <NavBar />
        <Component {...pageProps}/>
        </>
    );
}

 

 

_app.js 파일에서 전역 style을 지정하려면 다음과 같이 작성한다

export default function App({Component, pageProps}) {
    return (
        <>
        <Component {...pageProps}/>
        <style jsx global>
            {`
                a {
                    color: white
                }
            `}
        </style>
        </>
    );
}

 

 

_app.js에 전역으로 적용할 css 파일을 적용하려면 적용하려는 css 파일을 _app.js에 import한다

import "../styles/globals.css"