Bootstrap 5 Tutorial
v5.3.0Bootstrap 5 Tutorial
Responsive Video in Bootstrap 5
The Challenge with Video Embeds
Videos from platforms like YouTube, Vimeo, and others often come with fixed dimensions that don't adapt to different screen sizes. Bootstrap's ratio utilities solve this problem.
❌ Non-Responsive Video
Overflows on smaller screens
✅ Responsive Video
Perfectly scales on all screens
The Ratio Utility Classes
How Ratio Utilities Work
Bootstrap 5 introduces .ratio classes that maintain aspect ratios for embedded content. The container maintains its aspect ratio while the embedded content scales to fit.
/* CSS behind ratio classes */
.ratio {
position: relative;
width: 100%;
}
.ratio::before {
display: block;
padding-top: var(--bs-aspect-ratio);
content: "";
}
.ratio > * {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Example: 16:9 aspect ratio */
.ratio-16x9 {
--bs-aspect-ratio: 56.25%; /* 9 ÷ 16 = 0.5625 */
}How it works:
- Container uses padding-top to create aspect ratio
- Content is positioned absolutely to fill container
- Width is always 100% of parent
- Height scales proportionally
- Works with any embedded content (iframe, video, embed)
Key benefits:
- No JavaScript required
- Pure CSS solution
- Excellent browser support
- Lightweight and performant
- Easy to implement
Standard Aspect Ratios
Built-in Aspect Ratio Classes
1:1 (Square)
.ratio-1x14:3 (Standard)
.ratio-4x316:9 (Widescreen)
.ratio-16x921:9 (Ultrawide)
.ratio-21x93:2 (Photo)
.ratio-3x2Custom Ratio
style="--bs-aspect-ratio: 75%"<!-- Standard aspect ratios -->
<div class="ratio ratio-1x1">
<!-- Square content -->
</div>
<div class="ratio ratio-4x3">
<!-- Traditional TV/video -->
</div>
<div class="ratio ratio-16x9">
<!-- Modern widescreen -->
</div>
<div class="ratio ratio-21x9">
<!-- Ultra-wide cinema -->
</div>
<div class="ratio ratio-3x2">
<!-- Photographic prints -->
</div>
<!-- Custom aspect ratio -->
<div class="ratio" style="--bs-aspect-ratio: 75%;">
<!-- 4:3 equivalent -->
</div>YouTube & Vimeo Embeds
Embedding Video Platforms
YouTube Embed
Vimeo Embed
<!-- YouTube Embed -->
<div class="ratio ratio-16x9">
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>
</div>
<!-- Vimeo Embed -->
<div class="ratio ratio-16x9">
<iframe
src="https://player.vimeo.com/video/VIDEO_ID"
title="Vimeo video player"
frameborder="0"
allowfullscreen
></iframe>
</div>
<!-- Best practices:
1. Always include title attribute
2. Use allowfullscreen attribute
3. Consider lazy loading
4. Add loading="lazy" for performance
-->Performance Tips for Video Embeds:
- Lazy loading: Add
loading="lazy"to iframes - Preview image: Use thumbnail before loading video
- Defer loading: Load videos after page content
- Limit embeds: Too many videos slow down pages
- Consider alternatives: Use lightweight video players when possible
HTML5 Video Element
Native HTML5 Video
HTML5 Video Features:
- Native browser controls
- Multiple format support
- Custom styling options
- JavaScript API access
- Better accessibility
<!-- HTML5 Video with responsive wrapper -->
<div class="ratio ratio-16x9">
<video
controls
poster="preview-image.jpg"
class="rounded"
>
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<source src="video.ogv" type="video/ogg">
Your browser does not support the video tag.
</video>
</div>
<!-- Video attributes:
- controls: Shows native controls
- autoplay: Starts playing automatically
- muted: Starts muted (required for autoplay)
- loop: Loops the video
- preload: "none", "metadata", or "auto"
- poster: Preview image before playback
-->Custom Video Player Styling
Enhanced Video Components
With overlay badges and controls
Card with video background
Circular video player
Hero video with play button
<!-- Video with overlay badges -->
<div class="ratio ratio-16x9 position-relative">
<video controls class="rounded shadow">
<!-- video sources -->
</video>
<span class="position-absolute top-0 start-0 m-2 badge bg-danger">
Live
</span>
<button class="btn btn-sm btn-outline-light position-absolute top-0 end-0 m-2">
<i class="bi bi-fullscreen"></i>
</button>
</div>
<!-- Card with video background -->
<div class="ratio ratio-16x9">
<div class="card bg-dark text-white overflow-hidden">
<video muted autoplay loop class="card-img-top">
<!-- video sources -->
</video>
<div class="card-img-overlay d-flex flex-column justify-content-end">
<div class="bg-dark bg-opacity-75 p-3">
<h5 class="card-title">Featured Video</h5>
<button class="btn btn-sm btn-primary">Watch Now</button>
</div>
</div>
</div>
</div>
<!-- Circular video -->
<div class="ratio ratio-1x1 rounded-circle overflow-hidden border border-3 border-primary">
<video muted autoplay loop class="object-fit-cover">
<!-- video sources -->
</video>
</div>Responsive Video Gallery
Video Grid Layout
Video 1
Video Title 1
Short description of the video content and what users can expect to learn.
Video 2
Video Title 2
Short description of the video content and what users can expect to learn.
Video 3
Video Title 3
Short description of the video content and what users can expect to learn.
Video 4
Video Title 4
Short description of the video content and what users can expect to learn.
Video 5
Video Title 5
Short description of the video content and what users can expect to learn.
Video 6
Video Title 6
Short description of the video content and what users can expect to learn.
<!-- Responsive video gallery -->
<div class="row g-3">
<div class="col-lg-4 col-md-6">
<div class="card">
<!-- Video thumbnail/container -->
<div class="ratio ratio-16x9">
<!-- Video iframe or thumbnail image -->
<img
src="thumbnail.jpg"
class="card-img-top"
alt="Video thumbnail"
/>
<!-- Or play button overlay -->
<div class="position-absolute top-50 start-50 translate-middle">
<button class="btn btn-primary rounded-circle p-3">
<i class="bi bi-play-fill"></i>
</button>
</div>
</div>
<!-- Video info -->
<div class="card-body">
<h6 class="card-title">Video Title</h6>
<p class="card-text small">Description</p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">Duration</small>
<button class="btn btn-sm btn-outline-primary">
Play
</button>
</div>
</div>
</div>
</div>
<!-- Repeat for other videos -->
</div>Gallery Best Practices:
- Consistent thumbnails: Use same aspect ratio for all videos
- Lazy loading: Implement lazy loading for iframes/images
- Accessible controls: Ensure keyboard navigation works
- Performance: Load videos only when needed (click to play)
- Mobile optimization: Test touch controls on mobile devices
Performance Optimization
Optimizing Video Performance
Lazy Loading Videos
Video loads only when user clicks play
Low-Quality Preview
Small preview loads first, then full video
✅ Performance Best Practices:
- Use lazy loading for iframes
- Implement click-to-play for multiple videos
- Optimize video file sizes
- Use modern formats (WebM, MP4 H.265)
- Implement bandwidth detection
- Use CDN for video delivery
❌ Common Performance Issues:
- Autoplaying multiple videos
- Unoptimized video files
- Too many simultaneous embeds
- No lazy loading implementation
- Missing preview images
- Blocking render with video loading
<!-- Lazy loading video implementation -->
<!-- Option 1: Click to load -->
<div class="ratio ratio-16x9 position-relative">
<img
src="preview.jpg"
class="img-fluid rounded"
alt="Video preview"
/>
<button
class="btn btn-primary btn-lg position-absolute top-50 start-50 translate-middle"
onclick="loadVideo()"
>
<i class="bi bi-play-fill"></i> Play
</button>
</div>
<script>
function loadVideo() {
// Replace with iframe or video element
document.querySelector('.ratio').innerHTML = `
<iframe ...></iframe>
`;
}
<!-- Option 2: Intersection Observer -->
<iframe
loading="lazy"
data-src="https://youtube.com/embed/VIDEO_ID"
class="lazy-video"
></iframe>
<script>
// Load when visible in viewport
const lazyVideos = document.querySelectorAll('.lazy-video');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const iframe = entry.target;
iframe.src = iframe.dataset.src;
observer.unobserve(iframe);
}
});
});
lazyVideos.forEach(video => observer.observe(video));
</script>Accessibility Considerations
Making Videos Accessible
Accessibility Features:
- Closed captions/subtitles
- Audio descriptions
- Keyboard navigation
- Screen reader support
- Transcript availability
- Proper ARIA labels
- Color contrast for controls
<!-- Accessible video implementation -->
<div class="ratio ratio-16x9">
<video
controls
aria-label="Video title and purpose"
aria-describedby="video-description"
>
<!-- Video sources -->
<source src="video.mp4" type="video/mp4">
<!-- Captions for hearing impaired -->
<track
kind="captions"
src="captions.vtt"
srclang="en"
label="English"
default
>
<!-- Audio descriptions for visually impaired -->
<track
kind="descriptions"
src="descriptions.vtt"
srclang="en"
label="English Descriptions"
>
<!-- Fallback text -->
<p>
Your browser doesn't support HTML5 video.
<a href="video.mp4">Download the video</a>
or <a href="transcript.txt">read the transcript</a>.
</p>
</video>
</div>
<!-- Hidden description for screen readers -->
<div id="video-description" class="visually-hidden">
Detailed description of video content for screen readers.
</div>Accessibility Checklist:
- ✅ Provide captions for all spoken content
- ✅ Include audio descriptions for visual content
- ✅ Ensure keyboard navigable controls
- ✅ Provide text transcripts
- ✅ Use proper ARIA attributes
- ✅ Test with screen readers
- ✅ Ensure sufficient color contrast in controls
- ✅ Avoid autoplay or provide controls to stop
Common Issues and Solutions
| Issue | Cause | Solution |
|---|---|---|
| Video not scaling | Missing .ratio wrapper | Wrap in .ratio ratio-16x9 (or appropriate ratio) |
| Black bars around video | Aspect ratio mismatch | Use correct ratio class or object-fit: cover |
| Slow page loading | Too many video embeds | Implement lazy loading and click-to-play |
| Autoplay not working | Browser restrictions | Add muted attribute and user interaction |
| Mobile playback issues | Incompatible formats | Provide multiple source formats (MP4, WebM) |
| Controls not visible | Custom styling conflicts | Check CSS inheritance and z-index |
| Fullscreen not working | Missing allowfullscreen | Add allowfullscreen to iframes |
Best Practices Summary
Responsive Video Best Practices
- Always use ratio utilities: Ensure videos scale properly
- Implement lazy loading: Improve page performance
- Provide multiple formats: Ensure cross-browser compatibility
- Include accessibility features: Captions, transcripts, ARIA labels
- Optimize file sizes: Compress videos without losing quality
- Use appropriate aspect ratios: Match content to container
- Test on multiple devices: Ensure responsive behavior works everywhere
- Consider bandwidth: Provide quality options for different connections
- Add preview images: Improve perceived performance
- Follow platform guidelines: Respect YouTube/Vimeo embedding policies
Quick Reference
.ratio ratio-16x9- Widescreen video.ratio ratio-4x3- Standard video.ratio ratio-1x1- Square videoloading="lazy"- Lazy load iframesallowfullscreen- Enable fullscreencontrols- Show video controlsautoplay muted- Autoplay video