How to Add an Image in HTML
Learn how to add images in HTML with correct paths, accessible alt text, responsive sources, captions, troubleshooting, and performance tips.
The HTML element for displaying an image is <img>. Give it a valid src path and meaningful alt text:
<img src="images/photo.jpg" alt="A red bicycle leaning against a brick wall" width="800" height="600">
src identifies the image file. alt provides a text alternative for people who cannot see the image and for cases where the file cannot load. The <img> element is a void element, so it has no closing tag. See the MDN <img> reference.
1. Create the basic image
Assume this project structure:
project/
├── index.html
└── images/
└── photo.jpg
In index.html, reference the file relative to the HTML document:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Image example</title>
</head>
<body>
<img
src="images/photo.jpg"
alt="A red bicycle leaning against a brick wall"
width="800"
height="600"
>
</body>
</html>
A relative URL such as images/photo.jpg is resolved from the location of index.html. You can also use an absolute URL:
<img
src="https://example.com/images/photo.jpg"
alt="A red bicycle leaning against a brick wall"
>
For maintainability, hosting project images with your site and using relative paths is usually simpler. Check the exact folder, filename, capitalization, and extension when a local image does not appear.
2. Write useful alt text
Describe the information the image contributes in its surrounding context. Do not describe the HTML syntax or use a filename as the alternative.
| Image purpose | Good markup | Why |
|---|---|---|
| Informative photo | alt="A red bicycle leaning against a brick wall" |
Conveys the relevant visual information. |
| Functional link or button | alt="Download the annual report" |
Describes the action. |
| Decorative flourish | alt="" |
Marks it as decorative for assistive technology. |
Use an empty alt value for a purely decorative image. Do not omit alt casually: an omitted attribute can leave assistive technology without a clear alternative.
<!-- Informative image -->
<img src="images/map.png" alt="Map showing the trail from the visitor center to the lake">
<!-- Decorative image -->
<img src="images/divider-flourish.png" alt="">
3. Reserve space with width and height
When the intrinsic dimensions are known, include pixel-valued width and height attributes. The browser can calculate the aspect ratio before downloading the file and reserve space, which helps prevent layout shifts. CSS can still control the rendered size.
<img
src="images/gallery-detail.jpg"
alt="Close-up of the carved pattern on a wooden bowl"
width="1200"
height="800"
>
The values should match the image’s intrinsic ratio. For example, a 1200×800 image has a 3:2 ratio. Do not use arbitrary dimensions that distort the image.
4. Make images responsive
Use srcset and sizes for resolution alternatives
When you have the same composition at multiple intrinsic widths, list candidates with srcset. Width descriptors such as 400w must match the actual pixel widths of those files. Pair them with sizes so the browser knows the expected rendered slot.
<img
src="images/landscape-800.jpg"
srcset="images/landscape-400.jpg 400w,
images/landscape-800.jpg 800w,
images/landscape-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, 800px"
width="1600"
height="900"
alt="A mountain lake beneath a cloudy sky"
>
Use this pattern when the image content is the same and only resolution changes. The browser chooses an appropriate candidate for the viewport and device.
Use <picture> for art direction or formats
Use <picture> when you need a different crop for a breakpoint or want to offer alternate formats. Keep a fallback <img>; it carries the alt text.
<picture>
<source
srcset="images/portrait.avif"
media="(max-width: 600px)"
type="image/avif"
>
<source srcset="images/landscape.webp" type="image/webp">
<img
src="images/landscape.jpg"
alt="A kayaker crossing a calm lake"
width="1200"
height="800"
>
</picture>
Use srcset for same-composition resolution choices and <picture> when the crop or media format should change. The MDN <picture> documentation covers source selection details.
5. Lazy-load images below the fold
loading="lazy" allows the browser to defer an off-screen image until it is closer to the viewport:
<img
src="images/gallery-detail.jpg"
alt="Close-up of the carved pattern on a wooden bowl"
width="1200"
height="800"
loading="lazy"
>
Do not lazy-load an image needed in the initial viewport, such as a page’s main hero image. Keep dimensions on lazy-loaded images so deferred content still has reserved space. See MDN’s loading guidance.
6. Add a visible caption with <figure>
Use <figure> and <figcaption> when the image needs visible context, attribution, or a description:
<figure>
<img
src="images/dinosaur.jpg"
alt="The head and torso of a dinosaur skeleton"
width="200"
height="171"
>
<figcaption>A Tyrannosaurus skeleton on display in a museum.</figcaption>
</figure>
The caption is visible page content. Keep alt focused on a useful text replacement rather than duplicating the caption. The MDN figure and figcaption guide explains the semantic relationship.
7. Control presentation with CSS
HTML attributes describe the source and intrinsic ratio. CSS controls the displayed size and fit:
.article-image {
display: block;
max-width: 100%;
height: auto;
}
.thumbnail {
width: 240px;
height: 160px;
object-fit: cover;
}
<img
class="article-image"
src="images/landscape.jpg"
alt="A kayaker crossing a calm lake"
width="1200"
height="800"
>
max-width: 100% prevents an image from overflowing a narrow container. height: auto preserves its ratio. Use object-fit: cover only when cropping inside a fixed box is intentional.
8. Why an image is not showing
| Symptom | Likely cause | Fix |
|---|---|---|
| Broken-image icon | Wrong relative path | Resolve the path from the HTML file’s directory. For a sibling images folder, use images/photo.jpg. |
| Works locally, fails on deployment | Filename capitalization differs | Match case exactly. Many production file systems are case-sensitive. |
| 404 in the network panel | File was not copied or URL is wrong | Open the requested URL directly and verify the deployed file exists. |
| Image is stretched | Width and height ratio do not match | Use the intrinsic ratio and set CSS height: auto, or choose an intentional object-fit. |
| No accessible description | Missing or generic alt |
Describe the image’s meaning, or use alt="" when it is decorative. |
| Wrong responsive file | Inaccurate srcset descriptor or sizes |
Make each w value equal the file’s intrinsic width and describe the rendered slot accurately. |
| Image loads too late | Important image was lazy-loaded | Remove loading="lazy" from images needed in the initial viewport. |
| External image blocked | Hotlink protection, authentication, or Content Security Policy | Host the asset yourself, configure the server policy, or use an authorized public URL. |
In browser developer tools, inspect the rendered element and Network panel. Confirm the final requested URL, HTTP status, response content type, and whether the request is blocked by policy.
9. Performance and reliability checklist
- Use the smallest intrinsic file that supports the rendered size.
- Provide accurate
widthandheightvalues. - Use
srcsetandsizeswhen real resolution alternatives exist. - Use
<picture>for art direction or alternate formats. - Lazy-load below-the-fold images, but keep the lead image eager.
- Write meaningful
alttext for informative images and emptyaltfor decoration. - Keep image URLs stable and verify that deployment preserves their paths and capitalization.
- Use visible captions for context or attribution instead of putting all context in
alt.
10. Or skip the browser setup
If your goal is to obtain a clean image of a webpage rather than author an image element yourself, ScreenshotNeo returns a screenshot from one GET request. The API accepts PNG, JPEG, WebP, or PDF output and supports full-page capture, element selectors, responsive viewports, retina scale, custom CSS and JavaScript, waits, headers, cookies, user agents, blocking rules, caching, signed links, asynchronous jobs, bulk capture, and more. See the ScreenshotNeo API documentation.
# cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
# Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
// Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = require('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. An MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
11. Frequently asked questions
What do I put in the src attribute?
Put the image URL or a path relative to the HTML document, such as images/photo.jpg.
Does <img> need a closing tag?
No. It is a void HTML element and must not wrap child content or use </img>.
Should every image have alt text?
Every image should have an alt attribute. Use meaningful text for informative images and alt="" for purely decorative ones.
When should I use <picture> instead of srcset?
Use srcset for different resolutions of the same composition. Use <picture> when the crop or file format should change based on media conditions.
Can CSS add an image instead?
CSS background-image is appropriate for decoration. Use semantic <img> markup when the image conveys content that needs an alternative text.


