Nuxt Nation カンファレンス開催!11月12日~13日、ご参加ください。

スタイリング

Nuxtアプリケーションのスタイリング方法を学びましょう。

Nuxtはスタイリングに関して非常に柔軟性があります。独自のスタイルを作成するか、ローカルおよび外部スタイルシートを参照します。CSSプリプロセッサ、CSSフレームワーク、UIライブラリ、Nuxtモジュールを使用してアプリケーションをスタイリングできます。

ローカルスタイルシート

ローカルスタイルシートを作成する場合は、assets/ ディレクトリに配置するのが自然です。

コンポーネント内でのインポート

ページ、レイアウト、コンポーネントにスタイルシートを直接インポートできます。JavaScriptのインポートまたはCSSの@import ステートメントを使用できます。

pages/index.vue
<script>
// Use a static import for server-side compatibility
import '~/assets/css/first.css'

// Caution: Dynamic imports are not server-side compatible
import('~/assets/css/first.css')
</script>

<style>
@import url("~/assets/css/second.css");
</style>
スタイルシートは、NuxtによってレンダリングされたHTMLにインラインで挿入されます。

CSSプロパティ

Nuxt設定のcssプロパティを使用することもできます。スタイルシートを配置する最適な場所はassets/ ディレクトリです。その後、そのパスを参照すると、Nuxtはそれをアプリケーションのすべてのページに含めます。

nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/css/main.css']
})
スタイルシートは、NuxtによってレンダリングされたHTMLにインラインで挿入され、グローバルに注入され、すべてのページに存在します。

フォントの使用方法

ローカルフォントファイルを~/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>

NPMを介して配布されるスタイルシート

npmを介して配布されるスタイルシートを参照することもできます。人気のanimate.cssライブラリを例として使用してみましょう。

npm install animate.css

次に、ページ、レイアウト、コンポーネントで直接参照できます。

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

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

パッケージは、Nuxt設定のcssプロパティで文字列として参照することもできます。

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

外部スタイルシート

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' }]
} } })

スタイルシートの動的な追加

useHeadコンポーザブルを使用して、コード内でheadの値を動的に設定できます。

ドキュメント > API > コンポーザブル > Use Headで詳細をご覧ください。
useHead
({
link
: [{
rel
: 'stylesheet',
href
: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
})

Nuxtは内部的にunheadを使用しており、その完全なドキュメントはこちらを参照できます。

Nitroプラグインを使用したレンダリング済みheadの変更

より高度な制御が必要な場合は、フックを使用してレンダリングされた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ページは、レンダリングに時間がかかります。web.devで詳細を確認できます。

プリプロセッサの使用

SCSS、Sass、Less、Stylusなどのプリプロセッサを使用するには、最初にインストールします。

npm install -D sass

スタイルシートを作成する最適な場所はassetsディレクトリです。次に、プリプロセッサの構文を使用して、app.vue(またはレイアウトファイル)でソースファイルをインポートします。

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のプリプロセッサオプションを使用できます。

assetsディレクトリにいくつかのpartialを作成します。

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

次に、nuxt.config

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

NuxtはデフォルトでViteを使用します。Webpackを使用する場合は、各プリプロセッサローダーのドキュメントを参照してください。

シングルファイルコンポーネント(SFC)スタイリング

VueとSFCの優れた点の1つは、スタイリングを自然に処理する点です。コンポーネントファイルのstyleブロックにCSSまたはプリプロセッサコードを直接記述できるため、CSS-in-JSのようなものを使用する必要がなく、優れた開発者エクスペリエンスを得ることができます。ただし、CSS-in-JSを使用する場合は、pinceauなどのそれをサポートするサードパーティライブラリとモジュールを見つけることができます。

SFCでのコンポーネントのスタイリングに関する包括的なリファレンスについては、Vueドキュメントを参照してください。

クラスとスタイルのバインディング

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>
  <div :class="classObject"></div>
</template>

詳細については、Vueドキュメントを参照してください。

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属性を使用すると、コンポーネントを分離してスタイリングできます。この属性で宣言されたスタイルはこのコンポーネントにのみ適用されます。

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

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

CSSモジュール

CSSモジュールをmodule属性で使用できます。注入された$style変数でアクセスします。

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

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

プリプロセッサのサポート

SFCスタイルブロックはプリプロセッサの構文をサポートしています。Viteには、.scss、.sass、.less、.styl、.stylusファイルに対する設定不要の組み込みサポートがあります。最初にインストールするだけで、lang属性を使用してSFCで直接使用できます。

<style lang="scss">
  /* Write scss here */
</style>

Vite CSSドキュメント@vitejs/plugin-vueドキュメントを参照してください。Webpackユーザーはvue loaderドキュメントを参照してください。

PostCSSの使用

NuxtにはPostCSSが組み込まれています。nuxt.configファイルで設定できます。

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

SFCでの適切な構文の強調表示には、postcss lang属性を使用できます。

<style lang="postcss">
  /* Write postcss here */
</style>

デフォルトでは、Nuxtには次のプラグインが既に事前に設定されています。

  • postcss-import@importルールを改善します。
  • postcss-urlurl()ステートメントを変換します。
  • autoprefixer:ベンダープレフィックスを自動的に追加します
  • cssnano:ミニファイとパージ

複数のスタイルのためのレイアウトの活用

アプリケーションの異なる部分を完全に異なるスタイルで装飾する必要がある場合は、レイアウトを使用できます。異なるレイアウトに異なるスタイルを使用してください。

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

<style>
.default-layout {
  color: red;
}
</style>
詳細はドキュメント > ガイド > ディレクトリ構造 > レイアウトをご覧ください。

サードパーティライブラリとモジュール

Nuxtはスタイリングに関して意見を押し付けず、幅広いオプションを提供します。UnoCSSTailwind CSSのような一般的なライブラリなど、任意のスタイリングツールを使用できます。

コミュニティとNuxtチームは、統合を容易にするための多くのNuxtモジュールを開発しました。それらはウェブサイトのモジュールセクションで見つけることができます。開始に役立つモジュールをいくつかご紹介します。

  • UnoCSS:オンデマンドの即時原子CSSエンジン
  • Tailwind CSS:ユーティリティファーストCSSフレームワーク
  • Fontaine:フォントメトリックスフォールバック
  • Pinceau:適応可能なスタイリングフレームワーク
  • Nuxt UI:モダンウェブアプリのためのUIライブラリ
  • Panda CSS:ビルド時にアトミックCSSを生成するCSS-in-JSエンジン

Nuxtモジュールはすぐに優れた開発者エクスペリエンスを提供しますが、お気に入りのツールにモジュールがないからといって、Nuxtで使用できないわけではありません!独自のプロジェクト用に自分で設定できます。ツールによっては、Nuxtプラグインと/または独自のモジュールを作成する必要がある場合があります。そうした場合はコミュニティで共有してください!

webfontの簡単な読み込み

Nuxt Google Fontsモジュールを使用してGoogleフォントを読み込むことができます。

UnoCSSを使用している場合は、Googleフォントなど、一般的なプロバイダーからフォントを簡単に読み込むためのwebfontプリセットが付属していることに注意してください。

高度な機能

トランジション

NuxtはVueと同じ<Transition>要素を使用し、実験的なビュートランジションAPIもサポートしています。

詳細はドキュメント > はじめに > トランジションをご覧ください。

高度なフォント最適化

Fontaineを使用してCLSを削減することをお勧めします。より高度な機能が必要な場合は、Nuxtモジュールを作成してビルドプロセスまたはNuxtランタイムを拡張することを検討してください。

アプリケーションのスタイリングをより簡単かつ効率的にするために、Webエコシステム全体で利用可能なさまざまなツールとテクニックを活用することを常に忘れないでください。ネイティブCSS、プリプロセッサ、postcss、UIライブラリ、モジュールのいずれを使用している場合でも、Nuxtはあなたをサポートします。スタイリングを楽しんでください!

LCP高度な最適化

グローバルCSSファイルのダウンロード速度を上げるために、次のことができます。

  • CDNを使用することで、ファイルがユーザーに物理的に近くなります。
  • アセットを圧縮します。理想的にはBrotliを使用します。
  • 配信にHTTP2/HTTP3を使用します。
  • アセットを同じドメインにホストします(異なるサブドメインを使用しないでください)。

Cloudflare、Netlify、Vercelなどの最新のプラットフォームを使用している場合、これらのほとんどは自動的に実行されます。web.devでLCP最適化ガイドを見つけることができます。

すべてのCSSがNuxtによってインライン化されている場合、(実験的に)レンダリングされたHTMLで外部CSSファイルへの参照を完全に停止できます。これは、モジュールまたはNuxt設定ファイルに配置できるフックを使用して実現できます。

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'build:manifest': (manifest) => {
      // find the app entry, css list
      const css = Object.values(manifest).find(options => options.isEntry)?.css
      if (css) {
        // start from the end of the array and go to the beginning
        for (let i = css.length - 1; i >= 0; i--) {
          // if it starts with 'entry', remove it from the list
          if (css[i].startsWith('entry')) css.splice(i, 1)
        }
      }
    },
  },
})