srcSet属性在Safari浏览器中无法正常工作的问题求助
Safari中srcset图标不生效的解决建议
你当前的导航栏图标通过srcset实现多分辨率适配,在Chrome、Firefox等浏览器正常,但Safari无法加载对应分辨率的图片,以下是针对Safari兼容性的修复方案:
问题代码回顾
icons.ts
import dashboardIcon from 'assets/icons/dashboard_icon.png' import dashboardIcon2x from 'assets/icons/dashboard_icon@2x.png' import dashboardIcon3x from 'assets/icons/dashboard_icon@3x.png' import dashboardIcon4x from 'assets/icons/dashboard_icon@4x.png' dashboardIcon: { src: dashboardIcon, srcset: `${dashboardIcon4x} 4x,${dashboardIcon3x} 3x,${dashboardIcon2x} 2x, ${dashboardIcon} 1x`, },
CustomIcon.tsx
import React from 'react' import styled from 'styled-components' import { FixMeLater } from 'types' import FilePicker from 'components/button/FilePicker' export interface IconSourceType { src: string srcset: string } interface IIconProps { id?: string source: IconSourceType className?: string isFilePicker?: boolean getInputProps?: FixMeLater onClick?: (e: React.MouseEvent<HTMLElement>) => void onMouseDown?: (e: React.MouseEvent<HTMLElement>) => void onMouseUp?: (e: React.MouseEvent<HTMLElement>) => void } const CustomIcon = ({ id = '', source, className, isFilePicker, getInputProps, onClick, onMouseDown, onMouseUp, }: IIconProps) => { return ( <> <IconWrapper id={id} onClick={onClick} onMouseDown={onMouseDown} onMouseUp={onMouseUp} className={className} src={source.src} srcSet={source.srcset} clickable={!!onClick || !!onMouseUp} /> {isFilePicker && <FilePicker getInputProps={getInputProps} icon />} </> ) } export default CustomIcon const IconWrapper = styled.img` cursor: ${({ clickable }: { clickable: boolean }) => (clickable ? 'pointer' : 'unset')}; `
使用方式(NavigationBar.tsx)
... <CustomIcon source={icons.dashboardIcon} /> ...
修复方案
1. 确保图片实际分辨率与x描述符严格匹配
Safari对srcset的x描述符校验非常严格,要求@nx图片的实际像素尺寸必须是基础图的n倍。例如:
- 基础图
dashboard_icon.png如果是48×48像素,那么@2x必须是96×96,@3x是144×144,@4x是192×192。 - 若图片尺寸不匹配,Safari会忽略对应分辨率的图片,直接加载基础src。
2. 修正srcset的格式空格
你的srcset中部分条目缺少逗号后的空格(如4x,${dashboardIcon3x}),虽然其他浏览器容错,但Safari可能解析失败。统一格式为逗号+空格分隔:
dashboardIcon: { src: dashboardIcon, srcset: `${dashboardIcon4x} 4x, ${dashboardIcon3x} 3x, ${dashboardIcon2x} 2x, ${dashboardIcon} 1x`, },
3. 强制添加sizes属性(关键修复)
Safari在没有sizes属性时,无法准确判断图片的布局尺寸,进而无法正确选择srcset中的图片。根据你的图标实际布局尺寸添加sizes:
- 若图标固定显示为24px宽:
修改IconWrapper的props,添加sizes="24px":<IconWrapper id={id} onClick={onClick} onMouseDown={onMouseDown} onMouseUp={onMouseUp} className={className} src={source.src} srcSet={source.srcset} sizes="24px" // 新增 clickable={!!onClick || !!onMouseUp} /> - 若图标使用相对单位(如1em),则设置
sizes="1em",确保值与CSS中图标宽度一致。
4. 检查图片加载状态
打开Safari开发者工具的网络面板,筛选图片请求,确认各个分辨率的图片是否能正常加载:
- 若出现404,检查图片路径是否正确(注意webpack等打包工具的路径处理)。
- 若出现跨域错误,确认服务器配置了正确的CORS头。
5. 备选方案:改用<picture>元素
如果以上方案仍无效,可替换为<picture>元素实现多分辨率适配,Safari对其支持更稳定:
修改CustomIcon.tsx的返回部分:
const CustomIcon = ({ id = '', source, className, isFilePicker, getInputProps, onClick, onMouseDown, onMouseUp, }: IIconProps) => { // 拆分srcset为各个分辨率条目 const srcItems = source.srcset.split(',').map(item => item.trim().split(' ')) return ( <> <picture> {/* 为每个分辨率添加source */} {srcItems.map(([url, ratio]) => ( <source key={ratio} srcSet={url} media={`(-webkit-min-device-pixel-ratio: ${ratio.replace('x', '')})`} /> ))} {/* 基础图片作为 fallback */} <IconWrapper id={id} onClick={onClick} onMouseDown={onMouseDown} onMouseUp={onMouseUp} className={className} src={source.src} clickable={!!onClick || !!onMouseUp} /> </picture> {isFilePicker && <FilePicker getInputProps={getInputProps} icon />} </> ) }
内容的提问来源于stack exchange,提问作者fatihthebach
相关产品推荐
相关产品推荐

