Стили
Nuxt даёт большую свободу в стилизации: свои стили, локальные и внешние таблицы, препроцессоры, CSS-фреймворки, UI-библиотеки и модули Nuxt.
Локальные стили
Для локальных стилей естественное место — директория app/assets/.
Импорт в компонентах
Стили можно импортировать в страницах, макетах и компонентах — через JavaScript-импорт или CSS-@import.
<script>
// Статический импорт для совместимости с SSR
import '~/assets/css/first.css'
// Внимание: динамический импорт не совместим с SSR
import('~/assets/css/first.css')
</script>
<style>
@import url("~/assets/css/second.css");
</style>
Свойство css в конфиге
Стили можно подключить через свойство css в конфигурации Nuxt. Удобное место для файлов — директория app/assets/; укажите путь, и Nuxt подключит его ко всем страницам.
export default defineNuxtConfig({
css: ['~/assets/css/main.css'],
})
Работа со шрифтами
Разместите файлы шрифтов в public/, например в public/fonts. В стилях подключайте их через url().
@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
yarn add animate.css
pnpm install animate.css
bun install animate.css
deno install npm:animate.css
Подключение в страницах, макетах и компонентах:
<script>
import 'animate.css'
</script>
<style>
@import url("animate.css");
</style>
Пакет можно указать строкой в свойстве css в конфиге Nuxt:
export default defineNuxtConfig({
css: ['animate.css'],
})
Внешние стили
Внешние таблицы стилей подключаются через элемент link в head — например, через свойство app.head в конфиге Nuxt. Так же можно подключать и локальные стили.
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 из кода.
useHead({
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }],
})
Под капотом Nuxt использует unhead — см. документацию.
Изменение head через Nitro-плагин
Для более тонкого контроля можно перехватить отрендеренный HTML хуком и изменить head в коде.
Создайте плагин в ~~/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.
Препроцессоры
Для использования SCSS, Sass, Less или Stylus сначала установите нужный пакет:
npm install -D sass
npm install -D less
npm install -D stylus
Писать стили удобно в директории app/assets. Импортируйте их в app.vue (или в макетах) синтаксисом выбранного препроцессора:
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>
Либо укажите файл в свойстве css конфига Nuxt:
export default defineNuxtConfig({
css: ['~/assets/scss/main.scss'],
})
Чтобы внедрить код в обрабатываемые файлы (например, Sass-партиал с переменными цветов), используйте опции препроцессоров Vite.
Создайте партиалы в app/assets:
$primary: #49240F;
$secondary: #E4A79D;
$primary: #49240F
$secondary: #E4A79D
В nuxt.config:
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "~/assets/_colors.scss" as *;',
},
},
},
},
})
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
sass: {
additionalData: '@use "~/assets/_colors.sass" as *\n',
},
},
},
},
})
По умолчанию Nuxt использует Vite. При использовании webpack см. документацию лоадеров для каждого препроцессора.
Preprocessor Workers (экспериментально)
В Vite есть экспериментальная опция для ускорения препроцессоров.
Включение в nuxt.config:
export default defineNuxtConfig({
vite: {
css: {
preprocessorMaxWorkers: true, // число CPU минус 1
},
},
})
Стили в SFC (Single File Components)
В Vue и SFC стили задаются прямо в блоке <style> компонента — без обязательного CSS-in-JS. При желании можно использовать сторонние библиотеки вроде pinceau.
Подробнее: документация Vue по стилям в SFC.
Привязки class и style
Используйте возможности Vue SFC для привязки атрибутов class и style:
<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>
<script setup lang="ts">
const isActive = ref(true)
const error = ref(null)
const classObject = computed(() => ({
'active': isActive.value && !error.value,
'text-danger': error.value && error.value.type === 'fatal',
}))
</script>
<template>
<div :class="classObject" />
</template>
<script setup lang="ts">
const isActive = ref(true)
const errorClass = ref('text-danger')
</script>
<template>
<div :class="[{ active: isActive }, errorClass]" />
</template>
<script setup lang="ts">
const activeColor = ref('red')
const fontSize = ref(30)
const styleObject = reactive({ color: 'red', fontSize: '13px' })
</script>
<template>
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }" />
<div :style="[baseStyles, overridingStyles]" />
<div :style="styleObject" />
</template>
Подробнее: Vue — классы и стили.
Динамические стили с v-bind
В блоках <style> можно использовать переменные и выражения JavaScript через v-bind. Значения реактивны: при изменении переменной обновится и стиль.
<script setup lang="ts">
const color = ref('red')
</script>
<template>
<div class="text">
hello
</div>
</template>
<style>
.text {
color: v-bind(color);
}
</style>
Scoped-стили
Атрибут scoped ограничивает стили текущим компонентом.
<template>
<div class="example">
hi
</div>
</template>
<style scoped>
.example {
color: red;
}
</style>
CSS Modules
CSS Modules подключаются атрибутом module. Доступ через переменную $style:
<template>
<p :class="$style.red">
This should be red
</p>
</template>
<style module>
.red {
color: red;
}
</style>
Препроцессоры в SFC
В блоках <style> поддерживается синтаксис препроцессоров. Vite из коробки поддерживает .scss, .sass, .less, .styl и .stylus — достаточно установить пакет и указать lang:
<style lang="scss">
/* Пишите scss здесь */
</style>
<style lang="sass">
/* Пишите sass здесь */
</style>
<style lang="less">
/* Пишите less здесь */
</style>
<style lang="stylus">
/* Пишите stylus здесь */
</style>
См. Vite CSS и @vitejs/plugin-vue. Для webpack — vue-loader.
PostCSS
В Nuxt PostCSS встроен. Настройка в nuxt.config:
export default defineNuxtConfig({
postcss: {
plugins: {
'postcss-nested': {},
'postcss-custom-media': {},
},
},
})
Для подсветки синтаксиса в SFC можно указать lang="postcss":
<style lang="postcss">
/* Пишите postcss здесь */
</style>
По умолчанию в Nuxt уже подключены:
- postcss-import: улучшает правило
@import - postcss-url: преобразует
url() - autoprefixer: вендорные префиксы
- cssnano: минификация и очистка
Разные стили для макетов
Если разным частям приложения нужны разные стили, используйте макеты и задавайте стили для каждого макета.
<template>
<div class="default-layout">
<h1>Default Layout</h1>
<slot />
</div>
</template>
<style>
.default-layout {
color: red;
}
</style>
Сторонние библиотеки и модули
Nuxt не навязывает подход к стилям: можно использовать UnoCSS, Tailwind CSS и другие инструменты.
Сообщество и команда Nuxt разработали множество модулей для удобной интеграции. Ищите их в разделе модулей сайта. Несколько примеров:
- UnoCSS: атомарный CSS по требованию
- Tailwind CSS: utility-first CSS фреймворк
- Fontaine: метрики шрифтов и fallback
- Pinceau: адаптивная система стилей
- Nuxt UI: UI-библиотека для современных приложений
- Panda CSS: CSS-in-JS с генерацией атомарного CSS при сборке
Модули дают удобный опыт из коробки, но если у вашего инструмента нет модуля — его всё равно можно подключить вручную (плагин и/или собственный модуль). Имеет смысл поделиться решением в сообществе.
Подключение веб-шрифтов
Для Google Fonts можно использовать модуль Nuxt Google Fonts.
При использовании UnoCSS доступен пресет web fonts для подключения шрифтов от популярных провайдеров, включая Google Fonts.
Продвинутое
Переходы
В Nuxt доступен тот же элемент <Transition>, что и во Vue, плюс экспериментальная View Transitions API.
Оптимизация шрифтов
Рекомендуется Fontaine для снижения CLS. Для более сложных сценариев можно написать модуль Nuxt, расширяющий сборку или рантайм.
Оптимизация LCP
Чтобы ускорить загрузку глобального CSS:
- Используйте CDN для приближения файлов к пользователям
- Сжимайте ресурсы (предпочтительно Brotli)
- Используйте HTTP/2 или HTTP/3
- Размещайте ресурсы на том же домене (без отдельного поддомена)
На современных платформах (Cloudflare, Netlify, Vercel) многое из этого делается автоматически. Подробнее: web.dev — оптимизация LCP.
Если весь CSS инлайнится Nuxt, можно (экспериментально) убрать ссылки на внешние CSS из HTML. Для этого подойдёт хук в модуле или в конфиге Nuxt:
export default defineNuxtConfig({
hooks: {
'build:manifest': (manifest) => {
const css = Object.values(manifest).find(options => options.isEntry)?.css
if (css) {
for (let i = css.length - 1; i >= 0; i--) {
if (css[i].startsWith('entry')) {
css.splice(i, 1)
}
}
}
},
},
})