스타일링

Nuxt 애플리케이션을 스타일링하는 방법을 알아보세요.

Nuxt는 스타일링 측면에서 매우 유연합니다. 직접 스타일을 작성하거나, 로컬 및 외부 스타일시트를 참조할 수 있습니다. CSS 전처리기, CSS 프레임워크, UI 라이브러리 및 Nuxt 모듈을 사용해 애플리케이션을 스타일링할 수 있습니다.

Local Stylesheets

로컬 스타일시트를 작성한다면, 자연스러운 위치는 app/assets/ 디렉터리입니다.

Importing Within Components

페이지, 레이아웃 및 컴포넌트에서 스타일시트를 직접 가져올 수 있습니다. JavaScript import 또는 CSS @import을 사용할 수 있습니다.

app/pages/index.vue
<script>
// 서버 사이드 호환성을 위해 정적 import를 사용하세요
import '~/assets/css/first.css'

// 주의: 동적 import는 서버 사이드와 호환되지 않습니다
import('~/assets/css/first.css')
</script>

<style>
@import url("~/assets/css/second.css");
</style>
스타일시트는 Nuxt가 렌더링한 HTML에 인라인으로 포함됩니다.

The CSS Property

Nuxt 설정에서 css 속성을 사용할 수도 있습니다. 스타일시트의 자연스러운 위치는 app/assets/ 디렉터리입니다. 그런 다음 해당 경로를 참조하면 Nuxt가 애플리케이션의 모든 페이지에 이를 포함합니다.

nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/css/main.css'],
})
스타일시트는 Nuxt가 렌더링한 HTML에 인라인으로 포함되며, 전역으로 주입되어 모든 페이지에 존재합니다.

Working With Fonts

로컬 폰트 파일은 public/ 디렉터리에, 예를 들어 public/fonts에 두세요. 그런 다음 스타일시트에서 url()을 사용해 참조할 수 있습니다.

assets/css/main.css
@font-face {
  font-family: 'FarAwayGalaxy';
  src: url('/fonts/FarAwayGalaxy.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

그런 다음 스타일시트, 페이지 또는 컴포넌트에서 이름으로 폰트를 참조합니다:

<style>
h1 {
  font-family: 'FarAwayGalaxy', sans-serif;
}
</style>

Stylesheets Distributed Through NPM

npm을 통해 배포되는 스타일시트를 참조할 수도 있습니다. 예시로 인기 있는 animate.css 라이브러리를 사용해 보겠습니다.

npm install animate.css

그런 다음 페이지, 레이아웃 및 컴포넌트에서 직접 참조할 수 있습니다:

app/app.vue
<script>
import 'animate.css'
</script>

<style>
@import url("animate.css");
</style>

패키지는 Nuxt 설정의 css 속성에서 문자열로도 참조할 수 있습니다.

nuxt.config.ts
export default defineNuxtConfig({
  css: ['animate.css'],
})

External Stylesheets

nuxt.config 파일의 head 섹션에 link 요소를 추가하여 애플리케이션에 외부 스타일시트를 포함할 수 있습니다. 이 결과는 여러 방법으로 달성할 수 있습니다. 로컬 스타일시트도 이 방식으로 포함할 수 있다는 점에 유의하세요.

Nuxt 설정의 app.head 속성을 사용해 head를 조작할 수 있습니다:

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }],
    },
  },
})

Dynamically Adding Stylesheets

코드에서 useHead 컴포저블을 사용해 head에 값을 동적으로 설정할 수 있습니다.

Read more in Docs > 4 X > API > Composables > Use Head.
useHead({
  link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }],
})

Nuxt는 내부적으로 unhead를 사용하며, 전체 문서를 참고할 수 있습니다.

Modifying The Rendered Head With A Nitro Plugin

더 고급 제어가 필요하다면, 훅을 사용해 렌더링된 html을 가로채고 head를 프로그래밍 방식으로 수정할 수 있습니다.

다음과 같이 ~/server/plugins/my-plugin.ts에 플러그인을 생성하세요:

server/plugins/my-plugin.ts
export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook('render:html', (html) => {
    html.head.push('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">')
  })
})

외부 스타일시트는 렌더링 차단 리소스입니다. 브라우저가 페이지를 렌더링하기 전에 반드시 로드되고 처리되어야 합니다. 불필요하게 큰 스타일을 포함한 웹 페이지는 렌더링에 더 오래 걸립니다. 이에 대해 더 알고 싶다면 web.dev를 참고하세요.

Using Preprocessors

SCSS, Sass, Less 또는 Stylus와 같은 전처리기를 사용하려면 먼저 설치해야 합니다.

npm install -D sass

스타일시트를 작성하기에 자연스러운 위치는 app/assets 디렉터리입니다. 그런 다음 전처리기 문법을 사용해 app.vue(또는 레이아웃 파일)에서 소스 파일을 가져올 수 있습니다.

app/pages/app.vue
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>

또는 Nuxt 설정의 css 속성을 사용할 수도 있습니다.

nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/scss/main.scss'],
})
두 경우 모두, 컴파일된 스타일시트는 Nuxt가 렌더링한 HTML에 인라인으로 포함됩니다.

색상 변수와 같은 Sass partial에 코드를 주입해야 하는 경우, Vite의 preprocessors options를 사용해 그렇게 할 수 있습니다.

app/assets 디렉터리에 일부 partial을 생성하세요:

$primary: #49240F;
$secondary: #E4A79D;

그런 다음 nuxt.config에서:

export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "~/assets/_colors.scss" as *;',
        },
      },
    },
  },
})

Nuxt는 기본적으로 Vite를 사용합니다. 대신 webpack을 사용하고 싶다면, 각 전처리기 로더의 문서를 참고하세요.

Preprocessor Workers (Experimental)

Vite에는 전처리기 사용 속도를 높일 수 있는 실험적 옵션이 제공됩니다.

nuxt.config에서 이를 활성화할 수 있습니다:

export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorMaxWorkers: true, // CPU 개수 - 1
    },
  },
})
이는 실험적 옵션이므로 Vite 문서를 참고하고 피드백을 제공해야 합니다.

Single File Components (SFC) Styling

Vue와 SFC의 가장 좋은 점 중 하나는 스타일링을 자연스럽게 처리하는 능력입니다. 컴포넌트 파일의 style 블록에 직접 CSS 또는 전처리기 코드를 작성할 수 있으므로, CSS-in-JS 같은 것을 사용하지 않고도 훌륭한 개발자 경험을 얻을 수 있습니다. 하지만 CSS-in-JS를 사용하고 싶다면, pinceau와 같이 이를 지원하는 서드파티 라이브러리와 모듈을 찾을 수 있습니다.

SFC에서 컴포넌트를 스타일링하는 것에 대한 포괄적인 참고 자료는 Vue 문서를 참고하세요.

Class And Style Bindings

클래스 및 스타일 속성을 사용해 컴포넌트를 스타일링하기 위해 Vue SFC 기능을 활용할 수 있습니다.

<script setup lang="ts">
const isActive = ref(true)
const hasError = ref(false)
const classObject = reactive({
  'active': true,
  'text-danger': false,
})
</script>

<template>
  <div
    class="static"
    :class="{ 'active': isActive, 'text-danger': hasError }"
  />
  <div :class="classObject" />
</template>

자세한 내용은 Vue 문서를 참고하세요.

Dynamic Styles With v-bind

스타일 블록 내에서 v-bind 함수를 사용해 JavaScript 변수와 표현식을 참조할 수 있습니다. 바인딩은 동적이므로, 변수 값이 변경되면 스타일도 업데이트됩니다.

<script setup lang="ts">
const color = ref('red')
</script>

<template>
  <div class="text">
    hello
  </div>
</template>

<style>
.text {
  color: v-bind(color);
}
</style>

Scoped Styles

scoped 속성을 사용하면 컴포넌트를 독립적으로 스타일링할 수 있습니다. 이 속성으로 선언된 스타일은 해당 컴포넌트에만 적용됩니다.

<template>
  <div class="example">
    hi
  </div>
</template>

<style scoped>
.example {
  color: red;
}
</style>

CSS Modules

module 속성을 사용해 CSS Modules를 사용할 수 있습니다. 주입된 $style 변수를 통해 접근합니다.

<template>
  <p :class="$style.red">
    This should be red
  </p>
</template>

<style module>
.red {
  color: red;
}
</style>

Preprocessors Support

SFC style 블록은 전처리기 문법을 지원합니다. Vite는 별도 설정 없이 .scss, .sass, .less, .styl 및 .stylus 파일에 대한 기본 지원을 제공합니다. 먼저 설치만 하면, lang 속성을 사용해 SFC에서 바로 사용할 수 있습니다.

<style lang="scss">
  /* 여기에서 scss를 작성하세요 */
</style>

Vite CSS 문서@vitejs/plugin-vue 문서를 참고할 수 있습니다. webpack 사용자는 vue loader 문서를 참고하세요.

Using PostCSS

Nuxt에는 postcss가 기본 내장되어 있습니다. nuxt.config 파일에서 설정할 수 있습니다.

nuxt.config.ts
export default defineNuxtConfig({
  postcss: {
    plugins: {
      'postcss-nested': {},
      'postcss-custom-media': {},
    },
  },
})

SFC에서 올바른 문법 하이라이팅을 위해 postcss lang 속성을 사용할 수 있습니다.

<style lang="postcss">
  /* 여기에서 postcss를 작성하세요 */
</style>

기본적으로 Nuxt에는 다음 플러그인이 이미 사전 구성되어 있습니다:

Leveraging Layouts For Multiple Styles

애플리케이션의 서로 다른 부분을 완전히 다르게 스타일링해야 한다면, 레이아웃을 사용할 수 있습니다. 서로 다른 레이아웃에 서로 다른 스타일을 사용하세요.

<template>
  <div class="default-layout">
    <h1>Default Layout</h1>
    <slot />
  </div>
</template>

<style>
.default-layout {
  color: red;
}
</style>
Read more in Docs > 4 X > Directory Structure > App > Layouts.

Third Party Libraries And Modules

Nuxt는 스타일링에 대해 의견을 강하게 가지지 않으며, 다양한 옵션을 제공합니다. UnoCSSTailwind CSS 같은 인기 있는 라이브러리를 포함해 원하는 어떤 스타일링 도구든 사용할 수 있습니다.

커뮤니티와 Nuxt 팀은 통합을 더 쉽게 하기 위해 많은 Nuxt 모듈을 개발했습니다. 웹사이트의 modules 섹션에서 이를 찾아볼 수 있습니다. 시작하는 데 도움이 될 몇 가지 모듈은 다음과 같습니다:

  • UnoCSS: 즉시 온디맨드 원자적 CSS 엔진
  • Tailwind CSS: 유틸리티 우선 CSS 프레임워크
  • Fontaine: 폰트 메트릭 폴백
  • Pinceau: 적응형 스타일링 프레임워크
  • Nuxt UI: 현대 웹 앱을 위한 UI 라이브러리
  • Panda CSS: 빌드 타임에 원자적 CSS를 생성하는 CSS-in-JS 엔진

Nuxt 모듈은 기본적으로 좋은 개발자 경험을 제공하지만, 선호하는 도구에 모듈이 없다고 해서 Nuxt에서 사용할 수 없다는 뜻은 아닙니다! 프로젝트에 맞게 직접 설정할 수 있습니다. 도구에 따라 Nuxt 플러그인을 사용해야 하거나 직접 모듈을 만들어야 할 수도 있습니다. 만들었다면 커뮤니티와 공유하세요!

Easily Load Webfonts

Nuxt Google Fonts 모듈을 사용해 Google Fonts를 로드할 수 있습니다.

UnoCSS를 사용하는 경우, Google Fonts를 포함해 일반적인 제공자에서 폰트를 편리하게 로드할 수 있는 web fonts presets이 함께 제공된다는 점에 유의하세요.

Advanced

Transitions

Nuxt에는 Vue와 동일한 <Transition> 요소가 포함되어 있으며, 실험적인 View Transitions API도 지원합니다.

Read more in Docs > 4 X > Getting Started > Transitions.

Font Advanced Optimization

CLS를 줄이기 위해 Fontaine을 사용하는 것을 권장합니다. 더 고급 기능이 필요하다면, 빌드 프로세스나 Nuxt 런타임을 확장하는 Nuxt 모듈을 만드는 것을 고려하세요.

애플리케이션 스타일링을 더 쉽고 효율적으로 만들기 위해 웹 생태계 전반에서 제공되는 다양한 도구와 기법을 적극 활용하는 것을 항상 기억하세요. 네이티브 CSS, 전처리기, postcss, UI 라이브러리 또는 모듈을 사용하든, Nuxt는 이를 모두 지원합니다. 즐거운 스타일링 되세요!

LCP Advanced Optimizations

전역 CSS 파일 다운로드 속도를 높이기 위해 다음을 수행할 수 있습니다:

  • 파일을 사용자와 물리적으로 더 가까운 위치에 두기 위해 CDN 사용
  • 자산을 압축(이상적으로는 Brotli 사용)
  • 전송에 HTTP2/HTTP3 사용
  • 자산을 동일한 도메인에 호스팅(다른 서브도메인을 사용하지 않기)

Cloudflare, Netlify 또는 Vercel과 같은 최신 플랫폼을 사용 중이라면, 이러한 작업 대부분은 자동으로 처리됩니다. LCP 최적화 가이드는 web.dev에서 확인할 수 있습니다.

모든 CSS가 Nuxt에 의해 인라인 처리되는 경우, (실험적으로) 렌더링된 HTML에서 외부 CSS 파일 참조를 완전히 중단할 수 있습니다. 이는 모듈 또는 Nuxt 설정 파일에 둘 수 있는 훅을 사용해 달성할 수 있습니다.

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'build:manifest': (manifest) => {
      // app 엔트리와 css 목록을 찾습니다
      const css = Object.values(manifest).find(options => options.isEntry)?.css
      if (css) {
        // 배열의 끝에서 시작해 처음까지 이동합니다
        for (let i = css.length - 1; i >= 0; i--) {
          // 'entry'로 시작하면 목록에서 제거합니다
          if (css[i].startsWith('entry')) {
            css.splice(i, 1)
          }
        }
      }
    },
  },
})