capture属性仅对type="file"有效且必须配合accept指定媒体类型,标准值仅有"user"和"environment",缺失HTTPS、非用户手势触发或权限未开启时会静默降级至图库选择。

capture 属性只对 type="file" 有效,且必须配 accept
直接给 type="text" 或 type="button" 加 capture 完全没用,浏览器会静默忽略。它本质是 <input type="file"> 的提示性扩展,不是功能开关。
生效前提有三个,缺一不可:
-
type必须是"file" -
accept必须明确指定媒体类型,如accept="image/*"、accept="video/*"或accept="audio/*" -
capture必须存在(可带值,也可不带)
常见错误写法:<input type="file" capture>(漏 accept)、<input type="file" accept="image/jpeg" capture>(iOS 和部分 Android 会退化为图库选择)。
capture="user" 和 capture="environment" 是唯二标准值
W3C 规范只定义了 "user" 和 "environment" 两个合法字符串值,其他如 "camera"、"microphone" 都是非标写法,已被主流浏览器废弃或忽略。
立即学习“前端免费学习笔记(深入)”;
它们的语义很明确:
-
capture="user":提示优先调用前置摄像头或面向用户的麦克风(自拍/语音输入场景) -
capture="environment":提示优先调用后置摄像头(扫码、远距拍摄) - 不写值(
capture)或写其他字符串,行为由浏览器自行决定,iOS Safari 通常等价于capture="user"
注意:capture="environment" 在 iOS Safari 16.4+ 才真正支持;旧版本会直接忽略该属性,只当普通 accept="image/*" 处理。
为什么点了还是弹图库,而不是相机?
这不是 bug,是浏览器的降级策略——只要条件不满足,就会静默 fallback 到文件选择器,控制台也不会报错。
最常踩的坑有这些:
- 页面跑在
http://协议下:iOS Safari 和新版 Chrome 直接禁用摄像头入口 -
input是动态插入的(比如 Vue 的mounted、React 的useEffect、或innerHTML拼接):iOS 会跳过该元素上的capture -
input被设为display: none或visibility: hidden:Safari 不认,Android 部分 WebView 也会失效 - 用户此前拒绝过摄像头权限:后续点击不会再次弹 prompt,需引导手动开启
- 微信内置浏览器(iOS WKWebView / Android X5 内核):长期不响应
capture,连getUserMedia()都受限
检测微信可写:navigator.userAgent.includes("MicroMessenger"),命中则建议移除 capture,改用文案引导:“请打开相机 App 拍照后上传”。
真要可控拍摄,得上 MediaDevices.getUserMedia()
capture 属性做不到的事:实时预览、连续拍照、自定义 UI、EXIF 方向修正、横竖屏适配。
这时候必须切换方案:
- 用
getUserMedia()获取视频流,绑定到<video>标签显示预览 - 用
canvas.captureStream()或ImageCaptureAPI 截帧 - 手动处理权限拒绝、设备枚举、旋转方向(
exif-js或piexif)
但代价也很明显:代码量翻倍、兼容性更碎(X5 内核对 getUserMedia 支持不全)、首次授权体验更重。多数生产项目最终都走「UA 检测 + capture 尝试 + 引导文案 fallback」路线,而不是强依赖单一方案。



















