CSS 真的会阻塞文档解析吗?
在网页开发领域,一个常见的疑问是 CSS 是否会阻塞文档解析。理解这一问题对于优化网页性能、提升用户体验至关重要。要深入解答这个问题,需要从浏览器渲染网页的原理说起。
浏览器渲染网页的基本流程
浏览器在接收到 HTML 文档后,会依次进行以下几个主要步骤:
- 解析 HTML:浏览器从网络或本地获取 HTML 文件,然后开始解析,将 HTML 代码转换为 DOM(Document Object Model,文档对象模型)树。DOM 树是 HTML 文档的树形表示,它以节点的形式描述了页面的结构,比如标签之间的层级关系等。
- 构建 CSSOM:同时,浏览器会解析 CSS 代码,无论是内部样式表、外部样式表还是内联样式,都会被解析并构建成 CSSOM(CSS Object Model,CSS 对象模型)树。CSSOM 树描述了页面元素的样式信息,用于后续计算元素的最终样式。
- 合成渲染树:DOM 树和 CSSOM 树构建完成后,浏览器将两者结合,根据 DOM 中元素的结构和 CSSOM 中定义的样式,生成渲染树(Render Tree)。渲染树只包含那些需要显示在页面上的元素及其样式信息,例如
CSS 与文档解析的关系
从上述流程可以看出,CSS 本身并不直接阻塞 HTML 文档的解析。也就是说,浏览器在下载 HTML 文档的过程中,会一边下载一边解析,不会因为等待 CSS 的加载而暂停 HTML 的解析。然而,在实际情况中,CSS 确实可能导致文档解析的延迟,这主要与 JavaScript 脚本的执行以及渲染树的构建有关。
JavaScript 脚本执行的影响
由于 JavaScript 脚本可以操作 DOM 和 CSSOM,当浏览器在解析 HTML 过程中遇到
<!DOCTYPE html>
<html lang="en"><head><link rel="stylesheet" href="styles.css">
</head><body><div id="myDiv">这是一个测试div</div><script>const div = document.getElementById('myDiv');// 获取div的样式属性,比如宽度const width = window.getComputedStyle(div).width; console.log(width);</script>
</body></html>
在这个例子中,如果styles.css还没有完成下载和解析,当 JavaScript 脚本执行到获取元素样式的代码时,由于此时 CSSOM 尚未构建完成,获取到的样式值可能是错误的。为了避免这种情况,浏览器会延迟 JavaScript 脚本的执行以及 HTML 文档的解析,直到 CSSOM 构建完成。
渲染树构建的要求
渲染树的构建依赖于 DOM 树和 CSSOM 树。如果 CSS 还在加载或解析过程中,那么 CSSOM 树就不完整,此时无法准确构建渲染树。例如,假设一个网页中有大量复杂的 CSS 规则来定义元素的显示和隐藏、定位等样式,如果这些 CSS 没有加载完毕,浏览器无法确定哪些元素应该显示在页面上,也就无法正确构建渲染树。因此,在这种情况下,浏览器也会等待 CSS 的加载和解析,这间接导致了 HTML 文档解析的阻塞。
先加载 JavaScript 后加载 CSS 的问题及影响
若先加载 JavaScript 后加载 CSS,会引发一系列问题。
首先是页面闪烁,JavaScript 代码可能会操作 DOM,例如修改元素的显示、隐藏状态或样式等。由于 CSS 尚未加载,页面初始会以默认样式呈现,当 JavaScript 执行完相关操作后,CSS 才加载完成并应用样式,这就可能导致页面元素在短时间内从默认样式切换到最终样式,产生闪烁现象。比如一个图片元素原本在 JavaScript 中被设置为display:none,但 CSS 中又定义了其正常显示且有特定样式,用户可能会先看到图片消失,然后又突然出现并带有样式,影响视觉体验。
其次,脚本执行可能出现异常。JavaScript 脚本可能会依赖 CSS 样式来获取准确的元素尺寸、位置等信息进行操作。如果 CSS 未加载完成,那么getComputedStyle等获取样式的方法返回的值可能不准确。例如,在一个轮播图的 JavaScript 代码中,需要根据图片的宽度来计算切换动画的距离,若 CSS 未加载,获取的图片宽度可能是错误的,导致轮播图动画效果异常。
再者,渲染性能会下降。浏览器在渲染页面时,需要结合 DOM 和 CSSOM 构建渲染树。若先加载 JavaScript,而 JavaScript 又可能对 DOM 进行大量修改,之后 CSS 加载完成再应用样式,浏览器可能需要多次重新计算布局和重新渲染,增加了渲染的复杂性和时间成本,降低了渲染性能。
此外,当 JavaScript 修改 CSS 时,也存在潜在风险。恶意的 JavaScript 代码若被注入网页,就可能篡改 CSS 样式,破坏页面的布局和视觉效果。例如,将原本用于隐藏敏感信息的 CSS 样式修改为显示,从而导致信息泄露;或者恶意改变页面的字体、颜色、排版等,影响用户对页面内容的正常理解和使用。即便 CSS 已加载完成,JavaScript 操作 CSS 仍可能引发新问题。大量频繁的 JavaScript - CSS 操作,如在循环中不断修改元素的 CSS 属性,会导致浏览器频繁重新计算布局和重新绘制,严重影响页面性能。例如,通过 JavaScript 循环快速改变一个列表中所有项的背景颜色,页面会出现明显卡顿。而且,JavaScript 代码逻辑错误也可能导致 CSS 样式被错误修改。比如,错误地选择了元素,将原本应用于导航栏的样式错误地应用到了内容区域,破坏页面的视觉呈现。
解决办法
针对先加载 JavaScript 后加载 CSS 出现的问题,以及 JavaScript 修改 CSS 带来的潜在风险,有以下解决办法。
对于非关键的 JavaScript 脚本,可以使用async属性。
<script async src="script.js"></script>
,async会让浏览器在下载完脚本后立即执行,不会阻塞页面的解析和其他资源的加载,这样可以在一定程度上减少 JavaScript 对 CSS 加载的影响。
而对于需要按顺序执行且不会阻塞页面渲染的脚本,使用defer属性,<script defer src="script.js"></script>
、,defer会使脚本在 HTML 解析完成后、DOMContentLoaded 事件触发前执行,确保在 CSS 加载完成后再执行脚本,避免脚本执行时因 CSS 未加载而获取错误样式信息。
另外,将关键的 CSS 样式直接写在 HTML 文件的style标签内,这样浏览器在解析 HTML 时就能立即应用这些样式,减少页面闪烁的可能性。
例如,对于页面的基本布局样式、字体样式等关键部分进行内联,保证页面初始显示的基本样式正确,后续再加载外部 CSS 文件来补充完整样式。
同时,在 JavaScript 代码中,避免在 CSS 未加载完成时就进行依赖样式的操作。可以通过监听DOMContentLoaded事件,确保 DOM 和 CSSOM 都已准备好后再执行相关逻辑。
例如:
document.addEventListener('DOMContentLoaded', function() {// 这里写依赖样式的JavaScript代码
});
实际案例分析
以一个电商网站的产品详情页为例。该页面包含丰富的产品图片、描述文字、价格信息以及购买按钮等元素,同时有大量的 CSS 代码用于控制页面的布局和样式,比如设置图片的尺寸和排列方式、文字的字体和颜色、按钮的样式和交互效果等。
当用户访问该页面时,浏览器开始下载 HTML 文档。在解析 HTML 过程中,遇到了外部 CSS 文件的链接,于是同时开始下载 CSS 文件。然而,由于 CSS 文件较大,包含了许多针对不同屏幕尺寸的响应式样式以及复杂的动画效果样式,下载和解析时间较长。
在 HTML 文档中,还包含一些用于实现交互功能的 JavaScript 代码,比如当用户点击某个产品特性标签时,显示或隐藏相关的详细说明。这些 JavaScript 代码在执行时,需要获取页面元素的当前样式来进行相应的操作。例如,判断某个元素是否已经应用了特定的隐藏样式,从而决定是显示还是隐藏该元素。
由于 CSS 文件尚未完成下载和解析,CSSOM 树不完整,JavaScript 无法获取到准确的样式信息。为了保证 JavaScript 能够正确执行,浏览器会暂停 HTML 文档的解析,等待 CSSOM 构建完成。这就导致了整个页面的渲染延迟,用户可能会看到页面长时间处于空白或部分加载的状态,影响了用户体验。
综上所述,虽然 CSS 本身并不直接阻塞 HTML 文档的解析,但在与 JavaScript 脚本执行以及渲染树构建相关的情况下,CSS 的加载和解析过程可能会导致文档解析的延迟。同时,先加载 JavaScript 后加载 CSS 会带来诸多问题,JavaScript 对 CSS 的修改也存在潜在风险。网页开发者在优化页面性能时,需要充分考虑这些因素,例如合理优化 CSS 代码,减少其体积和复杂度,采用异步加载 CSS 的方式,以及合理安排 JavaScript 代码的执行顺序等,以确保页面能够快速、流畅地渲染,同时保障网页的安全性和稳定性。
相关文章:
CSS 真的会阻塞文档解析吗?
在网页开发领域,一个常见的疑问是 CSS 是否会阻塞文档解析。理解这一问题对于优化网页性能、提升用户体验至关重要。要深入解答这个问题,需要从浏览器渲染网页的原理说起。 浏览器渲染网页的基本流程 浏览器在接收到 HTML 文档后,会依次进行…...

大模型的UI自动化:Cline 使用Playwright MCP Server完成测试
大模型的UI自动化:Cline 使用Playwright MCP Server完成测试 MCP MCP(Model Context Protocol),是一个开发的协议,标准化了应用程序如何为大模型提供上下文。MCP提供了一个标准的为LLM提供数据、工具的方式,使用MCP会更容易的构建Agent或者是基于LLM的复杂工作流。 最近…...

碰撞检测 | 图解凸多边形分离轴定理(附ROS C++可视化)
目录 0 专栏介绍1 凸多边形碰撞检测2 多边形判凸算法3 分离轴定理(SAT)4 算法仿真与可视化4.1 核心算法4.2 仿真实验 0 专栏介绍 🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线…...
Python 基本数据类型
目录 1. 字符串(String) 2. 列表(List) 3. 字典(Dictionary) 4. 集合(Set) 5. 数字(Number) 6. 布尔值(Boolean) 1. 字符串&…...

突破“第一崇拜“:五维心理重构之路
一、视频介绍 在这个崇尚"第一"的时代,我们如何找到自己的独特价值?本视频将带您踏上五维心理重构之旅,从诗意人生的角度探讨如何突破"圣人之下皆蝼蚁"的局限。我们将穿越人生的不同阶段,从青春的意气风发到…...

KubeKey一键安装部署k8s集群和KubeSphere详细教程
目录 一、KubeKey简介 二、k8s集群KubeSphere安装 集群规划 硬件要求 Kubernetes支持版本 操作系统要求 SSH免密登录 配置集群时钟 所有节点安装依赖 安装docker DNS要求 存储要求 下载 KubeKey 验证KubeKey 配置集群文件 安装集群 验证命令 登录页面 一、Ku…...
UE5网络通信架构解析
文章目录 前言一、客户端-服务器架构(C/S Model)二、对等网络架构(P2P,非原生支持)三、混合架构(自定义扩展)四、UE5网络核心机制 前言 UE5的网络通信主要基于客户端-服务器(C/S&am…...

实验3 知识表示与推理
实验3 知识表示与推理 一、实验目的 (1)掌握知识和知识表示的基本概念,理解其在AI中的深刻含义与意义; (2)熟悉AI中常用的知识表示方法的优缺点及其应用场景; (3)掌握产…...

基于Springboot银行信用卡额度管理系统【附源码】
基于Springboot银行信用卡额度管理系统 效果如下: 系统登陆页面 用户个人中心页面 新增信用卡申请页面 评估审核页面 管理员主页面 评估审核页面 操作日志管理页面 消费页面 研究背景 随着金融行业的快速发展和信息技术的不断进步,信用卡作为一种便捷…...
达梦数据库学习笔记@1
目录 达梦数据库学习笔记一、表空间管理(一)默认表空间(二)相关数据字典(三)表空间操作(四)临时表空间管理 二、重做日志管理(一)系统视图(二&…...

图像处理篇---图像处理中常见参数
文章目录 前言一、分贝(dB)的原理1.公式 二、峰值信噪比(PSNR, Peak Signal-to-Noise Ratio)1.用途2.公式3.示例 三、信噪比(SNR, Signal-to-Noise Ratio)1.用途2.公式3.示例 四、动态范围(Dyna…...

AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践
前言 自2022年末ChatGPT的问世,大语言模型(LLM)技术引发全球关注。在大模型技术落地的最佳实践中,智能体(Agent)架构显现出巨大潜力,成为业界的普遍共识,各大公司也纷纷启动Agent技…...
50周学习go语言:第1周 环境搭建
以下是为零基础学习者准备的详细第1周教程,包含环境搭建、工具配置和首个Go程序的完整操作指南: 一、Go语言环境安装(Windows/macOS/Linux通用) 1. 下载安装包 官网地址:https://go.dev/dl//根据系统选择对应版本&am…...

4. MySQL 逻辑架构说明
4. MySQL 逻辑架构说明 文章目录 4. MySQL 逻辑架构说明1. 逻辑架构剖析1.1 服务器处理客户端请求1.2 Connectors(连接器)1.3 第1层:连接层1.4 第2层:服务层1.5 第3层:引擎层1.6 存储层 2. SQL执行流程2.1 MySQL 中的 SQL 执行流程 2.2 MySQL…...
《AI与NLP:开启元宇宙社交互动新纪元》
在科技飞速发展的当下,元宇宙正从概念逐步走向现实,成为人们关注的焦点。而在元宇宙诸多令人瞩目的特性中,社交互动体验是其核心魅力之一。人工智能(AI)与自然语言处理(NLP)技术的迅猛发展&…...

面对STM32的庞大体系,如何避免迷失在细节中?
我第一次接触STM32时,我以为抱着开发板就是拥抱未来,实际上一开机就喜提四大耳光,看到卖家演示的MP3播放、TFT彩屏、网口通信好炫酷,忍不住买回来掌握这些神技,到最后发现最实用的还是开发板的关机键和复位键。 看视频…...
ragflow-RAPTOR到底是什么?请通俗的解释!
RAPTOR有两种不同的含义,具体取决于上下文: RAPTOR作为一种信息检索技术 RAPTOR是一种基于树状结构的信息检索系统,全称为“Recursive Abstractive Processing for Tree-Organized Retrieval”(递归抽象处理树组织检索)…...

Linux系统移植之Uboot启动流程
Linux系统移植之Uboot启动流程 一,Uboot启动流程1.Uboot的两阶段1.1.第一阶段1.11.硬件初始化1.12.复制 U-Boot 到 RAM1.13.跳转到第二阶段 1.2.第二阶段1.21.C 语言环境初始化1.22. 硬件设备初始化1.23. 加载环境变量1.24. 显示启动信息1.25. 等待用户输入…...

【Open X-Embodiment】简单数据下载与预处理
文章目录 1. RLDS Dataset2. 处理成numpy格式3. 存储桶 1. RLDS Dataset 从 Octo 里面找到数据下载的代码 rlds_dataset_mod github 按照官网代码配置环境后,修改 prepare_open_x.sh,相当于只用 gsutil 下载数据: DOWNLOAD_DIR/mnt/data…...

【第四节】C++设计模式(创建型模式)-Builder(建造者)模式
目录 引言 一、Builder 模式概述 二、Builder 模式举例 三、Builder 模式的结构 四、Builder 模式的实现 五、Builder 模式的优缺点 六、总结 引言 Builder 模式是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离。通过一步步构建对象,…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...