给博客加个图片灯箱
3 min

博客里的图片太小,看不清楚?加个灯箱功能,点击就能放大查看。
创建组件
在 src/components/ 目录下新建 ImageLightbox.astro 文件,复制下面的代码:
---
export interface Props {
src: string;
alt: string;
caption?: string;
}
const { src, alt, caption } = Astro.props;
---
<div class="lightbox-container">
<img
src={src}
alt={alt}
class="lightbox-image"
loading="lazy"
/>
{caption && <p class="image-caption">{caption}</p>}
</div>
<div id="lightbox-modal" class="lightbox-modal">
<span class="close-lightbox">×</span>
<img class="lightbox-content" id="lightbox-img" />
{caption && <div id="lightbox-caption" class="lightbox-caption"></div>}
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const modal = document.getElementById('lightbox-modal') as HTMLElement;
const modalImg = document.getElementById('lightbox-img') as HTMLImageElement;
const modalCaption = document.getElementById('lightbox-caption') as HTMLElement;
const images = document.querySelectorAll('.lightbox-image') as NodeListOf<HTMLImageElement>;
const closeBtn = document.querySelector('.close-lightbox') as HTMLElement;
if (!modal || !modalImg || !closeBtn) {
console.error('Lightbox: Required elements not found');
return;
}
images.forEach(img => {
img.addEventListener('click', () => {
modal.style.display = 'block';
modalImg.src = img.src;
if (modalCaption) {
const caption = img.nextElementSibling as HTMLElement;
if (caption && caption.classList.contains('image-caption')) {
modalCaption.textContent = caption.textContent || '';
modalCaption.style.display = 'block';
} else {
modalCaption.style.display = 'none';
}
}
document.body.style.overflow = 'hidden';
});
});
closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
});
modal.addEventListener('click', (e) => {
if (e.target === modal) {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && modal.style.display === 'block') {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
});
</script>
<style>
.lightbox-container {
margin: 2rem 0;
text-align: center;
}
.lightbox-image {
max-width: 100%;
height: auto;
cursor: pointer;
transition: transform 0.3s ease;
border-radius: 4px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.lightbox-image:hover {
transform: scale(1.02);
}
.image-caption {
margin-top: 0.8rem;
font-size: 0.9rem;
color: #666;
font-style: italic;
}
.lightbox-modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
backdrop-filter: blur(5px);
}
.lightbox-content {
margin: auto;
display: block;
width: 80%;
max-width: 900px;
max-height: 90vh;
object-fit: contain;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 4px;
}
.close-lightbox {
position: absolute;
top: 20px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
cursor: pointer;
z-index: 1001;
}
.close-lightbox:hover {
color: #bbb;
}
.lightbox-caption {
margin: auto;
display: block;
width: 80%;
max-width: 900px;
text-align: center;
color: #f1f1f1;
padding: 10px 0;
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
font-size: 1rem;
}
@media only screen and (max-width: 768px) {
.lightbox-content {
width: 95%;
}
.lightbox-caption {
width: 95%;
font-size: 0.9rem;
bottom: 10px;
}
.close-lightbox {
top: 15px;
right: 20px;
font-size: 30px;
}
}
</style>使用组件
在文章中导入并使用:
---
title: "我的文章"
---
import ImageLightbox from '../components/ImageLightbox.astro';
<ImageLightbox
src="/images/photo.jpg"
alt="图片说明"
caption="可选的标题"
/>测试
启动开发服务器,访问页面,点击图片试试效果。
关闭方式:点击右上角 ×、点击背景、按 ESC 键。
常见问题
图片没反应? 检查组件路径和导入语句是否正确。
样式不对? 看看有没有全局样式覆盖,或者清除缓存试试。
想改样式? 直接修改 <style> 标签里的 CSS。
进阶
组件已经支持懒加载,提升页面速度。
想加过渡动画?在 .lightbox-modal 里加 animation: fadeIn 0.3s ease;。
想支持滚轮缩放?在 <script> 里添加 wheel 事件监听。
最后
保存文件后记得重启开发服务器,多测试几次确保功能正常。