likes
comments
collection
share

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

作者站长头像
站长
· 阅读数 42

项目背景

最近发现项目中偶现CSS优先级错乱的问题:某个 div 标签绑定了两个类名,分别是 form-root-wrapsetting-root-wrap,其中 form-root-wrap 类名对应的CSS样式是放在主HTML文档Head标签中的 form-main-chunk.css 文件中,首次渲染时该样式就会作用到 form-root-wrap 类名上;而 setting-root-wrap 类名对应的CSS样式是放在 framework_form_routes_setting-*.css 文件中,而该CSS文件是异步的,会在用户触发某个交互后(比如:切换路由)才会去加载,一般来说异步加载的CSS文件会创建link标签并append到HTML文件Head标签底部。所以不管从CSS文件加载先后顺序来讲,还是离目标 div 标签距离远近来说,setting-root-wrap 的CSS优先级肯定要高于 form-root-wrap,而且项目的初衷也是要用 setting-root-wrap 的样式去覆盖 form-root-wrap 的部分样式,但事实结果与所想恰好相反,form-root-wrap 的样式优先级大于 setting-root-wrap 🤔。

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

图1: 标签与样式示意图

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

图2: *form-main-chunk.css* 文件在HTML主文档的位置(下载时form-main-chunk.css还在head标签中)

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

图3: framework_form_routes_setting-*.css 异步文件加载时机与位(head底部)

现象探索

先后在Chrome、Safari、FireFox等诸多主流浏览器均进行了测试,得到的结果完全一致(form-root-wrap 样式优先级均大于 setting-root-wrap 样式优先级)。在Chrome Devtools 的 Elements 中尝试去搜索这两个CSS文件时却发现,framework_form_routes_setting-*.css 文件的所在位置与认知一致(在Head标签底部),而 form-main-chunk.css 文件却出现在了 body 标签中(HTML文档下载时form-main-chunk.css还在head标签中))

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

图4: form-main-chunk.css 与 framework_form_routes_setting-*.css 文件位置

不过这倒也解释了 form-root-wrap 的样式优先级为什么大于 setting-root-wrap。但明明HTML主文档下载时form-main-chunk.css 还在Head标签内,为什么在Elements预览中却出现在了Body标签中。

罪魁祸首

如图所示,罪魁祸首就是Head标签中的这个Div => <div id="toggle-config"></div>。浏览器解析这个Head中Div时会将其本身以及之后的所有标签元素均放到Body标签的顶部。

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

图5: HTML文件下载时Head中的Div元素及其之后元素的位置

HTML head标签中错误的div标签引发的思考...CSS优先级错乱问题思考:HTML文档Head标签内如有不规范的

图6: HTML解析后Head中的Div元素及其之后元素的位置(Chrome DevTools Elements)

归因分析

<div id="toggle-config"></div> 是前端webpack构建生产脚本时生成的固定模板字符串,而标签的本意是与数据中台约定好的模板字符串。前端的HTML请求到达NG后,会将该请求转发到某个webserver,这个webserver会根据请求路由与cookie去找到对应的镜像并拉取HTML资源,同时请求数据中台获取toggle_config相关的数据,并将HTML资源中的<div id="toggle-config"></div> 替换成类似于 <script>window.toggle=...</script>(当然如果数据中台报错或者超时,替换操作肯定就不会发生了,原来的div标签就被保留了下来)。所以主要归因还是前端构建时不应该把这个标签插入到head中,老老实实放到body就不会有这种偶现bug了。

最后的最后...

这里只分析了现象,但是还是没有找到这个问题依据(🤔Head忽略div或者仅仅把div放到body里都能理解)

为什么浏览器解析Head中Div时会将其本身以及之后的所有标签元素均放到Body标签顶部。

希望大佬们不吝赐教。

转载自:https://juejin.cn/post/7422888182494609446
评论
请登录