HTML: Media & Embedded Content
Images — Responsive & Performant
<!-- Basic image with required alt -->
<img src="photo.jpg" alt="Alice presenting at a conference">
<!-- Decorative image — empty alt, not described to screen readers -->
<img src="decorative-line.svg" alt="">
<!-- Responsive images — let browser choose optimal size -->
<img
src="hero-800.jpg"
srcset="
hero-400.jpg 400w,
hero-800.jpg 800w,
hero-1200.jpg 1200w,
hero-1600.jpg 1600w
"
sizes="
(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px
"
alt="Hero image"
width="1200"
height="600"
loading="lazy"
decoding="async">
<!-- Always include width/height to prevent layout shift (CLS) -->
<!-- loading="lazy" defers offscreen images until near viewport -->
<!-- decoding="async" doesn't block main thread during image decode -->picture Element — Art Direction
<!-- Different image crops for different screen sizes -->
<picture>
<!-- Mobile: tall portrait crop -->
<source
media="(max-width: 600px)"
srcset="hero-mobile.webp"
type="image/webp">
<!-- Tablet: square crop -->
<source
media="(max-width: 1024px)"
srcset="hero-tablet.webp"
type="image/webp">
<!-- Desktop: wide landscape -->
<source srcset="hero-desktop.webp" type="image/webp">
<!-- Fallback for browsers not supporting WebP -->
<img src="hero-desktop.jpg" alt="Product hero image" width="1440" height="600">
</picture>
<!-- Modern format with JPEG fallback -->
<picture>
<source srcset="photo.avif" type="image/avif">
<source srcset="photo.webp" type="image/webp">
<img src="photo.jpg" alt="A beautiful landscape">
</picture>Video
<video
controls
width="800"
height="450"
poster="thumbnail.jpg"
preload="metadata" <!-- none | metadata | auto -->
playsinline <!-- plays inline on iOS, not fullscreen -->
loop
muted <!-- required for autoplay to work in most browsers -->
autoplay>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
<!-- Subtitles / closed captions (required for accessibility) -->
<track kind="subtitles" src="captions.vtt" srclang="en" label="English" default>
<track kind="subtitles" src="captions-uk.vtt" srclang="uk" label="Ukrainian">
<p>Your browser doesn't support HTML video.
<a href="video.mp4">Download the video</a></p>
</video>Audio
<audio controls preload="none">
<source src="podcast.opus" type="audio/ogg; codecs=opus">
<source src="podcast.mp3" type="audio/mpeg">
<p>Your browser doesn't support HTML audio.</p>
</audio>
<!-- Autoplay audio is blocked by browsers unless muted -->
<audio autoplay muted loop>
<source src="ambient.mp3" type="audio/mpeg">
</audio>iframe — Embedding External Content
<!-- Embed a YouTube video (privacy-enhanced mode) -->
<iframe
width="560"
height="315"
src="https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"
title="Video title"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin">
</iframe>
<!-- Sandbox — restricts iframe capabilities -->
<iframe
src="https://example.com/widget"
sandbox="allow-scripts allow-same-origin allow-forms"
title="Widget description">
<!-- sandbox values (additive):
allow-scripts — run JavaScript
allow-same-origin — maintain origin (for cookie access, localStorage)
allow-forms — submit forms
allow-popups — window.open()
allow-top-navigation — navigate parent frame
-->
</iframe>canvas Basics
<canvas id="myCanvas" width="800" height="400">
<!-- Fallback content for non-canvas browsers -->
Your browser doesn't support Canvas.
</canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// Shapes
ctx.fillStyle = '#0070f3';
ctx.fillRect(10, 10, 100, 50); // x, y, width, height
ctx.strokeStyle = '#ff0000';
ctx.lineWidth = 3;
ctx.strokeRect(120, 10, 100, 50);
// Path
ctx.beginPath();
ctx.moveTo(10, 100);
ctx.lineTo(100, 150);
ctx.lineTo(50, 200);
ctx.closePath();
ctx.fill();
// Text
ctx.font = '24px sans-serif';
ctx.fillStyle = '#000';
ctx.fillText('Hello Canvas', 10, 300);
// Image
const img = new Image();
img.onload = () => ctx.drawImage(img, 200, 10, 200, 100);
img.src = 'photo.jpg';
</script>Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free