用原生HTML+JS实现缩略图切换大图:通过data-fullsrc存放大图地址,事件委托监听缩略图容器,点击时用Image预加载大图并赋值给主图src,失败则fallback占位图;缩略图用<button>包裹以支持键盘导航和aria-current高亮。

怎么用 <img> 实现点击缩略图切换大图预览
直接用原生 HTML + 少量 JS 就能搞定,不需要框架或插件。核心是让缩略图和大图区域建立映射关系,点击时更新 <img src> 和 alt。
常见错误是把所有缩略图都写死 src,导致加载慢、首屏卡顿;或者用 data-src 但没做懒加载兜底,图片反复请求。
- 缩略图用真实尺寸小图(如
thumb-200x150.jpg),别用 CSS 缩放原图 - 大图区域初始
src设为空或占位图,避免无意义请求 - 每个缩略图加
data-fullsrc存放大图地址,data-alt存放描述 - 绑定点击事件时用事件委托(比如监听父容器),避免重复绑定
<div id="gallery">
<img id="main-img" src="" alt="" width="800" height="600">
<div class="thumbnails">
<img src="thumb-1.jpg" data-fullsrc="full-1.jpg" data-alt="日落" alt="缩略图1">
<img src="thumb-2.jpg" data-fullsrc="full-2.jpg" data-alt="森林" alt="缩略图2">
</div>
</div>
为什么 loading="lazy" 不能直接用在大图上
因为大图是动态切换的,浏览器无法提前感知哪些图会显示,loading="lazy" 在 JS 修改 src 后不会自动触发加载逻辑,容易出现空白或 loading 状态卡住。
更可靠的做法是:切换前先创建 Image 实例预加载,加载成功再赋值给 DOM 节点。
立即学习“前端免费学习笔记(深入)”;
- 不依赖
loading属性,自己控制加载时机 - 加载失败时要有 fallback,比如显示错误占位图或提示文字
- 避免连续快速点击导致多个
Image实例并发请求
function loadFullImage(src, alt) {
const img = new Image();
img.onload = () => {
document.getElementById('main-img').src = src;
document.getElementById('main-img').alt = alt;
};
img.onerror = () => {
document.getElementById('main-img').src = '/placeholder-error.jpg';
};
img.src = src; // 触发加载
}
缩略图导航栏怎么保持当前项高亮且可键盘操作
光靠 CSS 的 :hover 不够,用户可能用 Tab 键浏览,或屏幕阅读器需要语义支持。
关键不是“加 class”,而是同步 aria-current="true" 和 tabindex="0",并监听 keydown 处理方向键切换。
- 缩略图用
<button type="button">包裹,比纯<img>更语义化、默认可聚焦 - 每次切换大图后,把当前按钮设为
aria-current="true",其他设为false - 监听
ArrowLeft/ArrowRight,用focus()移动焦点,再触发对应图片加载 - 避免用
outline: none彻底去掉焦点框,至少用:focus-visible做区分
移动端触摸滑动切换缩略图要注意什么
原生 touchstart/touchmove 容易误判为页面滚动,尤其在 iOS Safari 上。
真正稳定的做法是:只在缩略图容器内启用 touch 事件,并限制仅水平滑动,同时 preventDefault() 需谨慎——只在明确是滑动意图时才调用,否则会禁用页面滚动。
- 记录
touchstart的clientX,在touchend时对比位移,大于 30px 才算有效滑动 - 用
getBoundingClientRect()判断手指是否仍在缩略图区域内,防止划出后还响应 - 不要监听
touchmove做实时位移动画,性能差且难对齐;滑动结束才跳转下一张 - 搭配
touch-action: pan-y样式,允许垂直滚动,禁用默认的双指缩放等干扰行为
缩略图数量多时,DOM 节点过多会影响滚动流畅度,这时候该考虑虚拟滚动——但多数场景下,10–20 张图直接渲染就够了。



















