-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0d2b1b
commit d1d2853
Showing
10 changed files
with
411 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Day 003: Lazy Load Images | ||
|
||
## Project Description | ||
|
||
This project demonstrates the implementation of lazy loading for images on a web page. Lazy loading is a technique that defers the loading of non-critical resources (in this case, images) until they are needed. This approach can significantly improve page load times and reduce bandwidth usage, especially for pages with many images or on slower network connections. | ||
|
||
## Technologies Used | ||
|
||
- HTML5 | ||
- CSS3 | ||
- JavaScript (Vanilla JS) | ||
- Intersection Observer API | ||
|
||
## Features | ||
|
||
- Lazy loading of images as they enter the viewport | ||
- Placeholder images or low-resolution previews while full images load | ||
- Smooth transition effect when images load | ||
- Responsive design to showcase lazy loading across different screen sizes | ||
- Performance metrics display to show the benefits of lazy loading | ||
|
||
## Challenges Faced | ||
|
||
1. Implementing lazy loading without relying on external libraries | ||
2. Ensuring compatibility across different browsers | ||
3. Creating an effective placeholder strategy while images load | ||
4. Balancing between performance gains and user experience | ||
|
||
## Lessons Learned | ||
|
||
- How to use the Intersection Observer API for efficient lazy loading | ||
- Techniques for creating and styling placeholder images | ||
- The importance of performance optimization in web development | ||
- How to measure and display performance metrics in real-time | ||
|
||
## Future Improvements | ||
|
||
- Implement progressive image loading (blur-up technique) | ||
- Add support for lazy loading background images in CSS | ||
- Create a reusable lazy loading component or module | ||
- Implement error handling for failed image loads | ||
- Add option to preload critical images for faster initial display | ||
|
||
## Live Demo | ||
|
||
[View Live Demo](https://nexoscreator.github.io/365-Days-of-Web-Development/projects/day-003-lazy-load-images/) | ||
|
||
## Screenshots | ||
|
||
![Lazy Load Images Screenshot](https://github.com/nexoscreator/365-Days-of-Web-Development/raw/main/projects/day-003-lazy-load-images/screenshot.png) | ||
|
||
## How to Use | ||
|
||
1. Clone the repository | ||
2. Navigate to the `projects/day-003-lazy-load-images` directory | ||
3. Open `index.html` in your web browser | ||
4. Scroll down the page to see images lazy load as they enter the viewport | ||
|
||
## Code Snippet | ||
|
||
Here's a key part of the lazy loading implementation: | ||
|
||
```javascript | ||
const images = document.querySelectorAll('[data-src]'); | ||
|
||
const imgOptions = { | ||
threshold: 0, | ||
rootMargin: "0px 0px 300px 0px" | ||
}; | ||
|
||
const imgObserver = new IntersectionObserver((entries, imgObserver) => { | ||
entries.forEach(entry => { | ||
if (!entry.isIntersecting) return; | ||
|
||
const img = entry.target; | ||
img.src = img.dataset.src; | ||
img.classList.add('loaded'); | ||
imgObserver.unobserve(img); | ||
}); | ||
}, imgOptions); | ||
|
||
images.forEach(img => imgObserver.observe(img)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Day 003: Lazy Load Images</title> | ||
<link rel="stylesheet" href="./style.css"> | ||
</head> | ||
|
||
<body> | ||
<div class="image-container"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1/800/600" alt="Lazy loaded image 1" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/10/800/600" alt="Lazy loaded image 2" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/100/800/600" alt="Lazy loaded image 3" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1000/800/600" alt="Lazy loaded image 4" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1001/800/600" alt="Lazy loaded image 5" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1002/800/600" alt="Lazy loaded image 6" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1003/800/600" alt="Lazy loaded image 7" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1004/800/600" alt="Lazy loaded image 8" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1005/800/600" alt="Lazy loaded image 9" class="lazy-image"> | ||
<img src="placeholder.jpg" data-src="https://picsum.photos/id/1006/800/600" alt="Lazy loaded image 10" class="lazy-image"> | ||
</div> | ||
|
||
<script src="./main.js"></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
document.addEventListener('DOMContentLoaded', function() { | ||
const images = document.querySelectorAll('.lazy-image'); | ||
|
||
const imgOptions = { | ||
threshold: 0, | ||
rootMargin: "0px 0px 300px 0px" | ||
}; | ||
|
||
const imgObserver = new IntersectionObserver((entries, imgObserver) => { | ||
entries.forEach(entry => { | ||
if (!entry.isIntersecting) return; | ||
|
||
const img = entry.target; | ||
img.src = img.dataset.src; | ||
img.classList.add('loaded'); | ||
imgObserver.unobserve(img); | ||
}); | ||
}, imgOptions); | ||
|
||
images.forEach(img => imgObserver.observe(img)); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
.image-container { | ||
display: grid; | ||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | ||
gap: 1rem; | ||
} | ||
|
||
.lazy-image { | ||
width: 100%; | ||
height: 300px; | ||
object-fit: cover; | ||
background-color: #ddd; | ||
transition: opacity 0.3s ease-in-out; | ||
} | ||
|
||
.lazy-image.loaded { | ||
opacity: 1; | ||
} | ||
|
||
@media (max-width: 600px) { | ||
.image-container { | ||
grid-template-columns: 1fr; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Day 004: Lightbox Image Gallery | ||
|
||
## Project Description | ||
|
||
This project implements a responsive lightbox image gallery. Users can click on thumbnail images to view them in a larger, overlay lightbox. The lightbox includes navigation controls to move between images, as well as a close button to exit the lightbox view. | ||
|
||
## Technologies Used | ||
|
||
- HTML5 | ||
- CSS3 | ||
- JavaScript (Vanilla JS) | ||
|
||
## Features | ||
|
||
- Responsive grid layout for thumbnail images | ||
- Smooth transition effects when opening and closing the lightbox | ||
- Navigation controls (previous and next buttons) in the lightbox | ||
- Close button to exit the lightbox view | ||
- Keyboard navigation support (arrow keys and Esc key) | ||
- Automatic image sizing to fit the viewport | ||
|
||
## Challenges Faced | ||
|
||
1. Implementing smooth transitions between images in the lightbox | ||
2. Ensuring responsive design for both the thumbnail grid and the lightbox view | ||
3. Handling various image aspect ratios while maintaining a consistent layout | ||
4. Implementing keyboard navigation in addition to click events | ||
|
||
## Lessons Learned | ||
|
||
- Advanced CSS transitions and transforms for creating smooth visual effects | ||
- Techniques for creating an overlay effect with CSS and JavaScript | ||
- Handling keyboard events for improved accessibility and user experience | ||
- Managing image loading and error states in JavaScript | ||
|
||
## Future Improvements | ||
|
||
- Add touch swipe support for mobile devices | ||
- Implement image lazy loading for better performance with large galleries | ||
- Add zoom functionality for detailed image viewing | ||
- Create a slideshow mode with autoplay feature | ||
- Implement caption support for images | ||
|
||
## Live Demo | ||
|
||
[View Live Demo](https://nexoscreator.github.io/365-Days-of-Web-Development/projects/day-004-lightbox-image-gallery/) | ||
|
||
## Screenshots | ||
|
||
![Lightbox Image Gallery Screenshot](https://github.com/nexoscreator/365-Days-of-Web-Development/raw/main/projects/day-004-lightbox-image-gallery/screenshot.png) | ||
|
||
## How to Use | ||
|
||
1. Clone the repository | ||
2. Navigate to the `projects/day-004-lightbox-image-gallery` directory | ||
3. Open `index.html` in your web browser | ||
4. Click on any thumbnail to open the lightbox view | ||
5. Use the navigation arrows or keyboard arrow keys to move between images | ||
6. Click the close button or press the Esc key to exit the lightbox | ||
|
||
This project serves as an excellent starting point for implementing a lightbox image gallery in your web applications. Feel free to customize and expand upon it to suit your specific needs! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Day 004: Lightbox Image Gallery</title> | ||
<link rel="stylesheet" href="./style.css"> | ||
</head> | ||
|
||
<body> | ||
<div class="gallery"> | ||
<img src="https://picsum.photos/id/1015/300/200" alt="Image 1" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1016/300/200" alt="Image 2" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1018/300/200" alt="Image 3" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1019/300/200" alt="Image 4" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1020/300/200" alt="Image 5" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1021/300/200" alt="Image 6" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1022/300/200" alt="Image 7" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1023/300/200" alt="Image 8" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1024/300/200" alt="Image 9" class="gallery-img"> | ||
<img src="https://picsum.photos/id/1025/300/200" alt="Image 10" class="gallery-img"> | ||
</div> | ||
|
||
<div id="lightbox" class="lightbox"> | ||
<span class="close">×</span> | ||
<img class="lightbox-content" id="lightbox-img"> | ||
<div class="caption" id="caption"></div> | ||
<a class="prev">❮</a> | ||
<a class="next">❯</a> | ||
</div> | ||
|
||
<script src="./main.js"></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
document.addEventListener('DOMContentLoaded', function() { | ||
const gallery = document.querySelector('.gallery'); | ||
const lightbox = document.getElementById('lightbox'); | ||
const lightboxImg = document.getElementById('lightbox-img'); | ||
const caption = document.getElementById('caption'); | ||
const close = document.querySelector('.close'); | ||
const prev = document.querySelector('.prev'); | ||
const next = document.querySelector('.next'); | ||
let currentIndex = 0; | ||
const images = document.querySelectorAll('.gallery-img'); | ||
|
||
function openLightbox(index) { | ||
lightbox.style.display = 'block'; | ||
lightboxImg.src = images[index].src.replace('300/200', '1200/800'); | ||
caption.textContent = images[index].alt; | ||
currentIndex = index; | ||
} | ||
|
||
function closeLightbox() { | ||
lightbox.style.display = 'none'; | ||
} | ||
|
||
function showPrev() { | ||
currentIndex = (currentIndex - 1 + images.length) % images.length; | ||
openLightbox(currentIndex); | ||
} | ||
|
||
function showNext() { | ||
currentIndex = (currentIndex + 1) % images.length; | ||
openLightbox(currentIndex); | ||
} | ||
|
||
gallery.addEventListener('click', function(e) { | ||
if (e.target.classList.contains('gallery-img')) { | ||
const index = Array.from(images).indexOf(e.target); | ||
openLightbox(index); | ||
} | ||
}); | ||
|
||
close.addEventListener('click', closeLightbox); | ||
prev.addEventListener('click', showPrev); | ||
next.addEventListener('click', showNext); | ||
|
||
document.addEventListener('keydown', function(e) { | ||
if (lightbox.style.display === 'block') { | ||
if (e.key === 'ArrowLeft') { | ||
showPrev(); | ||
} else if (e.key === 'ArrowRight') { | ||
showNext(); | ||
} else if (e.key === 'Escape') { | ||
closeLightbox(); | ||
} | ||
} | ||
}); | ||
|
||
lightbox.addEventListener('click', function(e) { | ||
if (e.target === lightbox) { | ||
closeLightbox(); | ||
} | ||
}); | ||
}); |
Oops, something went wrong.