HTML video tag attributes reference
The HTML video tag supports the following attributes: src (specifies video file source), width (sets player width), height (sets player height), controls (displays default playback controls if present), autoPlay (starts playing when page loads, browser autoplay policies vary), loop (loops playback), muted (mutes audio by default, often used with autoPlay), preload (specifies preload behavior with values: none, metadata, auto), playsInline (enables inline playback on iOS devices, often necessary for autoplay on iOS Safari).
Best practice for video autoplay on all browsers
When using the autoPlay attribute, include both the muted attribute to ensure the video plays automatically in most browsers and the playsInline attribute for compatibility with iOS devices.
Video tag best practices for accessibility
Include fallback content inside the video tag for browsers that do not support video playback. Include subtitles or captions for users who are deaf or hard of hearing using the track tag to specify caption file sources. Standard HTML5 video controls are recommended for keyboard navigation and screen reader compatibility. For advanced needs, consider third-party players like react-player or video.js which offer accessible controls and consistent browser experience.
HTML iframe tag attributes reference
The HTML iframe tag supports the following attributes: src (the URL of the page to embed), width (sets iframe width), height (sets iframe height), allowFullScreen (allows iframe content to be displayed in full-screen mode), sandbox (enables an extra set of restrictions on iframe content), loading (optimize loading behavior such as lazy loading), title (provides a title for iframe to support accessibility).
When to use video tag vs iframe
Use the HTML video tag for self-hosted or direct video files when you need detailed control over the player's functionality and appearance. Use the HTML iframe tag for video hosting services like YouTube or Vimeo, which limits some control over the player but offers ease of use and features provided by these platforms.
Embedding externally hosted videos with Server Components and Suspense
To embed videos from external platforms, create a Server Component that fetches the video source URL and renders an iframe. Then stream the component using React Suspense with a fallback UI shown while the video component loads. This prevents the page from blocking and allows user interaction while the video component streams in. For better user experience, use a loading skeleton as the fallback UI instead of a simple loading message.
Example: Server Component for embedding external videos
```jsx
export default async function VideoComponent() {
const src = await getVideoSrc()
return <iframe src={src} allowFullScreen />
}
```
This Server Component fetches the video source URL and renders an iframe for embedding the video.
Example: Streaming video component with React Suspense
```jsx
import { Suspense } from 'react'
import VideoComponent from '../ui/VideoComponent.jsx'
import VideoSkeleton from '../ui/VideoSkeleton.jsx'
export default function Page() {
return (
<section>
<Suspense fallback={<VideoSkeleton />}>
<VideoComponent />
</Suspense>
{/* Other content of the page */}
</section>
)
}
```
This pattern streams a video component using React Suspense with a skeleton fallback UI while the video loads.
Self-hosted video benefits
Self-hosting videos provides: complete control and independence over video content from playback to appearance with full ownership free from external platform constraints; customization for specific needs like dynamic background videos aligned with design and functional requirements; ability to choose high-performing and scalable storage solutions to support increasing traffic and content size; balance of storage and bandwidth costs with easy integration into Next.js framework and broader tech ecosystem.
Hosting videos with Vercel Blob example
```jsx
import { Suspense } from 'react'
import { list } from '@vercel/blob'
export default function Page() {
return (
<Suspense fallback={<p>Loading video...</p>}>
<VideoComponent fileName="my-video.mp4" />
</Suspense>
)
}
async function VideoComponent({ fileName }) {
const { blobs } = await list({
prefix: fileName,
limit: 1,
})
const { url } = blobs[0]
return (
<video controls preload="none" aria-label="Video player">
<source src={url} type="video/mp4" />
Your browser does not support the video tag.
</video>
)
}
```
This example shows how to fetch a video from Vercel Blob using the list function and display it with the video tag using React Suspense.
Adding subtitles from Vercel Blob example
```jsx
async function VideoComponent({ fileName }) {
const { blobs } = await list({
prefix: fileName,
limit: 2,
})
const { url } = blobs[0]
const { url: captionsUrl } = blobs[1]
return (
<video controls preload="none" aria-label="Video player">
<source src={url} type="video/mp4" />
<track src={captionsUrl} kind="subtitles" srcLang="en" label="English" />
Your browser does not support the video tag.
</video>
)
}
```
This example shows how to fetch both video and subtitle files from Vercel Blob and add captions to the video using the track element.
Best practices for embedding external videos
Ensure video embeds are responsive by using CSS to make the iframe or video player adapt to different screen sizes. Implement strategies for loading videos based on network conditions, especially for users with limited data plans.
Example: Basic HTML video tag with subtitles
```jsx
export function Video() {
return (
<video width="320" height="240" controls preload="none">
<source src="/path/to/video.mp4" type="video/mp4" />
<track
src="/path/to/captions.vtt"
kind="subtitles"
srcLang="en"
label="English"
/>
Your browser does not support the video tag.
</video>
)
}
```
This example shows a basic video component with controls, a specific preload strategy, and subtitles.
Example: Basic HTML iframe for external videos
```jsx
export default function Page() {
return (
<iframe src="https://www.youtube.com/embed/19g66ezsKAg" allowFullScreen />
)
}
```
This example shows how to embed a YouTube video using an iframe with the allowFullScreen attribute.
Image Optimization with static export
Image Optimization through `next/image` can be used with static export by defining a custom image loader in next.config.js. Set `images: { loader: 'custom', loaderFile: './my-loader.ts' }` to use a custom loader that constructs URLs for a remote image service like Cloudinary.
Custom image loader for Cloudinary
A custom image loader function receives an object with `src` (string), `width` (number), and `quality` (optional number). The loader for Cloudinary constructs URLs by joining params like `f_auto`, `c_limit`, `w_${width}`, `q_${quality || 'auto'}` and appending them to `https://res.cloudinary.com/demo/image/upload/`. Example: `https://res.cloudinary.com/demo/image/upload/f_auto,c_limit,w_300,q_auto/turtles.jpg`