feat: added image collage component 5ed90249
Steve · 2025-10-02 19:49 1 file(s) · +115 −0
src/components/ImageCollage.astro (added) +115 −0
1 +
---
2 +
interface Props {
3 +
	images: string[];
4 +
}
5 +
6 +
const { images } = Astro.props;
7 +
---
8 +
9 +
<div class="image-collage">
10 +
	<div class="collage-grid">
11 +
		{images.map((url, index) => (
12 +
			<div class="collage-item" data-index={index}>
13 +
				<img src={url} alt={`Image ${index + 1}`} loading="lazy" />
14 +
			</div>
15 +
		))}
16 +
	</div>
17 +
	<div class="collage-overlay" id="collage-overlay">
18 +
		<img src="" alt="" id="expanded-image" />
19 +
	</div>
20 +
</div>
21 +
22 +
<style>
23 +
	.image-collage {
24 +
		position: relative;
25 +
		width: 100%;
26 +
	}
27 +
28 +
	.collage-grid {
29 +
		display: grid;
30 +
		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
31 +
		gap: 0.5rem;
32 +
		width: 100%;
33 +
	}
34 +
35 +
	.collage-item {
36 +
		position: relative;
37 +
		overflow: hidden;
38 +
		cursor: pointer;
39 +
		aspect-ratio: 1;
40 +
		transition: transform 0.2s ease;
41 +
	}
42 +
43 +
	.collage-item:hover {
44 +
		transform: scale(1.02);
45 +
	}
46 +
47 +
	.collage-item img {
48 +
		width: 100%;
49 +
		height: 100%;
50 +
		object-fit: cover;
51 +
		display: block;
52 +
	}
53 +
54 +
	.collage-overlay {
55 +
		position: fixed;
56 +
		top: 0;
57 +
		left: 0;
58 +
		width: 100vw;
59 +
		height: 100vh;
60 +
		background-color: rgba(0, 0, 0, 0);
61 +
		display: flex;
62 +
		align-items: center;
63 +
		justify-content: center;
64 +
		opacity: 0;
65 +
		pointer-events: none;
66 +
		transition: all 0.3s ease;
67 +
		z-index: 9999;
68 +
	}
69 +
70 +
	.collage-overlay.active {
71 +
		background-color: rgba(0, 0, 0, 0.9);
72 +
		opacity: 1;
73 +
		pointer-events: all;
74 +
	}
75 +
76 +
	.collage-overlay img {
77 +
		max-width: 90%;
78 +
		max-height: 90vh;
79 +
		object-fit: contain;
80 +
		transform: scale(0.8);
81 +
		transition: transform 0.3s ease;
82 +
	}
83 +
84 +
	.collage-overlay.active img {
85 +
		transform: scale(1);
86 +
	}
87 +
</style>
88 +
89 +
<script>
90 +
	document.addEventListener('DOMContentLoaded', () => {
91 +
		const collageItems = document.querySelectorAll('.collage-item');
92 +
		const overlay = document.getElementById('collage-overlay');
93 +
		const expandedImage = document.getElementById('expanded-image') as HTMLImageElement;
94 +
95 +
		collageItems.forEach((item) => {
96 +
			item.addEventListener('click', () => {
97 +
				const img = item.querySelector('img') as HTMLImageElement;
98 +
				if (img && overlay && expandedImage) {
99 +
					expandedImage.src = img.src;
100 +
					expandedImage.alt = img.alt;
101 +
					overlay.classList.add('active');
102 +
				}
103 +
			});
104 +
		});
105 +
106 +
		overlay?.addEventListener('click', () => {
107 +
			overlay.classList.remove('active');
108 +
			setTimeout(() => {
109 +
				if (expandedImage) {
110 +
					expandedImage.src = '';
111 +
				}
112 +
			}, 300);
113 +
		});
114 +
	});
115 +
</script>