很多站长搜“悬浮二维码源码兼容所有浏览器”,真正想要的不只是一个能飘在右下角的小图,而是它在Chrome、Safari、Edge、Firefox、微信内置浏览器和安卓WebView里都不飘偏、不遮挡、能长按识别。悬浮二维码本身不复杂,一个固定定位容器、一张二维码图、一个关闭按钮,代码量不大。麻烦的是兼容细节,尤其是移动端和微信环境。
先看浏览器底数。StatCounter 2025年4月全球数据,Chrome约占66%,Safari约18%,Edge约5%,Firefox约2.5%,剩下是三星浏览器、Opera和各色WebView。国内更碎,Chrome、Edge、360、QQ浏览器、微信X5/WKWebView混着跑。写源码时不能只按Chrome调,得按“最低共同点”写。我的建议是IE8以上兜底,IE6/7如果真有人用,只能上table版二维码和absolute定位降级,别硬上canvas。
悬浮层定位是头一个坑。桌面用position:fixed; right:20px; bottom:20px; z-index:9999; 大部分浏览器没问题。iOS Safari滚动时地址栏伸缩,fixed元素会跟着抖,安卓部分WebView也有类似表现。稳妥做法是给容器加transform: translateZ(0)开启合成层,底部间距用calc(20px + env(safe-area-inset-bottom))照顾刘海屏,旧浏览器不认calc就写两行,先写bottom:20px再写calc覆盖。要是必须兼容不支持fixed的老IE,用JS监听scroll,把position改成absolute并算top,虽然体验一般,但能显示。
二维码生成方式决定兼容上限。canvas画二维码清晰,但IE8不支持;table渲染兼容老浏览器,但高DPI屏上容易糊。实际项目里可以优先用qrcodejs这类库,它自带canvas和table双模式,检测不到canvas就退回table。更稳的是生成后转成img的data URL,微信长按识别只认img,canvas长按没反应。二维码显示尺寸别小于120px,纠错级别用M,四周留4个模块静区,对比度够,扫描识别率才稳。显示160px在桌面刚好,移动端120px到140px,太大挡内容。
事件和脚本写法也要收着点。用var,别用let/const和箭头函数,需要的话走Babel转ES5。绑定事件先判断addEventListener,没有就用attachEvent。关闭按钮的点击区域做到44px见方,视觉上可以小,热区不能小,移动端手指点得中。关闭状态存sessionStorage,没有就写cookie,刷新后别又弹出来烦人。展开二维码建议延迟到点击时再生成,首屏少一次canvas绘制,低端安卓机会明显轻一点。

还有一个容易忽略的点是遮挡和层级。悬浮二维码固定在右下角,别盖住客服、返回顶部和表单提交按钮。z-index给9999够用,别飙到2147483647,后面没法调。容器加aria-label,图片写alt,键盘能聚焦关闭按钮,这不是多余,是让源码能过基本无障碍检查。测试矩阵别省:Chrome、Edge、Firefox、Safari、iOS Safari、微信、安卓WebView、360极速各跑一遍,重点看滚动、横屏、长按识别、关闭后刷新。做到这些,“兼容所有浏览器”才不是口号,而是能交付的源码。