ScreenshotNeo

BlogHow-to

How to Insert an Image in an HTML Document

Learn the HTML img tag, image paths, alt text, responsive images, dimensions, troubleshooting, and a ScreenshotNeo shortcut.

By the ScreenshotNeo team1 October 20267 min read

How to Insert an Image in an HTML Document

Use the void <img> element. A beginner-safe example is:

<img src="images/photo.jpg" alt="A description of the image">

src identifies the image resource and alt provides a text replacement for its meaning. The HTML Standard recommends the img element when there is one image resource. See the WHATWG HTML Standard and MDN’s img reference.

1. Add a basic image

Create an HTML file and place an image file where the URL in src can reach it.

The browser resolves the image URL separately from the HTML document and then renders the resource.
The browser resolves the image URL separately from the HTML document and then renders the resource.
<!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>
  <h1>A mountain at sunrise</h1>
  <img src="images/mountain.jpg" alt="A mountain at sunrise">
</body>
</html>

The img element is void: it has no closing tag. Do not write </img>.

Choose the right src form

Form Example Resolution base
Relative images/photo.jpg The URL of the current HTML document
Root-relative /images/photo.jpg The site’s root
Absolute https://example.com/photo.jpg The specified host

Paths are case-sensitive on many servers. A page at /docs/index.html resolves images/photo.jpg as /docs/images/photo.jpg, while /images/photo.jpg starts at the site root.

2. Write useful alternative text

Use alt as the useful replacement for the image’s meaning or function. It is also shown when the image cannot load and is read by screen readers.

<img src="penguin.jpg" alt="A penguin standing on a beach">
  • Describe the subject and relevant context, not the filename.
  • Do not use generic text such as alt="image".
  • For a decorative image with no information, use alt="".
  • If the image is a link, describe the destination or action:
<a href="/gallery">
  <img src="gallery-thumb.jpg" alt="Open the photo gallery">
</a>

Do not repeat nearby text. If a caption already gives the complete meaning, an empty alt value may be appropriate when the image is supplementary.

3. Set dimensions and responsive layout

When intrinsic dimensions are known, include numeric width and height attributes. They let the browser reserve the correct aspect ratio before downloading the image, reducing layout shift.

<img
  src="photo.jpg"
  alt="A mountain at sunrise"
  width="1200"
  height="800">

HTML dimensions are integer pixel hints; do not include units such as px. Use CSS for fluid rendering:

img {
  max-width: 100%;
  height: auto;
}

Keep the HTML dimensions even when CSS scales the rendered image. They preserve the intrinsic ratio while the image adapts to its container.

Prevent overflow and control cropping

.content img {
  display: block;
  max-width: 100%;
  height: auto;
}

.avatar {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 50%;
}

Use object-fit: cover only when cropping is intentional. Use contain when the entire image must remain visible.

4. Serve responsive images

When the same image is available at multiple resolutions, use srcset with width descriptors and pair it with an accurate sizes rule.

srcset and sizes let the browser choose an image resource that fits the available slot.
srcset and sizes let the browser choose an image resource that fits the available slot.
<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, 800px"
  width="1600"
  height="1067"
  alt="A mountain at sunrise">

The browser uses the viewport, device pixel ratio, and sizes estimate to choose a candidate. The numbers must match each file’s actual intrinsic width. A wrong descriptor can make the browser download an unnecessarily large or blurry file.

Use picture for art direction or formats

<picture>
  <source media="(max-width: 600px)" srcset="portrait-crop.jpg">
  <source type="image/avif" srcset="photo.avif">
  <img src="photo.jpg" alt="A mountain at sunrise" width="1600" height="1067">
</picture>

picture can select a different crop or format. It must contain an img fallback with src and alt. The fallback is also where you put the final alternative text and intrinsic dimensions.

Captions

<figure>
  <img src="map.jpg" alt="Map of the hiking route" width="1200" height="700">
  <figcaption>The route follows the northern ridge.</figcaption>
</figure>

Linked images

<a href="/photos/sunrise-large.jpg">
  <img src="sunrise-thumb.jpg" alt="Open the full-size sunrise photograph" width="320" height="213">
</a>

Lazy loading

<img src="below-fold.jpg" alt="Forest trail" width="1200" height="800" loading="lazy" decoding="async">

Use lazy loading for images below the initial viewport. Avoid lazy-loading the main above-the-fold image, because it can delay the largest visible content. Keep dimensions on every lazy image so its space is reserved.

6. Complete working example

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Responsive image</title>
  <style>
    body { max-width:  fiftyrem; margin: 2rem auto; padding: 0 1rem; font: 1rem/1.5 system-ui, sans-serif; }
    img { display: block; max-width: 100%; height: auto; }
  </style>
</head>
<body>
  <main>
    <h1>Responsive image demo</h1>
    <figure>
      <picture>
        <source media="(max-width: 600px)" srcset="images/mountain-portrait.jpg">
        <source type="image/avif" srcset="images/mountain.avif">
        <img
          src="images/mountain-800.jpg"
          srcset="images/mountain-400.jpg 400w, images/mountain-800.jpg 800w, images/mountain-1600.jpg 1600w"
          sizes="(max-width: 600px) 100vw, 800px"
          width="1600"
          height="1067"
          alt="A mountain at sunrise"
          decoding="async">
      </picture>
      <figcaption>Sunrise over the ridge.</figcaption>
    </figure>
  </main>
</body>
</html>

Replace fiftyrem with 50rem in the CSS; the corrected declaration is max-width: 50rem.

7. Troubleshoot missing or incorrect images

Symptom Likely cause Fix
Nothing appears Missing src/srcset, a 404, or a blocked request Inspect the browser Network panel and open the resolved image URL directly.
Broken-image icon Wrong relative base, filename case, URL encoding, permissions, or server availability Check the exact path from the document URL and the server response status.
Image works locally but not after deployment Case-sensitive production filesystem or missing copied asset Match capitalization exactly and verify the deployed file exists.
Layout jumps while loading No intrinsic dimensions or mismatched ratio Add accurate width and height; keep height: auto.
Screen reader says an unhelpful phrase Filename, “image,” or missing alt text Write a concise meaningful alternative, or use alt="" for decoration.
Wrong responsive candidate Incorrect srcset widths or inaccurate sizes Check each file’s intrinsic width and describe its rendered slot accurately.
Image is cropped unexpectedly object-fit: cover or a fixed box Use contain, remove the crop, or choose a deliberate art-directed source.
Cross-origin error in script JavaScript is reading pixels from another origin without permission Configure the image host’s CORS policy or keep the image same-origin; ordinary img display does not require script access.

Debug checklist

  1. View the page source and confirm the element contains src or srcset.
  2. Copy the browser’s resolved request URL and open it directly.
  3. Check status code, MIME type, redirects, and console errors.
  4. Verify filename case, URL encoding, and deployment output.
  5. Check computed CSS for display: none, zero dimensions, clipping, or an unexpected object-fit rule.
  6. For responsive markup, use the browser’s current source and compare it with the intended sizes slot.

8. Performance, reliability, and cost

  • Choose an appropriate intrinsic size and format; downloading a huge source for a small slot wastes bandwidth.
  • Use srcset and sizes when the rendered width varies.
  • Reserve space with dimensions to reduce layout shift.
  • Lazy-load below-fold images, but keep the primary visible image eager.
  • Use a reliable origin or CDN, stable URLs, and long-lived caching for immutable filenames.
  • Keep accessibility independent of image availability: meaningful alt text still communicates when loading fails.
  • HTML itself has no image-hosting charge. Your costs come from storage, transfer, image processing, or a third-party host you choose.

9. Or skip the browser setup

If you need a clean screenshot of an existing page containing images, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from one GET request. Its capture process accepts consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off.

See the ScreenshotNeo API documentation for the available options.

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 bytes = new Uint8Array(await res.arrayBuffer());
await Bun.write('shot.webp', bytes);

Clean shots are the only shots billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Every plan includes every feature. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

10. FAQ

Does img need a closing tag?

No. It is a void element, so write <img ...>.

Can I use a local file path such as C:\\photo.jpg?

Use a web URL or a project-relative path served by your development server. Browser pages generally cannot request arbitrary files from a visitor’s computer.

Should decorative images have no alt attribute?

No. Keep the attribute and set it to an empty value: alt="".

What is the difference between srcset and picture?

srcset chooses among resolutions of the same image. picture can choose different crops or formats and still requires an img fallback.

Why does my image look blurry on a high-density display?

Provide larger candidates in srcset and describe the rendered slot correctly with sizes; the browser can then select an appropriate resource.