Images and Graphics: Adding Visual Elements to the Web โ
What are HTML Images? โ
Images are a vital part of web content. Studies show that the human brain processes images 60,000 times faster than text, making images crucial for grabbing user attention, conveying information, and improving user experience.
Why are Images So Important? โ
Imagine a website without any imagesโa page of pure text is not only boring but also difficult to quickly convey complex information. The roles of images are:
- Visual Appeal: Make pages more vivid and attractive.
- Information Conveyance: A picture is worth a thousand words, quickly conveying complex concepts.
- User Experience: Product displays, brand imagery, etc., all require images.
- Emotional Connection: Images can evoke emotions and enhance user engagement.
<!-- A basic image example -->
<img src="product.jpg" alt="UltraBook Pro laptop" />
<!-- Image with caption -->
<figure>
<img src="chart.png" alt="Sales growth chart" />
<figcaption>Annual sales growth 2020-2025</figcaption>
</figure>However, improper use of images can lead to problems: slow page loading, poor accessibility, poor SEO, etc. Therefore, using image tags correctly is very important.
img Tag Basics โ
Core Attributes of the img Tag โ
<img> is a self-closing tag. The two most important attributes are src and alt:
<!-- Basic Structure -->
<img src="image-path.jpg" alt="Description of image" />
<!-- Actual Example -->
<img src="/images/logo.png" alt="Company Logo" />
<!-- With width and height attributes -->
<img src="photo.jpg" alt="Sunset over mountains" width="800" height="600" />src Attribute - Image Source โ
src specifies the location of the image file:
<!-- Relative Path -->
<img src="images/photo.jpg" alt="Photo" />
<img src="../assets/logo.png" alt="Logo" />
<img src="/static/banner.jpg" alt="Banner" />
<!-- Absolute Path -->
<img src="https://cdn.example.com/image.jpg" alt="External Image" />
<!-- Protocol-relative Path -->
<img src="//cdn.example.com/image.jpg" alt="Image" />
<!-- Data URL (Base64 Encoded) -->
<img src="data:image/png;base64,iVBORw0KGg..." alt="Embedded Image" />alt Attribute - Alternative Text โ
The alt attribute is required. It provides a text description of the image:
<!-- โ
Good alt text: Descriptive and specific -->
<img
src="ceo-portrait.jpg"
alt="Sarah Chen, CEO of TechCorp, speaking at conference"
/>
<img
src="product-laptop.jpg"
alt="Silver UltraBook Pro 15-inch laptop, open at 90 degrees"
/>
<img
src="chart-sales.png"
alt="Bar chart showing 25% sales increase from 2024 to 2025"
/>
<!-- โ Avoid: Not descriptive enough -->
<img src="image1.jpg" alt="image" />
<img src="ceo.jpg" alt="person" />
<img src="chart.png" alt="chart" />
<!-- Decorative images use empty alt -->
<img src="decorative-border.png" alt="" />Why is alt so important?
<!--
Three main roles of alt:
1. Accessibility: Screen readers read alt text
2. SEO: Search engines understand image content via alt
3. Fallback Display: Displays alt text when image fails to load
-->
<!-- Example: When image fails to load -->
<img src="broken-link.jpg" alt="Product demonstration video screenshot" />
<!-- Users will see the text "Product demonstration video screenshot" -->width and height Attributes โ
Specifying image dimensions prevents page layout shifts:
<!-- โ
Recommended: Specify dimensions in advance -->
<img src="photo.jpg" alt="Landscape photo" width="800" height="600" />
<!-- Browser loading process:
1. Parses HTML, sees width and height
2. Reserves 800x600 space
3. Loads image
4. Image displays in reserved space, page doesn't jump
-->
<!-- โ Problem without dimensions -->
<img src="photo.jpg" alt="Photo" />
<!--
Issues:
- Browser doesn't know how much space to reserve before image loads
- Page content jumps suddenly after image loads
- Causes poor user experience (CLS issue)
-->loading Attribute - Lazy Loading โ
HTML natively supports image lazy loading:
<!-- Lazy loading: Load only when image approaches viewport -->
<img src="below-fold.jpg" alt="Content below the fold" loading="lazy" />
<!-- Eager loading (default) -->
<img src="hero-image.jpg" alt="Hero banner" loading="eager" />
<!-- Best Practices -->
<!-- Important above-the-fold images -->
<img src="logo.png" alt="Company logo" loading="eager" />
<img src="hero.jpg" alt="Hero image" loading="eager" />
<!-- Images below the fold -->
<img src="article-image-1.jpg" alt="Article image" loading="lazy" />
<img src="article-image-2.jpg" alt="Another image" loading="lazy" />Responsive Images โ
picture Element - Art Direction โ
The <picture> element allows providing different images for different scenarios:
<!-- Choose different images based on screen width -->
<picture>
<!-- Mobile: Portrait image -->
<source media="(max-width: 767px)" srcset="image-mobile.jpg" />
<!-- Tablet: Square image -->
<source media="(max-width: 1023px)" srcset="image-tablet.jpg" />
<!-- Desktop: Landscape image -->
<source media="(min-width: 1024px)" srcset="image-desktop.jpg" />
<!-- Fallback image -->
<img src="image-desktop.jpg" alt="Responsive image" />
</picture>
<!-- Real-world case: Different composition for different devices -->
<picture>
<!-- Mobile: Show only product closeup -->
<source media="(max-width: 767px)" srcset="product-closeup.jpg" />
<!-- Tablet: Product + Background -->
<source media="(max-width: 1023px)" srcset="product-medium.jpg" />
<!-- Desktop: Full scene -->
<source media="(min-width: 1024px)" srcset="product-full-scene.jpg" />
<img
src="product-full-scene.jpg"
alt="UltraBook Pro in modern office setting"
/>
</picture>srcset and sizes - Resolution Switching โ
Automatically select the most appropriate image based on screen density and size:
<!-- Based on Device Pixel Ratio (DPR) -->
<img
src="image.jpg"
srcset="image.jpg 1x, [email protected] 2x, [email protected] 3x"
alt="High-resolution image"
/>
<!-- Based on Viewport Width -->
<img
src="image-800.jpg"
srcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1200.jpg 1200w,
image-1600.jpg 1600w
"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px"
alt="Responsive width image"
/>
<!-- Real-world case: Product image -->
<img
src="product-800w.jpg"
srcset="
product-400w.jpg 400w,
product-800w.jpg 800w,
product-1200w.jpg 1200w,
product-1600w.jpg 1600w
"
sizes="(max-width: 500px) 100vw,
(max-width: 900px) 50vw,
33vw"
alt="UltraBook Pro laptop"
width="800"
height="600"
loading="lazy"
/>sizes Attribute Explained:
<!--
sizes tells the browser the display size of the image in different viewports:
- (max-width: 600px) 100vw: When viewport <= 600px, image width = 100% viewport width
- (max-width: 1200px) 50vw: When viewport <= 1200px, image width = 50% viewport width
- 800px: Otherwise, image width = 800px
Browser combines sizes and srcset to automatically select the optimal image
-->
<img
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
33vw"
src="medium.jpg"
alt="Example"
/>
<!--
Scenario 1: User on iPhone (375px width, 2x DPR)
- sizes calculation: 100vw = 375px
- Actual need: 375px ร 2 = 750px
- Browser chooses: medium.jpg (800w)
Scenario 2: User on iPad (768px width, 2x DPR)
- sizes calculation: 50vw = 384px
- Actual need: 384px ร 2 = 768px
- Browser chooses: medium.jpg (800w)
Scenario 3: User on Desktop (1920px width, 1x DPR)
- sizes calculation: 33vw = 633px
- Actual need: 633px ร 1 = 633px
- Browser chooses: medium.jpg (800w)
-->WebP and Modern Formats โ
<!-- Provide multiple formats, browser automatically selects supported one -->
<picture>
<!-- WebP Format: Modern browsers -->
<source type="image/webp" srcset="image.webp" />
<!-- AVIF Format: Newest browsers -->
<source type="image/avif" srcset="image.avif" />
<!-- JPEG Fallback: All browsers -->
<img src="image.jpg" alt="Modern format image" />
</picture>
<!-- Combined with responsive -->
<picture>
<source
type="image/webp"
srcset="image-400.webp 400w, image-800.webp 800w, image-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, 800px"
/>
<source
type="image/jpeg"
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 800px"
/>
<img
src="image-800.jpg"
alt="Optimized modern image"
width="800"
height="600"
loading="lazy"
/>
</picture>figure and figcaption Elements โ
Semantic Image Container โ
<figure> is used to wrap images and their captions:
<!-- Basic Usage -->
<figure>
<img src="architecture.jpg" alt="Modern building with glass facade" />
<figcaption>The new TechCorp headquarters in Seattle</figcaption>
</figure>
<!-- Multiple Images -->
<figure>
<img src="photo1.jpg" alt="Garden in spring" />
<img src="photo2.jpg" alt="Garden in summer" />
<img src="photo3.jpg" alt="Garden in autumn" />
<img src="photo4.jpg" alt="Garden in winter" />
<figcaption>The garden through four seasons</figcaption>
</figure>
<!-- With detailed description -->
<figure>
<img
src="chart-revenue.png"
alt="Line chart showing revenue growth"
width="800"
height="400"
/>
<figcaption>
<strong>Figure 1:</strong> Annual revenue growth 2020-2025. Revenue
increased from $50M to $200M, representing 300% growth.
</figcaption>
</figure>Other Uses of figure โ
<!-- Code Example -->
<figure>
<pre><code>function greet(name) {
return `Hello, ${name}!`;
}</code></pre>
<figcaption>Listing 1: Basic greeting function in JavaScript</figcaption>
</figure>
<!-- Quote -->
<figure>
<blockquote>
<p>
Design is not just what it looks like and feels like. Design is how it
works.
</p>
</blockquote>
<figcaption>โ Steve Jobs, Apple co-founder</figcaption>
</figure>
<!-- Video -->
<figure>
<video src="demo.mp4" controls width="640" height="360">
Your browser doesn't support video.
</video>
<figcaption>Product demonstration video</figcaption>
</figure>Image Format Selection โ
Common Image Formats Comparison โ
<!-- JPEG: Good for photos -->
<img src="photo.jpg" alt="Landscape photo" />
<!--
Pros: Small file size, widely supported
Cons: Lossy compression, no transparency
Use for: Photos, complex images
-->
<!-- PNG: Good for icons, screenshots -->
<img src="icon.png" alt="App icon" />
<!--
Pros: Lossless compression, supports transparency
Cons: Larger file size
Use for: Icons, logos, screenshots, images needing transparent background
-->
<!-- WebP: Modern format -->
<img src="image.webp" alt="Modern format" />
<!--
Pros: Smaller than JPEG/PNG, supports transparency and animation
Cons: Not supported by very old browsers
Use for: Modern Web applications
-->
<!-- SVG: Vector graphics -->
<img src="logo.svg" alt="Company logo" />
<!--
Pros: Infinite scaling without quality loss, small file size
Cons: Not suitable for complex images
Use for: Icons, logos, simple graphics
-->
<!-- GIF: Animation -->
<img src="animation.gif" alt="Loading animation" />
<!--
Pros: Supports animation
Cons: Color limit (256 colors), large file size
Use for: Simple animations (but video or CSS animation is recommended)
-->Best Practice: Format Selection Decision Tree โ
<!-- Decision Process -->
<!--
Need transparent background?
โโ Yes โ Simple graphic?
โ โโ Yes โ SVG or PNG
โ โโ No โ WebP (Fallback PNG)
โโ No โ Photo?
โโ Yes โ WebP (Fallback JPEG)
โโ No โ Icon/Logo?
โโ Yes โ SVG
โโ No โ WebP (Fallback PNG)
-->
<!-- Real-world Examples -->
<!-- 1. Logo (Vector Graphic) -->
<img src="logo.svg" alt="Company logo" width="200" height="50" />
<!-- 2. Product Photo -->
<picture>
<source type="image/webp" srcset="product.webp" />
<img src="product.jpg" alt="Product photo" width="600" height="400" />
</picture>
<!-- 3. Icon with Transparent Background -->
<picture>
<source type="image/webp" srcset="icon.webp" />
<img src="icon.png" alt="Feature icon" width="64" height="64" />
</picture>
<!-- 4. Screenshot -->
<picture>
<source type="image/webp" srcset="screenshot.webp" />
<img src="screenshot.png" alt="App screenshot" width="1200" height="800" />
</picture>SVG Inline Usage โ
Embedding SVG Directly โ
<!-- SVG as img tag -->
<img src="icon.svg" alt="Icon" width="24" height="24" />
<!-- Inline SVG: Controllable with CSS -->
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z"
fill="currentColor"
/>
</svg>
<!-- Accessible SVG -->
<svg width="100" height="100" role="img" aria-labelledby="icon-title">
<title id="icon-title">Settings icon</title>
<circle cx="50" cy="50" r="40" fill="#4CAF50" />
</svg>
<!-- Decorative SVG -->
<svg width="100" height="100" aria-hidden="true" focusable="false">
<circle cx="50" cy="50" r="40" fill="#2196F3" />
</svg>Image Optimization Best Practices โ
Performance Optimization โ
<!-- 1. Use appropriate dimensions -->
<!-- โ Don't load overly large images -->
<img src="huge-5000x5000.jpg" alt="Photo" width="200" height="200" />
<!-- Waste: Downloading 5000x5000 image but only displaying 200x200 -->
<!-- โ
Provide appropriately sized images -->
<img src="optimized-400x400.jpg" alt="Photo" width="200" height="200" />
<!-- 2x display is also clear enough -->
<!-- 2. Use lazy loading -->
<img
src="below-fold.jpg"
alt="Content"
loading="lazy"
width="800"
height="600"
/>
<!-- 3. Use modern formats -->
<picture>
<source type="image/avif" srcset="image.avif" />
<source type="image/webp" srcset="image.webp" />
<img src="image.jpg" alt="Optimized image" width="800" height="600" />
</picture>
<!-- 4. Provide multiple resolutions -->
<img
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 800px"
src="image-800.jpg"
alt="Responsive image"
loading="lazy"
/>
<!-- 5. Preload key images -->
<link rel="preload" as="image" href="hero-image.jpg" />
<!-- 6. Use CDN -->
<img src="https://cdn.example.com/optimized/image.jpg" alt="CDN hosted image" />Accessibility Optimization โ
<!-- 1. Always provide alt text -->
<img src="chart.png" alt="Bar chart showing 50% increase in user engagement" />
<!-- 2. Use empty alt for decorative images -->
<img src="decorative-pattern.png" alt="" aria-hidden="true" />
<!-- 3. Provide detailed description for complex images -->
<figure>
<img
src="complex-diagram.png"
alt="System architecture diagram"
aria-describedby="diagram-description"
/>
<figcaption id="diagram-description">
The diagram shows three main components: Frontend (React), Backend
(Node.js), and Database (PostgreSQL). Arrows indicate data flow between
components...
</figcaption>
</figure>
<!-- 4. Provide accurate description for functional images -->
<!-- โ Not descriptive enough -->
<a href="/search">
<img src="search-icon.png" alt="icon" />
</a>
<!-- โ
Describe function -->
<a href="/search">
<img src="search-icon.png" alt="Search" />
</a>
<!-- Or better: Use aria-label -->
<a href="/search" aria-label="Search the website">
<img src="search-icon.png" alt="" aria-hidden="true" />
</a>Real-World Application Cases โ
E-commerce Product Display โ
<article class="product">
<figure>
<picture>
<!-- WebP Format -->
<source
type="image/webp"
srcset="
product-400.webp 400w,
product-800.webp 800w,
product-1200.webp 1200w
"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
600px"
/>
<!-- JPEG Fallback -->
<source
type="image/jpeg"
srcset="
product-400.jpg 400w,
product-800.jpg 800w,
product-1200.jpg 1200w
"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
600px"
/>
<img
src="product-800.jpg"
alt="UltraBook Pro 15-inch laptop in silver, shown open at 90-degree angle"
width="800"
height="600"
loading="lazy"
/>
</picture>
<figcaption>UltraBook Pro - Starting at $1,299</figcaption>
</figure>
<!-- Thumbnails -->
<div class="thumbnails">
<img src="product-thumb-1.jpg" alt="Front view" width="80" height="60" />
<img src="product-thumb-2.jpg" alt="Side view" width="80" height="60" />
<img
src="product-thumb-3.jpg"
alt="Keyboard detail"
width="80"
height="60"
/>
</div>
</article>Blog Post Images โ
<article>
<header>
<h1>Understanding Web Performance</h1>
<figure class="hero-image">
<picture>
<source media="(max-width: 767px)" srcset="hero-mobile.jpg" />
<source media="(max-width: 1023px)" srcset="hero-tablet.jpg" />
<img
src="hero-desktop.jpg"
alt="Dashboard showing web performance metrics"
width="1200"
height="600"
/>
</picture>
</figure>
</header>
<section>
<p>Web performance is crucial...</p>
<figure>
<img
src="chart-performance.png"
alt="Line chart showing page load time decreasing from 5s to 1.5s"
width="800"
height="400"
loading="lazy"
/>
<figcaption>
<strong>Figure 1:</strong> Performance improvements after optimization
</figcaption>
</figure>
</section>
</article>Responsive Image Gallery โ
<section class="gallery">
<h2>Project Gallery</h2>
<div class="grid">
<figure>
<picture>
<source type="image/webp" srcset="gallery-1.webp" />
<img
src="gallery-1.jpg"
alt="Modern office interior with open floor plan"
width="400"
height="300"
loading="lazy"
/>
</picture>
<figcaption>Office Design Project</figcaption>
</figure>
<figure>
<picture>
<source type="image/webp" srcset="gallery-2.webp" />
<img
src="gallery-2.jpg"
alt="Residential kitchen with marble countertops"
width="400"
height="300"
loading="lazy"
/>
</picture>
<figcaption>Kitchen Renovation</figcaption>
</figure>
<!-- More images... -->
</div>
</section>Common Questions โ
Question 1: When to use img vs background-image? โ
<!-- img: Content-related image -->
<img src="product.jpg" alt="Product photo" />
<!--
Use img when:
- Image is part of the content
- Need SEO
- Need accessibility (alt text)
- Need printing
-->
<!-- CSS background: Decorative image -->
<div style="background-image: url('pattern.png')">Content here</div>
<!--
Use background when:
- Purely decorative
- No SEO needed
- No printing needed
- Need CSS control (position, repeat, etc.)
-->Question 2: How to handle high DPI screens? โ
<!-- Option 1: srcset with x descriptor -->
<img
src="image.jpg"
srcset="image.jpg 1x, [email protected] 2x, [email protected] 3x"
alt="High-res image"
/>
<!-- Option 2: srcset with w descriptor -->
<img
srcset="image-800.jpg 800w, image-1600.jpg 1600w, image-2400.jpg 2400w"
sizes="800px"
src="image-800.jpg"
alt="Responsive high-res"
/>
<!-- Option 3: SVG (Automatically adapts to any resolution) -->
<img src="logo.svg" alt="Logo" width="200" height="50" />Question 3: How to handle image load failures? โ
<!-- JavaScript handling -->
<img
src="image.jpg"
alt="Product photo"
onerror="this.src='placeholder.jpg'; this.onerror=null;"
/>
<!-- Better way: CSS -->
<img src="image.jpg" alt="Product photo" class="fallback-image" />
<style>
.fallback-image {
background: #f0f0f0 url("placeholder.svg") center/contain no-repeat;
min-height: 200px;
}
</style>Summary of Best Practices โ
- Always provide alt text: Except for decorative images, all images need meaningful alt text.
- Specify width and height: Prevent layout shifts, improve CLS (Cumulative Layout Shift).
- Use lazy loading: Use
loading="lazy"for images below the fold. - Responsive images: Use srcset/sizes or picture element to adapt to different devices.
- Modern formats: Prioritize WebP/AVIF, provide JPEG/PNG fallback.
- Optimize dimensions: Don't load images much larger than actual display size.
- Use CDN: Accelerate image loading.
- figure element: Use semantic tags for images with captions.
- SVG icons: Prioritize SVG for simple graphics.
- Performance monitoring: Regularly check image impact on page performance.
By correctly using image and graphic elements, you can create web applications that are visually appealing, high-performing, and accessible, providing an excellent experience for users.