详解css-vars-ponyfill 在ie环境下使用问题(nextjs 构建)
css-vars-ponyfill
通过css变量来实现网页换肤的过程中,会出现兼容性问题。
为了解决ie,qq,百度浏览器等兼容性问题,引入css-vars-ponyfill,但是在ie浏览器下,css-vars-ponyfill 的在nextjs下表现不佳,主要缺陷是由于页面是服务端渲染,因此用户在看到界面后,动态主题色等样式不能很快渲染好,而是有一个过渡的时间(css-vars-ponyfill 仅支持client-side),颜色会存在明显替换的过程用户体验差。通过阅读 源码 可以看到,cssVars需要等到浏览器contentLoaded之后,才会触发,否则一直监听dom的data content事件,这就导致了体验上的问题。
解决方案
1.解析速度
通过把直接去除 document.readyState !== 'loading' 这样的限制条件使得浏览器在解析到,然后更改css-vars-ponyfill 的引入方式(旧的引入方式是在nextjs中的mainjs中引入module,然后直接调用cssVars(),这样在调用到ponyfill的脚本前还会解析其他不相关的chunk,为了更快的解析css变量,需要手动选择插入位置),更改之后的css-vars-ponyfill 通过找到css变量的位置(nextjs 通过将不同组件下的style,统一打包在header里面),然后将更改后的ponyfill 插入到style 之后进行调用,这一步选择在服务端渲染的 _document.tsx 文件中更改。
2.解析稳定性
通过手动更改文件解析位置,以及对源码的条件触发机制进行相关更改,首页颜色渲染速度有了一定提升。但是仍存在一个问题,即通过路由跳转的界面,如果有新的style chunk,插入时不能进行有效的css变量解析(已尝试配置cssVars的option 打开MutationObserver)。
因此,解决方案是通过判断UA,来让ie等浏览器下所有的路由通过a标签跳转,触发css-ponyfill的重新解析执行。
export function browser() {
const UA = window.navigator.userAgent
if (UA.includes("qqbrowser")) return "qqbrowser"
if (UA.includes("baidu")) return "baidu"
if (UA.includes("Opera")) return "Opera"
if (UA.includes("Edge")) return "Edge"
if (UA.includes("MSIE") || (UA.includes("Trident") && UA.includes("rv:11.0")))
return "IE"
if (UA.includes("Firefox")) return "Firefox"
if (UA.includes("Chrome")) return "Chrome"
if (UA.includes("Safari")) return "Safari"
}
type CommonLinkProps = {
children: ReactElement
href?: string
target?: string
outerLink?: boolean
styles?: unknown
}
export default function CustomLink(props: CommonLinkProps) {
const { children, href, target, as, outerLink, styles = emptyStyles } = props
const [isIE, setIE] = useState<boolean>(false)
const cloneEl = (c: ReactElement, props?: any) =>
React.cloneElement(c, { href: as ?? href, target, ...props })
useEffect(() => {
if (["IE", "qqbrowser", "baidu"].includes(browser())) {
setIE(true)
}
}, [])
function renderLink() {
if (Children.only(children).type === "a") {
const node = cloneEl(children as ReactElement)
return node
} else {
let fn: () => void | null = null
if (outerLink) {
fn = () => {
window.open(as ?? href)
}
} else {
fn = () => {
window.location.href = as ?? href
}
}
const node = cloneEl(children as ReactElement, {
onClick: () => {
fn()
},
})
return node
}
}
return (
<>
{!href ? (
children
) : isIE ? (
renderLink()
) : (
<Link {...props}>{children}</Link>
)}
<style jsx>{styles}</style>
</>
)
}
这里children的type 选择了 ReactElement ,而不是插槽中通常支持的 ReactNode 主要是不想考虑直接插入字符串这种情况,会增加问题的复杂度,因此直接在type这层做限制。还有Fragments 也没有考虑,且没有找到有效的Fragments 类型,没法在ReactNode 中把它Omit掉,nextjs 里面的Link 如果首层插入了Fragments 后,也无法正常跳转,可能原因也是无法再Fragments 上面绑定有效的事件吧,目前Fragments(16.13.1) 只支持key属性,希望后续可以优化。
总结
到此这篇关于css-vars-ponyfill 在ie环境下使用问题(nextjs 构建)的文章就介绍到这了,更多相关css-vars-ponyfill使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!
相关文章
- CSS Grid 是一种二维布局系统,可以同时控制行和列,相比 Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,这篇文章主要介绍了前端CSS Grid 布局详解,需要的朋2025-04-16
- CSS 中的 padding 和 margin 是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍 padding 和 margin 的概念、区别以及如何在实际项目中使用它们2025-04-07
- will-change 是一个 CSS 属性,用于告诉浏览器某个元素在未来可能会发生哪些变化,本文给大家介绍CSS will-change 属性详解,感兴趣的朋友一起看看吧2025-04-07
- 本文给大家分享在 CSS 中,去除a标签(超链接)的下划线的几种方法,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧2025-04-07
在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将2025-04-07css中的 vertical-align与line-height作用详解
文章详细介绍了CSS中的`vertical-align`和`line-height`属性,包括它们的作用、适用元素、属性值、常见使用场景、常见问题及解决方案,感兴趣的朋友跟随小编一起看看吧2025-03-26浅析CSS 中z - index属性的作用及在什么情况下会失效
z-index属性用于控制元素的堆叠顺序,值越大,元素越显示在上层,它需要元素具有定位属性(如relative、absolute、fixed或sticky),本文给大家介绍CSS 中z - index属性的作用2025-03-21- 文章详细介绍了CSS中的打印媒体查询@mediaprint包括基本语法、常见使用场景和代码示例,如隐藏非必要元素、调整字体和颜色、处理链接的URL显示、分页控制、调整边距和背景等2025-03-18

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)
本文介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,感兴趣的朋友一起2025-03-10
前端 CSS 动态设置样式::class、:style 等技巧(推荐)
本文介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外2025-02-26





最新评论