Image Component and Image Optimization in Next.js 16
Next.js course · Module 3: Styling and Visual Optimization
In Metropolis Quantum, visual communication plays a key role. Futuristic holograms, digital billboards, and immersive displays are ubiquitous in the city's landscape. However, just like in real cities, engineers must ensure the efficiency of display systems so that images load quickly and do not consume too many resources.
In the world of web applications, images are one of the biggest obstacles to achieving optimal page performance. Large, uncompressed photos can significantly slow down page loading and worsen the user experience. Fortunately, Next.js 16 offers a powerful tool for image optimization - the Image component.
Why is Image Optimization Important?
Before we dive into the details of the Image component, it is worth understanding why image optimization is so important:
- Page performance - images often make up over 50% of a web page's weight
- Core Web Vitals - metrics like LCP (Largest Contentful Paint) are directly related to image loading time
- SEO - faster pages are better positioned in search results
- User experience - nobody likes waiting for content to load
- Data consumption - for mobile users, large images can quickly use up data limits
- Accessibility - properly optimized images are more accessible for people with slower internet connections
Traditional Approach to Images in HTML
In traditional HTML, images are usually added using the <img> tag:
1<img src="/images/quantum-city.jpg" alt="Panorama Metropolis Quantum" />This simple approach, however, has several drawbacks:
- No automatic optimization - images are served in their original format and size
- No responsiveness - images do not automatically adapt to different screen sizes
- No lazy loading - all images are loaded immediately, regardless of their visibility
- No prioritization - it is not easy to determine which images are critical for displaying the page
Komponent Image w Next.js 16
The Image component from Next.js solves these problems and offers a number of additional benefits:
- Automatic optimization - conversion to modern formats (WebP, AVIF)
- Size adjustment - serving images in the appropriate size for the device
- Lazy loading - images are loaded only when they approach the viewport
- Avoiding layout shifts - reserving space for images before they load
- Support for multiple sources - easy specification of different images for different resolutions
- Core Web Vitals optimization - improvement of metrics such as LCP and CLS
Basic Usage of the Image Component
To start using the Image component, you first need to import it from next/image:
1import Image from 'next/image';
2
3export default function QuantumCityView() {
4 return (
5 <div className="city-view">
6 <h1>Panorama Metropolis Quantum</h1>
7 <Image
8 src="/images/quantum-city.jpg"
9 alt="Panorama Metropolis Quantum z lotu ptaka"
10 width={1200}
11 height={600}
12 />
13 </div>
14 );
15}In the above example, the Image component requires several attributes:
src- path to the imagealt- alternative text for accessibilitywidthandheight- width and height of the image in pixels
Static Image Imports
Next.js also allows static importing of images, which provides additional benefits such as automatic dimension detection:
1import Image from 'next/image';
2import quantumCityImage from '@/public/images/quantum-city.jpg';
3
4export default function QuantumCityView() {
5 return (
6 <div className="city-view">
7 <h1>Panorama Metropolis Quantum</h1>
8 <Image
9 src={quantumCityImage}
10 alt="Panorama Metropolis Quantum z lotu ptaka"
11 // width and height are automatically determined from image metadata
12 />
13 </div>
14 );
15}Responsywne obrazy
The Image component can be easily adapted to different screen sizes using CSS styles:
1import Image from 'next/image';
2import quantumCityImage from '@/public/images/quantum-city.jpg';
3
4export default function QuantumCityView() {
5 return (
6 <div className="city-view">
7 <h1>Panorama Metropolis Quantum</h1>
8 <div className="relative w-full h-[50vh]">
9 <Image
10 src={quantumCityImage}
11 alt="Panorama Metropolis Quantum z lotu ptaka"
12 fill
13 style={{ objectFit: 'cover' }}
14 />
15 </div>
16 </div>
17 );
18}In this example:
- The
fillattribute causes the image to fill the parent container - The
objectFit: 'cover'style ensures the image maintains proportions, cropping it if necessary - The parent container must have
relativeorabsolutepositioning
Image Prioritization
For images that are visible "above the fold" (i.e., in the upper part of the page without scrolling), it is worth using the preload attribute. In Next.js 16 it replaced the deprecated priority attribute, which still works but should no longer be used in new code:
1<Image
2 src="/images/hero-quantum-city.jpg"
3 alt="Panorama Metropolis Quantum"
4 width={1200}
5 height={600}
6 preload
7/>The preload attribute causes:
- Next.js inserts a
<link rel="preload">tag for this image into the<head> - The browser starts downloading the image before it reaches it in the page content
- The image is available as soon as possible, which improves LCP
The Next.js 16 documentation advises using preload only for a single LCP image, such as a hero photo. In other cases, loading="eager" or fetchPriority="high" is enough.
Handling Images from CMS or External Sources
To use images from external sources (e.g., CMS, CDN, API), you need to tell Next.js which servers are allowed in the next.config.js file. Older projects do it with the domains option:
1// next.config.js
2module.exports = {
3 images: {
4 domains: ['cdn.quantum-city.com', 'images.cms-provider.com'],
5 },
6}This option has been deprecated since Next.js 14, so in Next.js 16 use "remotePatterns", which give you more precise control:
1// next.config.js
2module.exports = {
3 images: {
4 remotePatterns: [
5 {
6 protocol: 'https',
7 hostname: 'cdn.quantum-city.com',
8 port: '',
9 pathname: '/images/**',
10 },
11 {
12 protocol: 'https',
13 hostname: '**.cms-provider.com',
14 port: '',
15 pathname: '/assets/**',
16 },
17 ],
18 },
19}Placeholders i efekt rozmazania
Next.js 16 offers several ways to improve the user experience during image loading:
Placeholder z efektem blur
1<Image
2 src="/images/quantum-city.jpg"
3 alt="Panorama Metropolis Quantum"
4 width={1200}
5 height={600}
6 placeholder="blur"
7 blurDataURL="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1200' height='600'%3E%3Crect width='100%25' height='100%25' fill='%23071731'/%3E%3C/svg%3E"
8/>In this example:
placeholder="blur"enables a blur effect during image loadingblurDataURLspecifies the background color used during image loading (encoded as a base64 URL)
Automatic Blur Effect for Static Imports
When you use a static image import, Next.js automatically generates a blurred version:
1import Image from 'next/image';
2import quantumCityImage from '@/public/images/quantum-city.jpg';
3
4export default function QuantumCityView() {
5 return (
6 <Image
7 src={quantumCityImage}
8 alt="Panorama Metropolis Quantum"
9 placeholder="blur"
10 // blurDataURL jest generowany automatycznie
11 />
12 );
13}Image Loading Animations
You can add image loading animations using CSS:
1import Image from 'next/image';
2import styles from './image.module.css';
3
4export default function QuantumCityView() {
5 return (
6 <Image
7 src="/images/quantum-city.jpg"
8 alt="Panorama Metropolis Quantum"
9 width={1200}
10 height={600}
11 className={styles.imageTransition}
12 />
13 );
14}1/* image.module.css */
2.imageTransition {
3 opacity: 0;
4 transition: opacity 0.5s ease-in-out;
5}
6
7.imageTransition:global(.loaded) {
8 opacity: 1;
9}Zaawansowane funkcje komponentu Image
Adaptatywne obrazy i art direction
If you want to display different images for different screen sizes, you can use the srcSet attribute:
1<div className="relative aspect-video w-full">
2 <picture>
3 <source
4 media="(max-width: 640px)"
5 srcSet="/images/quantum-city-mobile.jpg"
6 />
7 <source
8 media="(max-width: 1024px)"
9 srcSet="/images/quantum-city-tablet.jpg"
10 />
11 <source
12 media="(min-width: 1025px)"
13 srcSet="/images/quantum-city-desktop.jpg"
14 />
15 <Image
16 src="/images/quantum-city-desktop.jpg"
17 alt="Panorama Metropolis Quantum"
18 fill
19 style={{ objectFit: 'cover' }}
20 />
21 </picture>
22</div>Handling Images in Different Formats
Although Next.js automatically converts images to WebP, you can also use the <picture> tag to handle different formats:
1<picture>
2 <source srcSet="/images/quantum-city.avif" type="image/avif" />
3 <source srcSet="/images/quantum-city.webp" type="image/webp" />
4 <Image
5 src="/images/quantum-city.jpg"
6 alt="Panorama Metropolis Quantum"
7 width={1200}
8 height={600}
9 />
10</picture>Handling Images with Transparency
For images with transparency (PNG, SVG), it is worth considering disabling WebP conversion:
1<Image
2 src="/images/quantum-logo.png"
3 alt="Logo Metropolis Quantum"
4 width={200}
5 height={200}
6 style={{ objectFit: 'contain' }}
7 unoptimized
8/>The unoptimized attribute disables Next.js optimization for the given image, which can be useful for:
- Images with transparency
- Already optimized images
- Animated GIFs
Configuring Image Optimization in Next.js 16
Next.js offers many configuration options for image optimization in the next.config.js file:
1// next.config.js
2module.exports = {
3 images: {
4 // Deprecated since Next.js 14 - use remotePatterns instead of domains
5 domains: ['cdn.quantum-city.com'],
6
7 // More detailed configuration for external images
8 remotePatterns: [
9 {
10 protocol: 'https',
11 hostname: '**.cms-provider.com',
12 port: '',
13 pathname: '/assets/**',
14 },
15 ],
16
17 // Supported formats
18 formats: ['image/webp', 'image/avif'],
19
20 // Allowed quality values (since Next.js 16 only [75] by default)
21 qualities: [50, 75, 90],
22
23 // Cache configuration (since Next.js 16 the default is 14400 s, i.e. 4 hours)
24 minimumCacheTTL: 60, // in seconds
25
26 // Image size limits
27 deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
28 imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // since Next.js 16, 16 is not in the default list
29
30 // Custom image loader (e.g., Cloudinary, imgix)
31 loader: 'default',
32
33 // Path to image optimization endpoint
34 path: '/_next/image',
35
36 // Disabling automatic optimization for all images
37 unoptimized: false,
38 },
39}Next.js 16 changed several defaults: minimumCacheTTL is now 4 hours (previously 60 seconds), the 16-pixel width is gone from imageSizes, and qualities allows only quality 75 by default. There are also new security options: maximumRedirects (at most 3 redirects by default) and dangerouslyAllowLocalIP, without which Next.js does not optimize images from local addresses.
Using External Provider Loaders
Next.js also supports popular image optimization services:
1// next.config.js
2module.exports = {
3 images: {
4 loader: 'cloudinary',
5 loaderFile: './my/image/loader.js',
6 // Domena Cloudinary
7 domains: ['res.cloudinary.com'],
8 },
9}You can also create your own loader:
1// my/image/loader.js
2export default function myImageLoader({ src, width, quality }) {
3 return `https://cdn.quantum-city.com/images/${src}?w=${width}&q=${quality || 75}`
4}And use it in the Image component:
1import Image from 'next/image';
2import myLoader from '@/my/image/loader';
3
4export default function QuantumCityView() {
5 return (
6 <Image
7 loader={myLoader}
8 src="quantum-city.jpg"
9 alt="Panorama Metropolis Quantum"
10 width={1200}
11 height={600}
12 />
13 );
14}Practical Application Examples
1. Image Gallery with Lazy Loading
1// components/quantum-gallery.tsx
2import { useState } from 'react';
3import Image from 'next/image';
4
5const images = [
6 { src: '/images/quantum-city-1.jpg', alt: 'Panorama Metropolis Quantum' },
7 { src: '/images/quantum-city-2.jpg', alt: 'Dzielnica Business Quantum' },
8 { src: '/images/quantum-city-3.jpg', alt: 'Parki Kwantowe' },
9 { src: '/images/quantum-city-4.jpg', alt: 'Architektura Kwantowa' },
10 { src: '/images/quantum-city-5.jpg', alt: 'Transport Kwantowy' },
11 // more images...
12];
13
14export default function QuantumGallery() {
15 const [selectedImage, setSelectedImage] = useState(null);
16
17 return (
18 <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
19 <h2 className="text-3xl font-bold mb-6">Galeria Metropolis Quantum</h2>
20
21 {/* Display selected image */}
22 {selectedImage && (
23 <div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50">
24 <div className="max-w-4xl mx-auto p-4">
25 <div className="relative w-full" style={{ height: '80vh' }}>
26 <Image
27 src={selectedImage.src}
28 alt={selectedImage.alt}
29 fill
30 style={{ objectFit: 'contain' }}
31 preload
32 />
33 </div>
34 <button
35 className="absolute top-4 right-4 text-white text-2xl"
36 onClick={() => setSelectedImage(null)}
37 >
38 ×
39 </button>
40 </div>
41 </div>
42 )}
43
44 {/* Image grid */}
45 <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
46 {images.map((image, index) => (
47 <div
48 key={index}
49 className="relative aspect-square overflow-hidden rounded-lg cursor-pointer hover:opacity-90 transition-opacity"
50 onClick={() => setSelectedImage(image)}
51 >
52 <Image
53 src={image.src}
54 alt={image.alt}
55 fill
56 style={{ objectFit: 'cover' }}
57 sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, (max-width: 1024px) 33vw, 25vw"
58 // First image is priority, rest are loaded lazily
59 preload={index === 0}
60 />
61 </div>
62 ))}
63 </div>
64 </div>
65 );
66}2. Responsive Banner with Different Images for Different Devices
1// components/quantum-hero.tsx
2import Image from 'next/image';
3
4export default function QuantumHero() {
5 return (
6 <div className="relative">
7 {/* Image for mobile devices */}
8 <div className="sm:hidden relative h-[50vh]">
9 <Image
10 src="/images/quantum-hero-mobile.jpg"
11 alt="Metropolis Quantum - City of the Future"
12 fill
13 style={{ objectFit: 'cover' }}
14 preload
15 />
16 </div>
17
18 {/* Image for tablets */}
19 <div className="hidden sm:block md:hidden relative h-[60vh]">
20 <Image
21 src="/images/quantum-hero-tablet.jpg"
22 alt="Metropolis Quantum - City of the Future"
23 fill
24 style={{ objectFit: 'cover' }}
25 preload
26 />
27 </div>
28
29 {/* Image for desktops */}
30 <div className="hidden md:block relative h-[70vh]">
31 <Image
32 src="/images/quantum-hero-desktop.jpg"
33 alt="Metropolis Quantum - City of the Future"
34 fill
35 style={{ objectFit: 'cover' }}
36 preload
37 />
38 </div>
39
40 {/* Overlay content */}
41 <div className="absolute inset-0 flex items-center justify-center">
42 <div className="text-center text-white p-4 backdrop-blur-sm bg-black/30 rounded-lg max-w-2xl">
43 <h1 className="text-4xl sm:text-5xl md:text-6xl font-bold mb-4">
44 Metropolis Quantum
45 </h1>
46 <p className="text-xl sm:text-2xl md:text-3xl">
47 The city of the future awaits you
48 </p>
49 </div>
50 </div>
51 </div>
52 );
53}3. Product Cards with Images
1// components/quantum-product-card.tsx
2import Image from 'next/image';
3import { useState } from 'react';
4
5interface ProductCardProps {
6 product: {
7 id: string;
8 name: string;
9 image: string;
10 price: number;
11 description: string;
12 };
13}
14
15export default function ProductCard({ product }: ProductCardProps) {
16 const [isLoading, setIsLoading] = useState(true);
17
18 return (
19 <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden">
20 <div className="relative h-64 w-full bg-gray-200 dark:bg-gray-700">
21 <Image
22 src={product.image}
23 alt={product.name}
24 fill
25 style={{ objectFit: 'cover' }}
26 sizes="(max-width: 768px) 100vw, 33vw"
27 className={`
28 duration-700 ease-in-out
29 ${isLoading ? 'scale-110 blur-xl grayscale' : 'scale-100 blur-0 grayscale-0'}
30 `}
31 onLoad={() => setIsLoading(false)}
32 />
33 </div>
34 <div className="p-4">
35 <h3 className="text-xl font-semibold mb-2 dark:text-white">{product.name}</h3>
36 <p className="text-gray-600 dark:text-gray-300 mb-2">{product.description}</p>
37 <div className="flex justify-between items-center">
38 <span className="text-lg font-bold dark:text-white">
39 {new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' }).format(product.price)}
40 </span>
41 <button className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md">
42 Dodaj do koszyka
43 </button>
44 </div>
45 </div>
46 </div>
47 );
48}Dobre praktyki przy pracy z komponentem Image
- Always specify dimensions - for images with the
srcattribute, always definewidthandheightor usefillwith a container of defined dimensions - Use the
sizesattribute - helps in delivering appropriate image sizes for different devices - Prioritize "above the fold" images - use
preload(formerlypriority) for the most important image visible without scrolling - Use appropriate formats - let Next.js automatically convert to WebP/AVIF
- Optimize for Core Web Vitals - maintain low LCP and CLS
- Use static imports for local images
- Do not overuse
unoptimized- use only in justified cases - Use meaningful
altvalues - for accessibility and SEO - Support different formats - configure AVIF and WebP support in
next.config.js
Image Format Support in Next.js 16
Next.js supports automatic conversion of images to modern formats. By default, Next.js uses the WebP format, which offers good compression while maintaining quality. However, you can also configure support for the AVIF format, which offers even better compression:
1// next.config.js
2module.exports = {
3 images: {
4 formats: ['image/avif', 'image/webp'],
5 },
6}Image Format Comparison
| Format | Advantages | Disadvantages | Browser Support | |--------|--------|------|----------------------| | JPEG | Widely supported, good for photography | No transparency, larger size than newer formats | All browsers | | PNG | Supports transparency, lossless | Large file size | All browsers | | WebP | Smaller size than JPEG/PNG, supports transparency | Incomplete support in older browsers | ~95% of browsers | | AVIF | Best compression, good quality | Limited browser support, slower encoding | ~70% of browsers |
Debugging and Troubleshooting
Problem: Images are Blurry or Low Quality
Solution: Adjust the quality parameter:
1<Image
2 src="/images/quantum-city.jpg"
3 alt="Panorama Metropolis Quantum"
4 width={1200}
5 height={600}
6 quality={90} // Default is 75
7/>In Next.js 16, the quality value must be on the images.qualities list in next.config. By default the list contains only 75, so unless you add 90, Next.js uses the closest allowed value, which is 75:
1// next.config.js
2module.exports = {
3 images: {
4 qualities: [50, 75, 90],
5 },
6};Now the image is generated at quality 90, while other images can keep using the default 75.
Problem: Layout Shift During Image Loading
Solution: Always specify image dimensions or use fill with a container of defined dimensions:
1<div className="relative w-full aspect-video">
2 <Image
3 src="/images/quantum-city.jpg"
4 alt="Panorama Metropolis Quantum"
5 fill
6 style={{ objectFit: 'cover' }}
7 />
8</div>Problem: Images are Not Responsive on Different Devices
Solution: Use the sizes attribute:
1<Image
2 src="/images/quantum-city.jpg"
3 alt="Panorama Metropolis Quantum"
4 width={1200}
5 height={600}
6 sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
7/>Problem: SVG Images are Not Displaying Properly
Solution: For SVG files, the best option is often to use unoptimized:
1<Image
2 src="/images/logo.svg"
3 alt="Logo Metropolis Quantum"
4 width={200}
5 height={200}
6 unoptimized
7/>Image Optimization Beyond the Image Component
In addition to the Image component, it is also worth using other image optimization techniques:
1. Optimizing Images Before Adding to the Project
Before adding images to the project, it is worth optimizing them using tools such as:
- ImageOptim
- Squoosh
- TinyPNG
- SVGO (for SVG files)
2. Using CDN for Serving Images
Using a CDN (Content Delivery Network) can significantly speed up image delivery:
1// next.config.js
2module.exports = {
3 images: {
4 loader: 'akamai',
5 path: 'https://cdn.quantum-city.com',
6 },
7}3. Using "Art Direction" Technique for Different Devices
1<picture>
2 <source media="(max-width: 640px)" srcSet="/images/banner-mobile.jpg" />
3 <source media="(max-width: 1024px)" srcSet="/images/banner-tablet.jpg" />
4 <source media="(min-width: 1025px)" srcSet="/images/banner-desktop.jpg" />
5 <img src="/images/banner-fallback.jpg" alt="Banner" />
6</picture>4. Using "Responsive Images" Technique with srcset
1<img
2 src="/images/quantum-city.jpg"
3 srcSet="
4 /images/quantum-city-small.jpg 640w,
5 /images/quantum-city-medium.jpg 1024w,
6 /images/quantum-city-large.jpg 1920w
7 "
8 sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
9 alt="Panorama Metropolis Quantum"
10/>Summary
Image optimization is a crucial aspect of creating efficient web applications. Next.js 16 offers a powerful Image component that automatically handles many aspects of optimization:
- Automatic optimization - conversion to modern formats (WebP, AVIF)
- Size adjustment - serving images in the appropriate size for the device
- Lazy loading - images are loaded only when they approach the viewport
- Avoiding layout shifts - reserving space for images before they load
- Support for multiple sources - easy specification of different images for different resolutions
Thanks to these features, you can create applications that load faster, consume less data, and provide a better user experience. Just as the engineers of Metropolis Quantum optimize hologram display systems and digital billboards, you can optimize images in your Next.js application to provide users with a smooth and efficient experience.
In the next chapter, we will learn about different image loading strategies (lazy, eager, priority), which will allow us to further customize image behavior to suit your application's needs.
Code for this lesson: app/page.tsx
1// Next.js Image Component - Optimization Demo
2'use client';
3
4import { useState } from 'react';
5
6// Note: In a real Next.js project, you'd use:
7// import Image from 'next/image';
8// Here we demonstrate the concepts with standard img tags
9
10export default function ImageOptimizationDemo() {
11 const [showComparison, setShowComparison] = useState(false);
12
13 return (
14 <div className="min-h-screen bg-gray-900 text-white p-8">
15 <div className="max-w-4xl mx-auto">
16 <h1 className="text-3xl font-bold mb-2">Image Optimization in Next.js 16</h1>
17 <p className="text-gray-400 mb-8">
18 Automatic optimization, lazy loading, and responsive images
19 </p>
20
21 {/* Traditional vs Next.js Image comparison */}
22 <section className="mb-12">
23 <h2 className="text-xl font-semibold mb-4">Traditional HTML vs Next.js Image</h2>
24
25 <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
26 {/* Traditional approach */}
27 <div className="bg-gray-800 rounded-lg p-6">
28 <h3 className="text-red-400 font-mono mb-3">Traditional {"<img>"}</h3>
29 <pre className="bg-gray-900 p-4 rounded text-sm overflow-x-auto">
30{`<img
31 src="/photo.jpg"
32 alt="City panorama"
33 width="800"
34 height="600"
35/>`}
36 </pre>
37 <ul className="mt-4 space-y-2 text-sm text-gray-400">
38 <li>• No automatic optimization</li>
39 <li>• No lazy loading by default</li>
40 <li>• No responsive sizing</li>
41 <li>• Can cause layout shift (CLS)</li>
42 </ul>
43 </div>
44
45 {/* Next.js Image approach */}
46 <div className="bg-gray-800 rounded-lg p-6">
47 <h3 className="text-green-400 font-mono mb-3">Next.js {"<Image>"}</h3>
48 <pre className="bg-gray-900 p-4 rounded text-sm overflow-x-auto">
49{`import Image from 'next/image';
50
51<Image
52 src="/photo.jpg"
53 alt="City panorama"
54 width={800}
55 height={600}
56 placeholder="blur"
57/>`}
58 </pre>
59 <ul className="mt-4 space-y-2 text-sm text-gray-400">
60 <li>Auto WebP/AVIF conversion</li>
61 <li>Built-in lazy loading</li>
62 <li>Responsive srcset</li>
63 <li>Prevents layout shift</li>
64 </ul>
65 </div>
66 </div>
67 </section>
68
69 {/* Image properties demo */}
70 <section className="mb-12">
71 <h2 className="text-xl font-semibold mb-4">Key Properties</h2>
72 <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
73 <div className="bg-gray-800 rounded-lg p-4">
74 <h3 className="text-blue-400 font-semibold mb-2">fill</h3>
75 <p className="text-sm text-gray-400">
76 Image fills parent container. Use with position: relative on parent.
77 </p>
78 <code className="text-xs text-green-400 mt-2 block">
79 {"<Image fill style={{objectFit: 'cover'}} />"}
80 </code>
81 </div>
82 <div className="bg-gray-800 rounded-lg p-4">
83 <h3 className="text-purple-400 font-semibold mb-2">sizes</h3>
84 <p className="text-sm text-gray-400">
85 Responsive breakpoints for different viewport widths.
86 </p>
87 <code className="text-xs text-green-400 mt-2 block">
88 {'sizes="(max-width: 768px) 100vw, 50vw"'}
89 </code>
90 </div>
91 <div className="bg-gray-800 rounded-lg p-4">
92 <h3 className="text-yellow-400 font-semibold mb-2">placeholder</h3>
93 <p className="text-sm text-gray-400">
94 Show blur or empty placeholder while image loads.
95 </p>
96 <code className="text-xs text-green-400 mt-2 block">
97 {'placeholder="blur" blurDataURL="..."'}
98 </code>
99 </div>
100 </div>
101 </section>
102 </div>
103 </div>
104 );
105}Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. In Tailwind CSS the class 'flex justify-center items-center' means:
2. CSS-in-JS allows:
Hands-on tasks in the game
- Code editor
Create CSS with media queries for mobile-first responsive design (sm, md, lg, xl breakpoints)
- Horizontal ordering
Arrange the elements in the correct order: return { → notFound: → true
- Click in order
Arrange the media query syntax with min-width
- Code editor
Create a page layout with header, sidebar, main content and footer using CSS Grid