Table of Contents
- Introduction to Web Media
- Image Formats and Optimization
- HTML Image Elements
- CSS Image Styling
- Responsive Images
- Background Images
- Image Effects and Filters
- Video and Audio
- SVG and Icons
- Image Galleries
- Performance Optimization
- Accessibility
- Practical Examples
- Best Practices
Introduction to Web Media
Images and media are essential components of modern web design. They enhance user experience, convey information visually, and make websites more engaging. This comprehensive guide covers everything from basic image insertion to advanced techniques for optimizing and styling media content.
Why Images Matter
- Visual Communication: Images convey information faster than text
- User Engagement: Visual content increases time on site
- Brand Identity: Images help establish brand personality
- SEO Benefits: Properly optimized images improve search rankings
- Accessibility: Alt text makes content accessible to all users
Image Formats and Optimization
Common Image Formats
<!-- Comparison of image formats --> <table> <tr> <th>Format</th> <th>Best For</th> <th>Pros</th> <th>Cons</th> </tr> <tr> <td>JPEG/JPG</td> <td>Photographs, complex images</td> <td>Small file size, 16.7M colors</td> <td>No transparency, lossy compression</td> </tr> <tr> <td>PNG</td> <td>Logos, graphics, screenshots</td> <td>Transparency, lossless</td> <td>Larger file size</td> </tr> <tr> <td>GIF</td> <td>Simple animations</td> <td>Animation support</td> <td>Limited colors (256), large files</td> </tr> <tr> <td>WebP</td> <td>Web images (modern)</td> <td>Small size, transparency, animation</td> <td>Browser support (good but not universal)</td> </tr> <tr> <td>AVIF</td> <td>Next-gen web images</td> <td>Excellent compression, HDR support</td> <td>Limited browser support</td> </tr> <tr> <td>SVG</td> <td>Icons, logos, illustrations</td> <td>Scalable, small size, editable</td> <td>Not for complex images/photos</td> </tr> </table>
Image Optimization Tips
/* CSS for image optimization demo */
.optimization-demo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
}
.format-card {
background: white;
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.format-card img {
width: 100%;
height: auto;
border-radius: 4px;
}
.file-size {
font-family: monospace;
background: #f0f0f0;
padding: 5px 10px;
border-radius: 4px;
display: inline-block;
margin: 10px 0;
}
HTML Image Elements
Basic Image Insertion
<!-- Basic image tag --> <img src="image.jpg" alt="Description of image"> <!-- Image with dimensions --> <img src="photo.jpg" alt="Beautiful landscape" width="800" height="600"> <!-- Image with title (tooltip) --> <img src="logo.png" alt="Company Logo" title="Click to go home"> <!-- Image as a link --> <a href="https://example.com"> <img src="button.png" alt="Click me"> </a>
Figure and Figcaption
<!-- Figure with caption --> <figure> <img src="sunset.jpg" alt="Beautiful sunset over mountains"> <figcaption>Sunset at Grand Canyon, Arizona - 2024</figcaption> </figure> <!-- Multiple images in one figure --> <figure> <img src="cat1.jpg" alt="Cat sleeping"> <img src="cat2.jpg" alt="Cat playing"> <img src="cat3.jpg" alt="Cat eating"> <figcaption>My cat's daily activities</figcaption> </figure>
Picture Element for Art Direction
<!-- Picture element for different viewports --> <picture> <source media="(max-width: 600px)" srcset="image-mobile.jpg"> <source media="(max-width: 1200px)" srcset="image-tablet.jpg"> <source media="(min-width: 1201px)" srcset="image-desktop.jpg"> <img src="image-fallback.jpg" alt="Description"> </picture> <!-- Picture with different formats --> <picture> <source type="image/avif" srcset="image.avif"> <source type="image/webp" srcset="image.webp"> <source type="image/jpeg" srcset="image.jpg"> <img src="image.jpg" alt="Description" loading="lazy"> </picture>
Responsive Images with srcset
<!-- srcset for different resolutions --> <img src="small.jpg" srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 2000w" sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw" alt="Responsive image example"> <!-- With x descriptors for device pixel ratio --> <img src="1x.jpg" srcset="1x.jpg 1x, 2x.jpg 2x, 3x.jpg 3x" alt="High DPI display support"> <!-- Complete responsive image example --> <img src="hero-small.jpg" srcset="hero-small.jpg 480w, hero-medium.jpg 768w, hero-large.jpg 1024w, hero-xlarge.jpg 1920w" sizes="(max-width: 480px) 100vw, (max-width: 768px) 100vw, (max-width: 1024px) 100vw, 1920px" alt="Hero image" loading="lazy" decoding="async">
CSS Image Styling
Basic Image Styling
/* Basic image styling */
img {
max-width: 100%;
height: auto;
display: block;
}
/* Rounded images */
.rounded {
border-radius: 8px;
}
/* Circular images */
.circular {
border-radius: 50%;
aspect-ratio: 1 / 1;
object-fit: cover;
}
/* Image borders */
.bordered {
border: 2px solid #333;
padding: 5px;
background: white;
}
/* Image shadows */
.shadow {
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.shadow-hover:hover {
box-shadow: 0 8px 16px rgba(0,0,0,0.3);
transition: box-shadow 0.3s;
}
/* Image alignment */
.center {
display: block;
margin-left: auto;
margin-right: auto;
}
.float-left {
float: left;
margin-right: 20px;
margin-bottom: 10px;
}
.float-right {
float: right;
margin-left: 20px;
margin-bottom: 10px;
}
Object-Fit and Object-Position
/* Object-fit examples */
.cover {
width: 300px;
height: 300px;
object-fit: cover; /* Covers entire area, may crop */
}
.contain {
width: 300px;
height: 300px;
object-fit: contain; /* Fits entirely, may have letterbox */
}
.fill {
width: 300px;
height: 300px;
object-fit: fill; /* Stretches to fit */
}
.scale-down {
width: 300px;
height: 300px;
object-fit: scale-down; /* Like contain or none, whichever smaller */
}
.none {
width: 300px;
height: 300px;
object-fit: none; /* Original size */
}
/* Object-position */
.focus-top {
width: 300px;
height: 300px;
object-fit: cover;
object-position: top; /* Focus on top of image */
}
.focus-bottom {
object-position: bottom;
}
.focus-left {
object-position: left;
}
.focus-right {
object-position: right;
}
.custom-focus {
object-position: 25% 75%; /* Custom focus point */
}
Image Hover Effects
/* Image gallery with hover effects */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
padding: 20px;
}
.gallery-item {
position: relative;
overflow: hidden;
border-radius: 8px;
cursor: pointer;
}
.gallery-item img {
width: 100%;
height: 300px;
object-fit: cover;
transition: transform 0.5s;
}
/* Scale on hover */
.gallery-item:hover img {
transform: scale(1.1);
}
/* Overlay effect */
.gallery-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
color: white;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s;
}
.gallery-item:hover .gallery-overlay {
opacity: 1;
}
/* Grayscale hover */
.grayscale-hover {
filter: grayscale(100%);
transition: filter 0.3s;
}
.grayscale-hover:hover {
filter: grayscale(0%);
}
/* Sepia hover */
.sepia-hover {
filter: sepia(0%);
transition: filter 0.3s;
}
.sepia-hover:hover {
filter: sepia(100%);
}
/* Blur hover */
.blur-hover {
filter: blur(0);
transition: filter 0.3s;
}
.blur-hover:hover {
filter: blur(3px);
}
/* Brightness hover */
.brightness-hover {
filter: brightness(1);
transition: filter 0.3s;
}
.brightness-hover:hover {
filter: brightness(1.2);
}
/* Rotate and scale */
.rotate-hover {
transition: transform 0.5s;
}
.rotate-hover:hover {
transform: rotate(5deg) scale(1.05);
}
Background Images
CSS Background Properties
/* Basic background image */
.element {
background-image: url('image.jpg');
}
/* Background repeat */
.no-repeat {
background-repeat: no-repeat;
}
.repeat-x {
background-repeat: repeat-x; /* Horizontal repeat */
}
.repeat-y {
background-repeat: repeat-y; /* Vertical repeat */
}
.repeat {
background-repeat: repeat; /* Default - both directions */
}
/* Background position */
.position-center {
background-position: center;
}
.position-top {
background-position: top;
}
.position-bottom {
background-position: bottom;
}
.position-left {
background-position: left;
}
.position-right {
background-position: right;
}
.custom-position {
background-position: 25% 75%;
}
/* Background size */
.cover {
background-size: cover; /* Cover entire area */
}
.contain {
background-size: contain; /* Fit entirely */
}
.auto {
background-size: auto; /* Original size */
}
.custom-size {
background-size: 50% 50%; /* Percentage */
background-size: 200px 100px; /* Specific dimensions */
}
/* Background attachment */
.fixed {
background-attachment: fixed; /* Parallax effect */
}
.scroll {
background-attachment: scroll; /* Default */
}
.local {
background-attachment: local; /* Scrolls with content */
}
/* Background shorthand */
.hero {
background: #333 url('hero.jpg') no-repeat center/cover fixed;
}
Hero Sections with Background Images
<!-- Hero section with background image --> <section class="hero"> <div class="hero-content"> <h1>Welcome to Our Site</h1> <p>Discover amazing experiences</p> <a href="#" class="btn">Learn More</a> </div> </section>
/* Hero section styles */
.hero {
position: relative;
height: 100vh;
background-image: url('hero-bg.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed;
color: white;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
/* Overlay for better text readability */
.hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
}
.hero-content {
position: relative;
z-index: 1;
max-width: 800px;
padding: 20px;
}
.hero h1 {
font-size: 3.5rem;
margin-bottom: 1rem;
animation: fadeInUp 1s ease;
}
.hero p {
font-size: 1.25rem;
margin-bottom: 2rem;
animation: fadeInUp 1s ease 0.2s both;
}
.hero .btn {
display: inline-block;
padding: 15px 30px;
background: #ff6b6b;
color: white;
text-decoration: none;
border-radius: 5px;
transition: background 0.3s;
animation: fadeInUp 1s ease 0.4s both;
}
.hero .btn:hover {
background: #ff5252;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Multiple Backgrounds
/* Multiple background images */
.multiple-bg {
width: 100%;
height: 500px;
background-image:
url('overlay.png'),
url('pattern.png'),
linear-gradient(to bottom, rgba(0,0,0,0.5), rgba(0,0,0,0.5)),
url('main-bg.jpg');
background-position:
center,
repeat,
center,
center;
background-repeat:
no-repeat,
repeat,
no-repeat,
no-repeat;
background-size:
contain,
auto,
cover,
cover;
}
Parallax Scrolling
/* Simple parallax effect */
.parallax {
background-image: url('parallax-bg.jpg');
min-height: 500px;
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* Parallax section */
.parallax-section {
position: relative;
height: 100vh;
overflow: hidden;
}
.parallax-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 120%; /* Extra height for movement */
background-image: url('parallax-bg.jpg');
background-size: cover;
background-position: center;
transform: translateY(0);
will-change: transform;
z-index: -1;
}
.parallax-content {
position: relative;
z-index: 1;
color: white;
text-align: center;
padding: 200px 20px;
}
/* JavaScript would update transform based on scroll */
Image Effects and Filters
CSS Filters
/* CSS filter effects */
.filter-demo img {
width: 300px;
height: 300px;
object-fit: cover;
margin: 10px;
}
.blur {
filter: blur(5px);
}
.brightness {
filter: brightness(150%);
}
.contrast {
filter: contrast(200%);
}
.grayscale {
filter: grayscale(100%);
}
.hue-rotate {
filter: hue-rotate(90deg);
}
.invert {
filter: invert(100%);
}
.opacity {
filter: opacity(50%);
}
.saturate {
filter: saturate(200%);
}
.sepia {
filter: sepia(100%);
}
.drop-shadow {
filter: drop-shadow(5px 5px 10px rgba(0,0,0,0.5));
}
/* Multiple filters */
.multiple-filters {
filter: brightness(120%) contrast(110%) saturate(120%) sepia(20%);
}
/* Filter transitions */
.filter-transition {
transition: filter 0.3s;
}
.filter-transition:hover {
filter: brightness(120%) contrast(110%);
}
Blend Modes
/* Background blend modes */
.bg-blend {
background-image: url('image1.jpg'), url('image2.jpg');
background-blend-mode: multiply; /* screen, overlay, darken, lighten, etc. */
background-size: cover;
height: 400px;
}
/* Mix blend modes (element blends with background) */
.mix-blend {
position: relative;
}
.mix-blend h1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 5rem;
mix-blend-mode: difference;
text-align: center;
}
/* Blend mode examples */
.blend-examples {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.blend-card {
position: relative;
height: 200px;
overflow: hidden;
}
.blend-card img {
width: 100%;
height: 100%;
object-fit: cover;
}
.blend-card .overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
mix-blend-mode: overlay;
}
/* Different blend modes */
.multiply { mix-blend-mode: multiply; }
.screen { mix-blend-mode: screen; }
.overlay { mix-blend-mode: overlay; }
.darken { mix-blend-mode: darken; }
.lighten { mix-blend-mode: lighten; }
.color-dodge { mix-blend-mode: color-dodge; }
.color-burn { mix-blend-mode: color-burn; }
.hard-light { mix-blend-mode: hard-light; }
.soft-light { mix-blend-mode: soft-light; }
.difference { mix-blend-mode: difference; }
.exclusion { mix-blend-mode: exclusion; }
.hue { mix-blend-mode: hue; }
.saturation { mix-blend-mode: saturation; }
.color { mix-blend-mode: color; }
.luminosity { mix-blend-mode: luminosity; }
Clip Path and Masking
/* Clip path examples */
.clip-circle {
clip-path: circle(50%);
width: 300px;
height: 300px;
}
.clip-polygon {
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
width: 300px;
height: 300px;
}
.clip-ellipse {
clip-path: ellipse(25% 40% at 50% 50%);
width: 300px;
height: 300px;
}
.clip-inset {
clip-path: inset(10% 20% 10% 20%);
width: 300px;
height: 300px;
}
.clip-path-hover {
transition: clip-path 0.3s;
}
.clip-path-hover:hover {
clip-path: circle(50%);
}
/* CSS masks */
.mask-image {
mask-image: linear-gradient(to bottom, transparent, black);
mask-size: cover;
}
.mask-url {
mask-image: url('mask.png');
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
}
Video and Audio
HTML5 Video
<!-- Basic video --> <video src="video.mp4" controls width="640" height="360"> Your browser doesn't support video. </video> <!-- Video with multiple sources --> <video controls width="640" height="360" poster="thumbnail.jpg"> <source src="video.mp4" type="video/mp4"> <source src="video.webm" type="video/webm"> <source src="video.ogv" type="video/ogg"> <track kind="captions" src="captions.vtt" srclang="en" label="English"> <track kind="subtitles" src="subtitles.vtt" srclang="es" label="Spanish"> Your browser doesn't support video. </video> <!-- Video attributes --> <video controls autoplay loop muted preload="auto" playsinline> <source src="background-video.mp4" type="video/mp4"> </video> <!-- Video with custom controls --> <div class="video-container"> <video id="myVideo" width="640" height="360"> <source src="video.mp4" type="video/mp4"> </video> <div class="video-controls"> <button onclick="playPause()">Play/Pause</button> <button onclick="stopVideo()">Stop</button> <input type="range" id="seekBar" value="0"> <span id="currentTime">0:00</span> / <span id="duration">0:00</span> <button onclick="muteVolume()">Mute</button> <input type="range" id="volumeBar" min="0" max="1" step="0.1" value="1"> <button onclick="toggleFullscreen()">Fullscreen</button> </div> </div>
Video Styling with CSS
/* Video container */
.video-wrapper {
position: relative;
width: 100%;
max-width: 800px;
margin: 0 auto;
}
/* Responsive video */
video {
width: 100%;
height: auto;
display: block;
}
/* Video with rounded corners */
video {
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
/* Background video */
.background-video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: -1;
}
/* Video overlay */
.video-overlay {
position: relative;
}
.video-overlay::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.7));
pointer-events: none;
}
/* Custom play button */
.video-container {
position: relative;
cursor: pointer;
}
.play-button {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80px;
height: 80px;
background: rgba(255,255,255,0.8);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
color: #333;
transition: all 0.3s;
opacity: 0.8;
}
.video-container:hover .play-button {
opacity: 1;
transform: translate(-50%, -50%) scale(1.1);
background: white;
}
HTML5 Audio
<!-- Basic audio -->
<audio src="audio.mp3" controls>
Your browser doesn't support audio.
</audio>
<!-- Audio with multiple sources -->
<audio controls preload="auto">
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
<source src="audio.wav" type="audio/wav">
Your browser doesn't support audio.
</audio>
<!-- Audio with attributes -->
<audio controls autoplay loop muted>
<source src="background-music.mp3" type="audio/mpeg">
</audio>
<!-- Audio player with playlist -->
<div class="audio-player">
<audio id="audioPlayer" controls>
<source src="track1.mp3" type="audio/mpeg">
</audio>
<div class="playlist">
<ul>
<li onclick="playTrack('track1.mp3')">Track 1 - Song Title</li>
<li onclick="playTrack('track2.mp3')">Track 2 - Another Song</li>
<li onclick="playTrack('track3.mp3')">Track 3 - Final Track</li>
</ul>
</div>
</div>
YouTube and External Video Embeds
<!-- YouTube embed -->
<div class="video-responsive">
<iframe width="560" height="315"
src="https://www.youtube.com/embed/VIDEO_ID"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</div>
<!-- YouTube with parameters -->
<iframe width="560" height="315"
src="https://www.youtube.com/embed/VIDEO_ID?autoplay=1&mute=1&loop=1&playlist=VIDEO_ID"
frameborder="0"
allowfullscreen>
</iframe>
<!-- Vimeo embed -->
<div class="video-responsive">
<iframe src="https://player.vimeo.com/video/VIDEO_ID"
width="640"
height="360"
frameborder="0"
allow="autoplay; fullscreen"
allowfullscreen>
</iframe>
</div>
<!-- Responsive video container -->
<style>
.video-responsive {
position: relative;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
height: 0;
overflow: hidden;
max-width: 100%;
}
.video-responsive iframe,
.video-responsive object,
.video-responsive embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
SVG and Icons
Inline SVG
<!-- Inline SVG --> <svg width="100" height="100" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" fill="red" stroke="black" stroke-width="3"/> <rect x="20" y="20" width="60" height="60" fill="blue" opacity="0.5"/> <line x1="10" y1="10" x2="90" y2="90" stroke="green" stroke-width="2"/> <text x="30" y="60" fill="white">SVG</text> </svg> <!-- SVG with CSS classes --> <svg class="icon" viewBox="0 0 24 24"> <path class="icon-path" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/> </svg>
SVG Sprites
<!-- SVG sprite definition (usually hidden) --> <svg style="display: none;"> <symbol id="icon-home" viewBox="0 0 24 24"> <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/> </symbol> <symbol id="icon-user" viewBox="0 0 24 24"> <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> </symbol> <symbol id="icon-settings" viewBox="0 0 24 24"> <path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94 0 .31.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.57 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/> </symbol> </svg> <!-- Using SVG sprite --> <svg class="icon"><use xlink:href="#icon-home"></use></svg> <svg class="icon"><use xlink:href="#icon-user"></use></svg> <svg class="icon"><use xlink:href="#icon-settings"></use></svg>
Icon Fonts (Font Awesome)
<!-- Font Awesome (CDN) --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <!-- Basic icons --> <i class="fas fa-home"></i> Home <i class="fas fa-user"></i> Profile <i class="fas fa-cog"></i> Settings <!-- Icon sizes --> <i class="fas fa-camera fa-xs"></i> <i class="fas fa-camera fa-sm"></i> <i class="fas fa-camera fa-lg"></i> <i class="fas fa-camera fa-2x"></i> <i class="fas fa-camera fa-3x"></i> <i class="fas fa-camera fa-5x"></i> <i class="fas fa-camera fa-7x"></i> <i class="fas fa-camera fa-10x"></i> <!-- Fixed width icons --> <i class="fas fa-home fa-fw"></i> <i class="fas fa-user fa-fw"></i> <i class="fas fa-cog fa-fw"></i> <!-- List icons --> <ul class="fa-ul"> <li><span class="fa-li"><i class="fas fa-check-square"></i></span>List item 1</li> <li><span class="fa-li"><i class="fas fa-check-square"></i></span>List item 2</li> <li><span class="fa-li"><i class="fas fa-spinner fa-pulse"></i></span>List item 3</li> </ul> <!-- Rotating icons --> <i class="fas fa-sync-alt fa-spin"></i> <i class="fas fa-circle-notch fa-spin"></i> <i class="fas fa-cog fa-pulse"></i> <!-- Stacked icons --> <span class="fa-stack fa-2x"> <i class="fas fa-circle fa-stack-2x"></i> <i class="fas fa-flag fa-stack-1x fa-inverse"></i> </span> <!-- Social media icons --> <a href="#"><i class="fab fa-facebook"></i></a> <a href="#"><i class="fab fa-twitter"></i></a> <a href="#"><i class="fab fa-instagram"></i></a> <a href="#"><i class="fab fa-linkedin"></i></a> <a href="#"><i class="fab fa-github"></i></a>
Styling Icons with CSS
/* Icon styling */
.icon {
width: 24px;
height: 24px;
fill: currentColor; /* Inherits text color */
transition: fill 0.3s;
}
.icon:hover {
fill: #ff6b6b;
}
/* Icon button */
.icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
background: #f0f0f0;
transition: all 0.3s;
cursor: pointer;
}
.icon-button:hover {
background: #e0e0e0;
transform: scale(1.1);
}
/* Social icon strip */
.social-strip {
display: flex;
gap: 15px;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 10px;
}
.social-strip a {
color: white;
font-size: 24px;
transition: transform 0.3s;
}
.social-strip a:hover {
transform: translateY(-3px);
}
Image Galleries
Basic CSS Grid Gallery
<div class="gallery"> <div class="gallery-item"> <img src="image1.jpg" alt="Description 1"> <div class="gallery-caption">Caption 1</div> </div> <div class="gallery-item"> <img src="image2.jpg" alt="Description 2"> <div class="gallery-caption">Caption 2</div> </div> <!-- More items --> </div>
/* Gallery grid */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
}
.gallery-item {
position: relative;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.gallery-item img {
width: 100%;
height: 300px;
object-fit: cover;
display: block;
transition: transform 0.5s;
}
.gallery-item:hover img {
transform: scale(1.1);
}
.gallery-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
color: white;
padding: 20px;
transform: translateY(100%);
transition: transform 0.3s;
}
.gallery-item:hover .gallery-caption {
transform: translateY(0);
}
Masonry Gallery
<div class="masonry"> <div class="masonry-item"> <img src="image1.jpg" alt="Tall image"> </div> <div class="masonry-item"> <img src="image2.jpg" alt="Wide image"> </div> <div class="masonry-item"> <img src="image3.jpg" alt="Square image"> </div> <!-- More items --> </div>
/* Masonry layout with CSS columns */
.masonry {
column-count: 4;
column-gap: 20px;
padding: 20px;
}
.masonry-item {
break-inside: avoid;
margin-bottom: 20px;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.masonry-item img {
width: 100%;
height: auto;
display: block;
}
/* Responsive columns */
@media (max-width: 1200px) {
.masonry { column-count: 3; }
}
@media (max-width: 800px) {
.masonry { column-count: 2; }
}
@media (max-width: 500px) {
.masonry { column-count: 1; }
}
Lightbox Gallery
<!-- Lightbox HTML --> <div class="lightbox-gallery"> <a href="#img1"> <img src="thumb1.jpg" alt="Thumbnail 1"> </a> <a href="#img2"> <img src="thumb2.jpg" alt="Thumbnail 2"> </a> </div> <!-- Lightbox overlays --> <div class="lightbox" id="img1"> <a href="#" class="close">×</a> <img src="full1.jpg" alt="Full image 1"> <a href="#img2" class="prev">❮</a> <a href="#img2" class="next">❯</a> </div> <div class="lightbox" id="img2"> <a href="#" class="close">×</a> <img src="full2.jpg" alt="Full image 2"> <a href="#img1" class="prev">❮</a> <a href="#img1" class="next">❯</a> </div>
/* Lightbox styles */
.lightbox {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.9);
z-index: 1000;
text-align: center;
}
.lightbox:target {
display: flex;
align-items: center;
justify-content: center;
}
.lightbox img {
max-width: 90%;
max-height: 90%;
object-fit: contain;
border: 3px solid white;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
}
.lightbox .close {
position: absolute;
top: 20px;
right: 40px;
color: white;
font-size: 40px;
text-decoration: none;
transition: color 0.3s;
}
.lightbox .close:hover {
color: #ff6b6b;
}
.lightbox .prev,
.lightbox .next {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: white;
font-size: 50px;
text-decoration: none;
padding: 20px;
transition: background 0.3s;
}
.lightbox .prev {
left: 20px;
}
.lightbox .next {
right: 20px;
}
.lightbox .prev:hover,
.lightbox .next:hover {
background: rgba(255,255,255,0.1);
border-radius: 50%;
}
Carousel/Slider Gallery
<div class="carousel"> <div class="carousel-container"> <div class="carousel-slide"> <img src="slide1.jpg" alt="Slide 1"> </div> <div class="carousel-slide"> <img src="slide2.jpg" alt="Slide 2"> </div> <div class="carousel-slide"> <img src="slide3.jpg" alt="Slide 3"> </div> </div> <button class="carousel-prev">❮</button> <button class="carousel-next">❯</button> <div class="carousel-dots"> <span class="dot active"></span> <span class="dot"></span> <span class="dot"></span> </div> </div>
/* Carousel styles */
.carousel {
position: relative;
max-width: 800px;
margin: 0 auto;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.carousel-container {
display: flex;
transition: transform 0.5s ease;
}
.carousel-slide {
min-width: 100%;
}
.carousel-slide img {
width: 100%;
height: 400px;
object-fit: cover;
display: block;
}
.carousel-prev,
.carousel-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 15px 20px;
cursor: pointer;
font-size: 18px;
transition: background 0.3s;
border-radius: 5px;
}
.carousel-prev:hover,
.carousel-next:hover {
background: rgba(0,0,0,0.8);
}
.carousel-prev {
left: 10px;
}
.carousel-next {
right: 10px;
}
.carousel-dots {
text-align: center;
padding: 10px;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
}
.dot {
display: inline-block;
width: 10px;
height: 10px;
margin: 0 5px;
background: rgba(255,255,255,0.5);
border-radius: 50%;
cursor: pointer;
transition: background 0.3s;
}
.dot.active,
.dot:hover {
background: white;
}
Performance Optimization
Lazy Loading
<!-- Native lazy loading -->
<img src="image.jpg" loading="lazy" alt="Lazy loaded image">
<!-- With fallback for older browsers -->
<img src="placeholder.jpg"
data-src="actual-image.jpg"
class="lazy"
alt="Lazy loaded image">
<!-- JavaScript for lazy loading (Intersection Observer) -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const lazyImages = document.querySelectorAll('img.lazy');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
imageObserver.unobserve(img);
}
});
});
lazyImages.forEach(function(img) {
imageObserver.observe(img);
});
} else {
// Fallback for older browsers
lazyImages.forEach(function(img) {
img.src = img.dataset.src;
});
}
});
</script>
Responsive Image Loading
<!-- Modern responsive image loading --> <img srcset="image-480w.jpg 480w, image-768w.jpg 768w, image-1024w.jpg 1024w, image-1920w.jpg 1920w" sizes="(max-width: 480px) 100vw, (max-width: 768px) 100vw, (max-width: 1024px) 100vw, 1920px" src="image-1920w.jpg" alt="Responsive image" loading="lazy"> <!-- Picture element with art direction --> <picture> <!-- Mobile portrait --> <source media="(max-width: 480px) and (orientation: portrait)" srcset="image-mobile-portrait.jpg"> <!-- Mobile landscape --> <source media="(max-width: 768px) and (orientation: landscape)" srcset="image-mobile-landscape.jpg"> <!-- Tablet --> <source media="(max-width: 1024px)" srcset="image-tablet.jpg"> <!-- Desktop --> <source media="(min-width: 1025px)" srcset="image-desktop.jpg"> <!-- Fallback --> <img src="image-fallback.jpg" alt="Art directed image"> </picture>
Image Compression Tips
/* CSS for image optimization demo */
.optimization-tips {
background: #f9f9f9;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
}
.tip-card {
background: white;
padding: 15px;
margin: 10px 0;
border-left: 4px solid #4ecdc4;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
}
.tip-title {
font-weight: bold;
color: #2c3e50;
margin-bottom: 5px;
}
.tip-content {
color: #666;
line-height: 1.6;
}
<!-- Image optimization tips in HTML --> <div class="optimization-tips"> <h3>Image Optimization Checklist</h3> <div class="tip-card"> <div class="tip-title">✓ Choose the right format</div> <div class="tip-content">Use WebP/AVIF for web, JPEG for photos, PNG for transparency, SVG for icons</div> </div> <div class="tip-card"> <div class="tip-title">✓ Compress images</div> <div class="tip-content">Use tools like ImageOptim, TinyPNG, or Squoosh to reduce file size</div> </div> <div class="tip-card"> <div class="tip-title">✓ Use responsive images</div> <div class="tip-content">Serve different sizes for different devices using srcset and sizes</div> </div> <div class="tip-card"> <div class="tip-title">✓ Lazy load</div> <div class="tip-content">Load images only when they're about to enter the viewport</div> </div> <div class="tip-card"> <div class="tip-title">✓ Set dimensions</div> <div class="tip-content">Specify width and height to prevent layout shifts (CLS)</div> </div> <div class="tip-card"> <div class="tip-title">✓ Use CDN</div> <div class="tip-content">Content Delivery Networks optimize and serve images faster</div> </div> </div>
Accessibility
Alt Text Best Practices
<!-- Good alt text examples --> <!-- Decorative image - empty alt --> <img src="decorative-line.png" alt="" role="presentation"> <!-- Informative image --> <img src="chart.png" alt="Bar chart showing sales growth from 100k to 500k over 2024"> <!-- Functional image (link) --> <a href="/home"> <img src="logo.png" alt="Return to homepage"> </a> <!-- Complex image with long description --> <img src="infographic.png" alt="Infographic about web accessibility" longdesc="description.html"> <!-- Image with caption already explains --> <figure> <img src="team-photo.jpg" alt=""> <figcaption>Our development team at the 2024 conference</figcaption> </figure> <!-- Icons with text --> <button> <img src="print-icon.png" alt=""> Print document </button> <!-- Icons without text --> <button aria-label="Print"> <img src="print-icon.png" alt=""> </button>
ARIA for Images
<!-- ARIA roles for complex images --> <div role="img" aria-label="Company logo: Blue circle with white wave"> <svg><!-- SVG content --></svg> </div> <!-- Image with ARIA describedby --> <img src="diagram.jpg" alt="Network architecture diagram" aria-describedby="diagram-desc"> <div id="diagram-desc" hidden> The diagram shows a load balancer distributing traffic to three application servers connected to a database cluster. </div> <!-- Image button with ARIA --> <button aria-label="Close dialog"> <img src="close-icon.png" alt=""> </button>
CSS for Accessibility
/* Hide images in high contrast mode */
@media (prefers-contrast: high) {
.decorative-image {
display: none;
}
}
/* Respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* Focus indicators for interactive images */
a:focus img {
outline: 3px solid #4A90E2;
outline-offset: 2px;
}
/* High contrast focus */
@media (prefers-contrast: high) {
a:focus img {
outline: 3px solid black;
}
}
Practical Examples
Example 1: Hero Section with Video Background
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Hero Section</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
.hero {
position: relative;
height: 100vh;
overflow: hidden;
color: white;
}
.hero-video {
position: absolute;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translateX(-50%) translateY(-50%);
object-fit: cover;
z-index: -1;
}
.hero-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.4) 100%);
z-index: 0;
}
.hero-content {
position: relative;
z-index: 1;
max-width: 800px;
margin: 0 auto;
padding: 20px;
text-align: center;
top: 50%;
transform: translateY(-50%);
}
.hero h1 {
font-size: clamp(2rem, 5vw, 4rem);
margin-bottom: 1rem;
animation: fadeInDown 1s ease;
}
.hero p {
font-size: clamp(1rem, 2vw, 1.25rem);
margin-bottom: 2rem;
opacity: 0.9;
animation: fadeInUp 1s ease 0.2s both;
}
.hero-buttons {
animation: fadeInUp 1s ease 0.4s both;
}
.btn {
display: inline-block;
padding: 12px 30px;
margin: 0 10px;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
transition: all 0.3s;
}
.btn-primary {
background: #ff6b6b;
color: white;
}
.btn-primary:hover {
background: #ff5252;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(255,107,107,0.4);
}
.btn-outline {
border: 2px solid white;
color: white;
}
.btn-outline:hover {
background: white;
color: #333;
transform: translateY(-2px);
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 768px) {
.hero-content {
padding: 10px;
}
.btn {
display: block;
margin: 10px auto;
max-width: 200px;
}
}
</style>
</head>
<body>
<div class="hero">
<video class="hero-video" autoplay loop muted playsinline>
<source src="hero-video.mp4" type="video/mp4">
<source src="hero-video.webm" type="video/webm">
Your browser doesn't support video.
</video>
<div class="hero-overlay"></div>
<div class="hero-content">
<h1>Welcome to Our World</h1>
<p>Experience the beauty of nature through our lens. Join us on an unforgettable journey through stunning landscapes and breathtaking moments.</p>
<div class="hero-buttons">
<a href="#" class="btn btn-primary">Get Started</a>
<a href="#" class="btn btn-outline">Learn More</a>
</div>
</div>
</div>
</body>
</html>
Example 2: Responsive Image Gallery with Lightbox
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Gallery</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', sans-serif;
background: #f5f5f5;
padding: 20px;
}
.gallery-container {
max-width: 1200px;
margin: 0 auto;
}
.gallery-title {
text-align: center;
margin-bottom: 30px;
color: #333;
}
.gallery-title h1 {
font-size: 2.5rem;
margin-bottom: 10px;
}
.gallery-title p {
color: #666;
}
/* Gallery grid */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.gallery-item {
position: relative;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
cursor: pointer;
transition: transform 0.3s, box-shadow 0.3s;
}
.gallery-item:hover {
transform: translateY(-5px);
box-shadow: 0 8px 20px rgba(0,0,0,0.15);
}
.gallery-item img {
width: 100%;
height: 250px;
object-fit: cover;
display: block;
transition: transform 0.5s;
}
.gallery-item:hover img {
transform: scale(1.1);
}
.gallery-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.8), transparent);
color: white;
padding: 20px;
transform: translateY(100%);
transition: transform 0.3s;
}
.gallery-item:hover .gallery-caption {
transform: translateY(0);
}
/* Lightbox */
.lightbox {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.95);
z-index: 1000;
opacity: 0;
transition: opacity 0.3s;
}
.lightbox.active {
display: flex;
opacity: 1;
}
.lightbox-content {
position: relative;
max-width: 90%;
max-height: 90%;
margin: auto;
}
.lightbox-content img {
max-width: 100%;
max-height: 90vh;
object-fit: contain;
border: 3px solid white;
box-shadow: 0 0 30px rgba(0,0,0,0.5);
}
.lightbox-caption {
position: absolute;
bottom: -40px;
left: 0;
right: 0;
text-align: center;
color: white;
font-size: 1rem;
}
.lightbox-close {
position: absolute;
top: 20px;
right: 20px;
color: white;
font-size: 40px;
cursor: pointer;
transition: color 0.3s;
z-index: 1001;
}
.lightbox-close:hover {
color: #ff6b6b;
}
.lightbox-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: white;
font-size: 50px;
cursor: pointer;
padding: 20px;
transition: background 0.3s;
z-index: 1001;
}
.lightbox-nav:hover {
background: rgba(255,255,255,0.1);
border-radius: 50%;
}
.lightbox-prev {
left: 20px;
}
.lightbox-next {
right: 20px;
}
/* Filter buttons */
.filter-buttons {
text-align: center;
margin: 30px 0;
}
.filter-btn {
display: inline-block;
padding: 8px 20px;
margin: 0 5px;
border: none;
background: #e0e0e0;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s;
}
.filter-btn.active {
background: #333;
color: white;
}
.filter-btn:hover {
background: #666;
color: white;
}
/* Loading animation */
.loading {
text-align: center;
padding: 50px;
display: none;
}
.loading.active {
display: block;
}
.loading-spinner {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (max-width: 768px) {
.gallery {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.lightbox-nav {
font-size: 30px;
padding: 10px;
}
.lightbox-close {
font-size: 30px;
}
}
</style>
</head>
<body>
<div class="gallery-container">
<div class="gallery-title">
<h1>My Photo Gallery</h1>
<p>Click on any image to view in lightbox</p>
</div>
<div class="filter-buttons">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="nature">Nature</button>
<button class="filter-btn" data-filter="city">City</button>
<button class="filter-btn" data-filter="people">People</button>
</div>
<div class="gallery" id="gallery">
<!-- Gallery items will be populated by JavaScript -->
</div>
<div class="loading" id="loading">
<div class="loading-spinner"></div>
<p>Loading more images...</p>
</div>
</div>
<div class="lightbox" id="lightbox">
<span class="lightbox-close" id="close">×</span>
<span class="lightbox-nav lightbox-prev" id="prev">❮</span>
<span class="lightbox-nav lightbox-next" id="next">❯</span>
<div class="lightbox-content">
<img id="lightbox-img" src="" alt="">
<div class="lightbox-caption" id="caption"></div>
</div>
</div>
<script>
// Sample image data
const images = [
{ src: 'nature1.jpg', thumb: 'thumb-nature1.jpg', category: 'nature', title: 'Mountain Lake', description: 'Beautiful mountain lake at sunset' },
{ src: 'nature2.jpg', thumb: 'thumb-nature2.jpg', category: 'nature', title: 'Forest Path', description: 'Sunlight filtering through trees' },
{ src: 'city1.jpg', thumb: 'thumb-city1.jpg', category: 'city', title: 'City Skyline', description: 'Downtown at night' },
{ src: 'city2.jpg', thumb: 'thumb-city2.jpg', category: 'city', title: 'Street Art', description: 'Colorful mural in urban area' },
{ src: 'people1.jpg', thumb: 'thumb-people1.jpg', category: 'people', title: 'Portrait', description: 'Candid portrait in natural light' },
{ src: 'people2.jpg', thumb: 'thumb-people2.jpg', category: 'people', title: 'Group Photo', description: 'Team celebration' },
{ src: 'nature3.jpg', thumb: 'thumb-nature3.jpg', category: 'nature', title: 'Waterfall', description: 'Majestic waterfall in forest' },
{ src: 'city3.jpg', thumb: 'thumb-city3.jpg', category: 'city', title: 'Architecture', description: 'Modern building design' }
];
let currentIndex = 0;
let filteredImages = [...images];
// Gallery grid
function renderGallery(filter = 'all') {
filteredImages = filter === 'all'
? [...images]
: images.filter(img => img.category === filter);
const gallery = document.getElementById('gallery');
gallery.innerHTML = filteredImages.map((img, index) => `
<div class="gallery-item" data-index="${index}">
<img src="${img.thumb}" alt="${img.title}" loading="lazy">
<div class="gallery-caption">
<h3>${img.title}</h3>
<p>${img.description}</p>
</div>
</div>
`).join('');
}
// Lightbox functionality
function openLightbox(index) {
currentIndex = index;
const img = filteredImages[currentIndex];
document.getElementById('lightbox-img').src = img.src;
document.getElementById('caption').textContent = `${img.title} - ${img.description}`;
document.getElementById('lightbox').classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeLightbox() {
document.getElementById('lightbox').classList.remove('active');
document.body.style.overflow = '';
}
function nextImage() {
currentIndex = (currentIndex + 1) % filteredImages.length;
const img = filteredImages[currentIndex];
document.getElementById('lightbox-img').src = img.src;
document.getElementById('caption').textContent = `${img.title} - ${img.description}`;
}
function prevImage() {
currentIndex = (currentIndex - 1 + filteredImages.length) % filteredImages.length;
const img = filteredImages[currentIndex];
document.getElementById('lightbox-img').src = img.src;
document.getElementById('caption').textContent = `${img.title} - ${img.description}`;
}
// Event listeners
document.addEventListener('DOMContentLoaded', () => {
renderGallery();
// Gallery item click
document.getElementById('gallery').addEventListener('click', (e) => {
const item = e.target.closest('.gallery-item');
if (item) {
const index = parseInt(item.dataset.index);
openLightbox(index);
}
});
// Filter buttons
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
renderGallery(btn.dataset.filter);
});
});
// Lightbox controls
document.getElementById('close').addEventListener('click', closeLightbox);
document.getElementById('next').addEventListener('click', nextImage);
document.getElementById('prev').addEventListener('click', prevImage);
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (!document.getElementById('lightbox').classList.contains('active')) return;
if (e.key === 'Escape') closeLightbox();
if (e.key === 'ArrowRight') nextImage();
if (e.key === 'ArrowLeft') prevImage();
});
// Click outside to close
document.getElementById('lightbox').addEventListener('click', (e) => {
if (e.target === document.getElementById('lightbox')) {
closeLightbox();
}
});
});
// Infinite scroll simulation
window.addEventListener('scroll', () => {
const scrollPosition = window.innerHeight + window.scrollY;
const threshold = document.body.offsetHeight - 500;
if (scrollPosition > threshold) {
document.getElementById('loading').classList.add('active');
// Simulate loading more images
setTimeout(() => {
document.getElementById('loading').classList.remove('active');
// In real implementation, fetch more images here
}, 1000);
}
});
</script>
</body>
</html>
Best Practices
Image Optimization Checklist
<!-- Complete image optimization checklist --> <div class="checklist"> <h3>Image Optimization Checklist</h3> <div class="checklist-item"> <input type="checkbox" id="format"> <label for="format">✓ Choose the right format (WebP/AVIF for web, JPEG for photos, PNG for transparency)</label> </div> <div class="checklist-item"> <input type="checkbox" id="compress"> <label for="compress">✓ Compress images (reduce file size by 40-80%)</label> </div> <div class="checklist-item"> <input type="checkbox" id="responsive"> <label for="responsive">✓ Use responsive images (srcset with appropriate sizes)</label> </div> <div class="checklist-item"> <input type="checkbox" id="lazy"> <label for="lazy">✓ Implement lazy loading</label> </div> <div class="checklist-item"> <input type="checkbox" id="dimensions"> <label for="dimensions">✓ Set width and height attributes to prevent layout shifts</label> </div> <div class="checklist-item"> <input type="checkbox" id="alt"> <label for="alt">✓ Add descriptive alt text for accessibility</label> </div> <div class="checklist-item"> <input type="checkbox" id="cdn"> <label for="cdn">✓ Use CDN for faster delivery</label> </div> <div class="checklist-item"> <input type="checkbox" id="cache"> <label for="cache">✓ Set proper cache headers</label> </div> <div class="checklist-item"> <input type="checkbox" id="webp"> <label for="webp">✓ Provide WebP/AVIF fallbacks with picture element</label> </div> <div class="checklist-item"> <input type="checkbox" id="sprites"> <label for="sprites">✓ Consider CSS sprites for multiple small icons</label> </div> </div>
Accessibility Checklist
<!-- Accessibility checklist --> <div class="a11y-checklist"> <h3>Accessibility Checklist</h3> <div class="checklist-item"> <input type="checkbox" id="a11y-alt"> <label for="a11y-alt">✓ All images have meaningful alt text</label> </div> <div class="checklist-item"> <input type="checkbox" id="a11y-decorative"> <label for="a11y-decorative">✓ Decorative images have empty alt (alt="")</label> </div> <div class="checklist-item"> <input type="checkbox" id="a11y-contrast"> <label for="a11y-contrast">✓ Text over images has sufficient contrast</label> </div> <div class="checklist-item"> <input type="checkbox" id="a11y-motion"> <label for="a11y-motion">✓ Respect prefers-reduced-motion</label> </div> <div class="checklist-item"> <input type="checkbox" id="a11y-focus"> <label for="a11y-focus">✓ Interactive images have focus indicators</label> </div> <div class="checklist-item"> <input type="checkbox" id="a11y-captions"> <label for="a11y-captions">✓ Videos have captions</label> </div> <div class="checklist-item"> <input type="checkbox" id="a11y-transcripts"> <label for="a11y-transcripts">✓ Audio content has transcripts</label> </div> </div>
Conclusion
Images and media are crucial elements of modern web design. This comprehensive guide covered:
Key Takeaways
- Choose the right format for each use case
- Optimize images for web delivery
- Use responsive images with srcset and picture elements
- Implement lazy loading for better performance
- Style images creatively with CSS
- Ensure accessibility with proper alt text
- Consider performance impact of media files
- Use modern formats like WebP and AVIF
- Implement proper fallbacks for older browsers
- Test across devices and connection speeds
Tools and Resources
- Image Optimization: ImageOptim, TinyPNG, Squoosh
- Responsive Testing: Chrome DevTools, Responsively
- Accessibility Checkers: WAVE, axe, Lighthouse
- CDN Services: Cloudinary, Imgix, Cloudflare Images
- Icon Libraries: Font Awesome, Material Icons, Feather Icons
Next Steps
- Practice creating responsive image galleries
- Experiment with CSS filters and effects
- Implement lazy loading in your projects
- Learn about WebP and AVIF formats
- Study image CDN services
- Explore SVG animations
- Master video and audio embedding
Remember: Well-optimized, accessible media content significantly improves user experience and engagement!
HTML & CSS Learning Guides, Exercises, Projects, Design Systems, Accessibility & Performance (Related to HTML & CSS Development)
HTML & CSS Quiz – Comprehensive Assessment:
This quiz evaluates core knowledge of HTML and CSS including structure, styling, layout, forms, and responsive design. It is used to test practical understanding of front-end fundamentals and identify skill levels in web development.
Read more: https://macronepal.com/bash/html-and-css-quiz-comprehensive-assessment/
Complete Guide to HTML & CSS Tooling & Automation:
This guide explains tools and automation workflows used in modern web development, such as preprocessors, build tools, and task runners that improve efficiency in HTML and CSS projects.
Read more: https://macronepal.com/bash/complete-guide-to-html-and-css-tooling-automation/
Complete HTML & CSS Exercises:
A collection of practical exercises designed to strengthen HTML and CSS skills through hands-on coding tasks, covering layout, styling, and responsive design concepts.
Read more: https://macronepal.com/bash/complete-html-and-css-exercises/
Complete HTML & CSS Landing Page Project:
This project focuses on building a full landing page using HTML and CSS, helping learners understand real-world website structure, layout design, and UI development.
Read more: https://macronepal.com/bash/complete-html-css-landing-page-project/
HTML & CSS Debugging and Testing Guide:
This guide teaches how to identify and fix errors in HTML and CSS code, along with testing techniques to ensure websites work correctly across browsers.
Read more: https://macronepal.com/bash/complete-guide-to-html-and-css-debugging-testing/
HTML & CSS Design Systems Guide:
A design system approach helps maintain consistency in UI development using reusable components, styles, and patterns across web projects.
Read more: https://macronepal.com/html-and-css/complete-guide-to-html-and-css-design-systems/
HTML & CSS Accessibility (A11y) Guide:
This guide focuses on making websites accessible for all users, including proper semantic HTML, keyboard navigation, alt text, and screen reader support.
Read more: https://macronepal.com/bash/complete-guide-to-html-css-accessibility-a11y/
HTML & CSS Performance Guide:
This topic explains optimization techniques such as reducing file size, improving loading speed, and writing efficient HTML and CSS for better website performance.
Read more: https://macronepal.com/bash/complete-guide-to-html-and-css-performance/
HTML & CSS Design Systems (Advanced Overview):
Design systems help developers maintain scalable and consistent UI components across large projects using structured HTML and reusable CSS patterns.
Read more: https://macronepal.com/html-and-css/complete-guide-to-html-and-css-design-systems/