Files
gh-lttr-claude-marketplace-…/skills/nuxt/references/nuxt-image.md
2025-11-30 08:38:06 +08:00

596 lines
11 KiB
Markdown

# Nuxt Image Reference
**Last Updated:** 2025-11
**Check:** `@nuxt/image` in package.json
Nuxt Image is an image optimization module that provides automatic image optimization, lazy loading, responsive images, and support for multiple image providers.
## Installation & Setup
```bash
pnpm add @nuxt/image
```
**nuxt.config.ts:**
```typescript
export default defineNuxtConfig({
modules: ["@nuxt/image"],
image: {
// Optional configuration
quality: 80,
formats: ["webp", "avif"],
// Image providers
providers: {
cloudinary: {
baseURL: "https://res.cloudinary.com/{your-cloud-name}/image/upload/",
},
},
},
})
```
## Core Components
### NuxtImg
Basic optimized image component:
```vue
<template>
<NuxtImg src="/images/hero.jpg" alt="Hero image" width="800" height="600" />
</template>
```
**Common Props:**
- `src` - Image source (path or URL)
- `alt` - Alt text for accessibility
- `width` / `height` - Dimensions
- `loading` - `"lazy"` (default) or `"eager"`
- `fit` - `"cover"`, `"contain"`, `"fill"`, `"inside"`, `"outside"`
- `format` - `"webp"`, `"avif"`, `"jpg"`, `"png"`
- `quality` - Image quality (0-100)
- `provider` - Image provider to use
### NuxtPicture
Responsive image with multiple formats:
```vue
<template>
<NuxtPicture
src="/images/hero.jpg"
:img-attrs="{ alt: 'Hero image', class: 'rounded-lg' }"
sizes="sm:100vw md:50vw lg:400px"
/>
</template>
```
**Benefits:**
- Automatically generates multiple formats (WebP, AVIF)
- Creates responsive srcset for different screen sizes
- Better browser compatibility with fallbacks
## Common Patterns
### Responsive Images
```vue
<template>
<NuxtPicture
src="/images/product.jpg"
:img-attrs="{ alt: 'Product image' }"
sizes="xs:100vw sm:100vw md:50vw lg:33vw"
:modifiers="{ fit: 'cover' }"
/>
</template>
```
### Image with Loading States
```vue
<template>
<div class="relative">
<NuxtImg
src="/images/large.jpg"
alt="Large image"
loading="lazy"
placeholder
@load="imageLoaded = true"
/>
<div
v-if="!imageLoaded"
class="absolute inset-0 bg-gray-200 animate-pulse"
/>
</div>
</template>
<script setup lang="ts">
const imageLoaded = ref(false)
</script>
```
### Background Images
```vue
<template>
<div
:style="{
backgroundImage: `url(${$img('/images/hero.jpg', { width: 1920, height: 1080 })})`,
backgroundSize: 'cover',
}"
class="h-96"
>
Content
</div>
</template>
```
### Image with Different Formats
```vue
<template>
<NuxtPicture
src="/images/photo.jpg"
format="webp"
:img-attrs="{ alt: 'Photo', class: 'w-full' }"
/>
</template>
```
### Fit Options
```vue
<template>
<div class="grid grid-cols-3 gap-4">
<!-- Cover: Crop to fill dimensions -->
<NuxtImg
src="/images/photo.jpg"
fit="cover"
width="300"
height="300"
alt="Cover"
/>
<!-- Contain: Fit within dimensions -->
<NuxtImg
src="/images/photo.jpg"
fit="contain"
width="300"
height="300"
alt="Contain"
/>
<!-- Fill: Stretch to fill -->
<NuxtImg
src="/images/photo.jpg"
fit="fill"
width="300"
height="300"
alt="Fill"
/>
</div>
</template>
```
## Image Providers
### Local Provider (Default)
For images in `public/` directory:
```vue
<template>
<NuxtImg src="/images/local.jpg" />
</template>
```
### External URLs
```vue
<template>
<NuxtImg src="https://example.com/image.jpg" provider="cloudinary" />
</template>
```
### Cloudinary
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
image: {
cloudinary: {
baseURL: "https://res.cloudinary.com/{your-cloud-name}/image/upload/",
},
},
})
```
```vue
<template>
<NuxtImg provider="cloudinary" src="sample.jpg" width="600" height="400" />
</template>
```
### Vercel / Netlify
Automatically detected and configured when deployed:
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
image: {
provider: "vercel", // or 'netlify'
},
})
```
### Custom Provider
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
image: {
providers: {
custom: {
provider: "~/providers/custom-provider.ts",
options: {
baseURL: "https://cdn.example.com",
},
},
},
},
})
```
```typescript
// providers/custom-provider.ts
import { joinURL } from "ufo"
import type { ProviderGetImage } from "@nuxt/image"
export const getImage: ProviderGetImage = (src, { modifiers, baseURL }) => {
const { width, height, format, quality } = modifiers
const url = joinURL(baseURL, src)
return {
url: `${url}?w=${width}&h=${height}&fm=${format}&q=${quality}`,
}
}
```
## Composables
### $img Helper
Generate image URLs programmatically:
```vue
<script setup lang="ts">
const { $img } = useNuxtApp()
// Generate optimized URL
const imageUrl = $img("/images/photo.jpg", {
width: 800,
height: 600,
format: "webp",
quality: 80,
})
// Use in v-bind or computed
const backgroundImage = computed(() =>
$img("/images/hero.jpg", { width: 1920 }),
)
</script>
<template>
<div :style="{ backgroundImage: `url(${backgroundImage})` }">Content</div>
</template>
```
## Performance Optimization
### Lazy Loading (Default)
Images are lazy-loaded by default:
```vue
<template>
<!-- Lazy loaded (default) -->
<NuxtImg src="/images/photo.jpg" loading="lazy" />
<!-- Eager load for above-the-fold images -->
<NuxtImg src="/images/hero.jpg" loading="eager" />
</template>
```
### Preload Critical Images
```vue
<script setup lang="ts">
useHead({
link: [
{
rel: "preload",
as: "image",
href: "/images/hero.jpg",
type: "image/jpeg",
},
],
})
</script>
<template>
<NuxtImg src="/images/hero.jpg" loading="eager" />
</template>
```
### Placeholder / Blur
```vue
<template>
<NuxtImg
src="/images/large.jpg"
placeholder
alt="Image with blur placeholder"
/>
</template>
```
### Image Sizes
Specify responsive sizes for optimal loading:
```vue
<template>
<NuxtPicture
src="/images/responsive.jpg"
sizes="xs:100vw sm:100vw md:50vw lg:400px xl:400px"
:img-attrs="{ alt: 'Responsive image' }"
/>
</template>
```
## Advanced Usage
### Modifiers Object
Pass multiple modifiers:
```vue
<script setup lang="ts">
const imageModifiers = {
width: 800,
height: 600,
fit: "cover",
format: "webp",
quality: 85,
}
</script>
<template>
<NuxtImg src="/images/photo.jpg" :modifiers="imageModifiers" alt="Photo" />
</template>
```
### Dynamic Sources
```vue
<script setup lang="ts">
const images = ref([
{ id: 1, src: "/images/photo1.jpg", alt: "Photo 1" },
{ id: 2, src: "/images/photo2.jpg", alt: "Photo 2" },
{ id: 3, src: "/images/photo3.jpg", alt: "Photo 3" },
])
</script>
<template>
<div class="grid grid-cols-3 gap-4">
<NuxtImg
v-for="image of images"
:key="image.id"
:src="image.src"
:alt="image.alt"
width="400"
height="300"
fit="cover"
/>
</div>
</template>
```
### Image Gallery
```vue
<template>
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<NuxtPicture
v-for="(image, index) of gallery"
:key="index"
:src="image.src"
:img-attrs="{
alt: image.alt,
class: 'w-full h-64 object-cover rounded-lg cursor-pointer',
}"
sizes="sm:50vw md:33vw lg:25vw"
@click="openLightbox(image)"
/>
</div>
</template>
<script setup lang="ts">
const gallery = ref([
{ src: "/images/gallery1.jpg", alt: "Gallery 1" },
{ src: "/images/gallery2.jpg", alt: "Gallery 2" },
{ src: "/images/gallery3.jpg", alt: "Gallery 3" },
])
function openLightbox(image: any) {
// Handle lightbox
}
</script>
```
### Art Direction
Different images for different screen sizes:
```vue
<template>
<picture>
<source
media="(min-width: 1024px)"
:srcset="$img('/images/hero-desktop.jpg', { width: 1920 })"
/>
<source
media="(min-width: 768px)"
:srcset="$img('/images/hero-tablet.jpg', { width: 1024 })"
/>
<NuxtImg src="/images/hero-mobile.jpg" alt="Hero" width="768" />
</picture>
</template>
```
## Configuration Reference
### Global Configuration
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
image: {
// Default quality
quality: 80,
// Default formats
formats: ["webp", "avif", "jpg"],
// Image sizes for responsive images
screens: {
xs: 320,
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
xxl: 1536,
"2xl": 1536,
},
// Provider configuration
provider: "cloudinary",
providers: {
cloudinary: {
baseURL: "https://res.cloudinary.com/{cloud-name}/image/upload/",
},
},
// IPX options (local provider)
ipx: {
maxAge: 60 * 60 * 24 * 365, // 1 year cache
},
// Presets
presets: {
avatar: {
modifiers: {
format: "webp",
width: 100,
height: 100,
fit: "cover",
},
},
thumbnail: {
modifiers: {
format: "webp",
width: 300,
height: 200,
fit: "cover",
},
},
},
},
})
```
### Using Presets
```vue
<template>
<NuxtImg src="/images/user.jpg" preset="avatar" alt="User avatar" />
<NuxtImg
src="/images/product.jpg"
preset="thumbnail"
alt="Product thumbnail"
/>
</template>
```
## Best Practices
1. **Always include alt text** - Essential for accessibility
2. **Use NuxtPicture for hero images** - Better format support and responsiveness
3. **Specify dimensions** - Prevents layout shift
4. **Lazy load by default** - Except above-the-fold images
5. **Use appropriate fit** - `cover` for thumbnails, `contain` for products
6. **Optimize quality** - 80-85 is usually sufficient
7. **Leverage providers** - Use CDN providers for external images
8. **Use presets** - Define common image styles once
9. **Test on slow networks** - Verify lazy loading and placeholders work
10. **Prefer WebP/AVIF** - Modern formats for better compression
## Troubleshooting
### Images Not Optimizing
Check:
1. `@nuxt/image` is in `nuxt.config.ts` modules
2. Images are in `public/` directory for local provider
3. Provider is correctly configured
4. Development server was restarted after config changes
### Images Not Loading
1. Verify src path is correct
2. Check provider baseURL configuration
3. Ensure CORS is configured for external images
4. Check network tab for 404/403 errors
### Poor Performance
1. Enable lazy loading (default)
2. Use appropriate image sizes
3. Implement placeholders
4. Use WebP/AVIF formats
5. Configure CDN caching
### Layout Shift
Always specify width and height:
```vue
<template>
<!-- Bad: No dimensions -->
<NuxtImg src="/images/photo.jpg" />
<!-- Good: Dimensions specified -->
<NuxtImg src="/images/photo.jpg" width="800" height="600" />
</template>
```
## Official Resources
- **Documentation:** https://image.nuxt.com
- **Providers:** https://image.nuxt.com/providers
- **API Reference:** https://image.nuxt.com/api
- **GitHub:** https://github.com/nuxt/image
---
**Note:** Always verify provider-specific features with official documentation. Image optimization strategies may vary by provider.