整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

浏览器工作原理

览器(也称为网络浏览器或互联网浏览器)是安装在我们设备上的软件应用程序,使我们能够访问万维网。在阅读这篇文字时,你实际上正在使用一个浏览器。

有许多浏览器正在被使用,截至2022年,使用最多的是:谷歌浏览器、苹果的Safari、微软的Edge和火狐。

但是,它们实际上是如何工作的,从我们在地址栏中键入网络地址开始,到我们试图访问的页面显示在屏幕上,会发生什么?

关于这个问题的答案,一个极其简化的版本是:

当我们从一个特定的网站请求一个网页时,浏览器从网络服务器检索必要的内容,然后在我们的设备上显示该网页。

很直接,对吗?是的,但在这个看似超级简单的过程中还涉及更多的内容。在这个系列中,我们将讨论导航获取数据解析渲染等步骤,并希望能使你对这些概念更清晰。

1.导航

导航是加载网页的第一步。它指的是当用户通过点击一个链接在浏览器地址栏中写下一个网址提交一个表格等方式请求一个网页时发生的过程。

DNS 查询(解决网址问题)

导航到一个网页的第一步是找到该网页的静态资源位置(HTML、CSS、Javascript和其他类型的文件)。如果我们导航到 https://example.com ,HTML 页面位于 IP 地址为 93.184.216.34 的服务器上(对我们来说,网站是域名,但对计算机来说,它们是 IP 地址)。如果我们以前从未访问过这个网站,就必须进行域名系统(DNS)查询。

DNS 服务器是包含公共 IP 地址及其相关主机名数据库的计算机服务器(这通常被比作电话簿,因为人们的名字与一个特定的电话号码相关联)。在大多数情况下,这些服务器按照要求将这些名字解析或翻译成 IP 地址(现在有 600 多个不同的 DNS 根服务器分布在世界各地)。

因此,当我们请求进行 DNS 查询时,我们实际做的是与这些服务器中的一个进行对话,要求找出与https://example.com 名称相对应的IP地址。如果找到了一个对应的 IP,就会返回。如果发生了一些情况,查找不成功,我们会在浏览器中看到一些错误信息。

在这个最初的查询之后,IP 地址可能会被缓存一段时间,所以下次访问同一个网站会更快,因为不需要进行 DNS 查询(记住,DNS 查询只发生在我们第一次访问一个网站时)。

TCP (Transmission Control Protocol) 握手

一旦浏览器知道了网站的 IP 地址,它将尝试通过 TCP 三次握手(也称为 SYN-SYN-ACK,或者更准确的说是 SYN、SYN-ACK、ACK,因为 TCP 有三个消息传输,用于协商和启动两台计算机之间的TCP 会话),与持有资源的服务器建立连接。

TCP 是传输控制协议的缩写,是一种通信标准,使应用程序和计算设备能够在网络上交换信息。它被设计用来在互联网上发送数据包,并确保数据和信息在网络上成功传递。

TCP 握手是一种机制,旨在让两个想要相互传递信息的实体(在我们的例子中是浏览器和服务器)在传输数据之前协商好连接的参数。

>

因此,如果浏览器和服务器是两个人,他们之间的对话会是这样的:

浏览器向服务器发送一个 SYNC 消息,要求进行同步(同步意味着连接)

然后,服务器将回复一个 SYNC-ACK 消息( SYNChronization 和 ACKnowledgement)

在最后一步,浏览器将回复一个 ACK 信息

现在,TCP连接(双向连接)已经通过3次握手建立,TLS协商可以开始。

TLS协商

对于通过 HTTPS 建立的安全连接,需要进行另一次握手。这种握手(TLS协商)决定了哪个密码将被用于加密通信,验证服务器,并在开始实际的数据传输之前建立一个安全的连接。

传输层安全(TLS)是现已废弃的安全套接字层(SSL)的继任者,是一种加密协议,旨在通过计算机网络提供通信安全。该协议被广泛用于电子邮件和即时通讯等应用,但它在确保 HTTPS安全方面的应用仍然是最公开的。由于应用程序可以使用或不使用 TLS(或SSL)进行通信,因此客户(浏览器)有必要要求服务器建立 TLS 连接。

在这一步骤中,浏览器和服务器之间还交换了一些信息

  1. 客户端 hello。浏览器向服务器发送一条信息,其中包括它所支持的TLS版本和密码套件,以及一串随机字节,称为 客户端随机数
  2. 服务器 hello 和证书。服务器发回一条信息,其中包括服务器的SSL证书、服务器选择的密码套件和服务器随机数,这是服务器生成的另一个随机字节串。
  3. 认证。浏览器会向颁发证书的机构核实服务器的 SSL 证书。这样,浏览器就可以确定服务器就是它所说的那个人。
  4. 预主密码。浏览器会再发送一串随机的字节,称为主密钥,用浏览器从服务器的 SSL 证书上获取的公钥进行加密。主密码只能由服务器用私钥解密。
  5. 使用私钥。服务器解密预主密码
  6. 创建会话密钥。浏览器和服务器从客户端随机数、服务器随机数和预主密码中生成会话密钥。
  7. 客户端完成。浏览器向服务器发送一个消息,说它已经完成。
  8. 服务器完成。服务器向浏览器发送一个消息,表示它也完成了。
  9. 安全对称加密实现。握手完成,通信可以继续使用会话密钥。

现在可以开始从服务器请求和接收数据了

2.获取数据

在上一节中,我们谈到了导航,这是浏览器显示网站的第一步。现在,我们将进入下一个步骤,看看如何获取资源

HTTP 请求

在我们与服务器建立安全连接后,浏览器将发送一个初始的 HTTP GET 请求。首先,浏览器将请求页面的 HTML 文件。它将使用 HTTP 协议来做这件事。

HTTP(超文本传输协议)是一个获取资源的协议,如HTML文件。它是网络上任何数据交换的基础,它是一个客户-服务器协议,这意味着请求是由接收者发起的,通常是网络浏览器。

请求方法 - POST, GET, PUT, PATCH, DELETE 等

URI - 是统一资源识别符的缩写。URIs 用于识别互联网上的抽象或物理资源,如网站或电子邮件地址等资源。一个 URI 最多可以有 5 个部分

scheme:用于说明使用的是什么协议

authority:用于识别域名

path:用于显示资源的确切路径

query:用于表示一个请求动作

fragment:用来指代资源的一部分

// URI parts
scheme :// authority path ? query # fragment

//URI example
<https://example.com/users/user?name=Alice#address>

https: // scheme name
example.com // authority
users/user // path
name=Alice // query
address // fragment

HTTP 头字段 - 是浏览器和服务器在每个 HTTP 请求和响应中发送和接收的字符串列表(它们通常对终端用户是不可见的)。在请求的情况下,它们包含关于要获取的资源或请求资源的浏览器的更多信息。

如果你想看看这些请求头字段是什么样子的,请进入 Chrome 浏览器并打开开发者工具(F12)。进入 Network 标签,选择 FETCH/XHR。在下面的屏幕截图中,我刚刚在搜索引擎上搜索了Palm Springs,这就是请求头的样子。

HTTP 响应

一旦服务器收到请求,它将对其进行处理并回复一个 HTTP 响应。在响应的正文中,我们可以找到所有相关的响应头和我们请求的HTML文档的内容

状态代码 - 例如:200、400、401、504网关超时等(我们的目标是 200 状态代码,因为它告诉我们一切正常,请求是成功的)

响应头字段 - 保存关于响应的额外信息,如它的位置或提供它的服务器。

一个 HTML 文档的例子可以是这样的

<!doctype HTML>
<html>
 <head>
  <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>我的页面</title>
  <link rel="stylesheet" src="styles.css"/>
  <script src="mainScripts.js"></script>
</head>
<body>
  <h1 class="heading">这个是我的页面</h1>
  <p>一个段落和一个 <a href="<https://example.com/about>">链接</a></p>
  <div>
    <img src="myImage.jpg" alt="image description"/>
  </div>
  <script src="sideEffectsScripts.js"></script>
</body>
</html>

对于我前面提到的同一个搜索,响应头是这样的

如果我们看一下HTML文档,我们会发现它引用了不同的 CSS 和 Javascript 文件。这些文件不会被请求。在这个时候,只有 HTML 被请求并从服务器接收。

这个初始请求的响应包含收到的第一个字节的数据。第一个字节的时间(TTFB)是指从用户提出请求(在地址栏中输入网站名称)到收到第一个 HTML 数据包(通常为14kb)的时间。

TCP 慢启动和拥塞算法

TCP 慢启动 是一种平衡网络连接速度的算法。 第一个数据包将是 14kb(或更小),其工作方式是逐渐增加传输的数据量,直到达到预定的阈值。 从服务器接收到每个数据包后,客户端以 ACK 消息响应。 由于连接容量有限,如果服务器发送太多数据包太快,它们将被丢弃。 客户端不会发送任何 ACK 消息,因此服务器会将此解释为拥塞。 这就是拥塞算法发挥作用的地方。 他们监控发送的数据包和 ACK 消息的流,以确定流量的最佳速率并创建稳定的流量流。

3.HTML 解析

到目前为止,我们讨论了导航和数据获取。 今天我们将讨论解析,特别是 HTML 解析

我们看到在向服务器发出初始请求后,浏览器如何收到包含我们尝试访问的网页的 HTML 资源(第一块数据)的响应。 现在浏览器的工作就是开始解析数据。

解析是指将程序分析并转换为运行时环境实际可以运行的内部格式

换句话说,解析意味着将我们编写的代码作为文本(HTML、CSS)并将其转换为浏览器可以使用的内容。 解析将由浏览器引擎完成(不要与浏览器的 Javascript 引擎混淆)。

浏览器引擎是每个主要浏览器的核心组件,它的主要作用是结合结构 (HTML) 和样式 (CSS),以便它可以在我们的屏幕上绘制网页。 它还负责找出哪些代码片段是交互式的。 我们不应将其视为一个单独的软件,而应将其视为更大软件(在我们的例子中为浏览器)的一部分。

有许多浏览器引擎,但大多数浏览器使用这三个活跃且完整引擎之一:

Gecko 它是由 Mozilla 为 Firefox 开发的。 过去,它曾为其他几种浏览器提供支持,但目前,除了 Firefox,Tor 和 Waterfox 是唯一仍在使用 Gecko 的浏览器。 它是用 C++ 和 JavaScript 编写的,自 2016 年起,还用 Rust 编写。

WebKit 它主要由 Apple 为 Safari 开发。 它还为 GNOME Web (Epiphany) 和 Otter 提供支持。 (令人惊讶的是,在 iOS 上,包括 Firefox 和 Chrome 在内的所有浏览器也由 WebKit 提供支持)。 它是用 C++ 编写的。

Blink,Chromium 的一部分 它最初是 WebKit 的一个分支,主要由 Google 为 Chrome 开发。 它还为 Edge、Brave、Silk、Vivaldi、Opera 和大多数其他浏览器项目(一些通过 QtWebEngine)提供支持。 它是用 C++ 编写的。

现在我们了解了谁将进行解析,让我们看看在从服务器接收到第一个 HTML 文档后到底发生了什么。 让我们假设文档如下所示:

<!doctype HTML>
<html>
 <head>
  <title>This is my page</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <h1>This is my page</h1>
  <h3>This is a H3 header.</h3>
  <p>This is a paragraph.</p>
  <p>This is another paragraph,</p>
</body>
</html>

即使请求页面的 HTML 大于初始的 14KB 数据包,浏览器也会开始解析并尝试根据其拥有的数据呈现体验。 HTML 解析涉及两个步骤:词法分析树构造(构建称为 DOM 树的东西)。

词法分析

它将一些输入转换为标签(源代码的基本组件)。 想象一下,我们将一段英文文本分解成单词,其中单词就是标签。

词法分析过程结束时的结果是一系列 0 个或多个以下标签:DOCTYPE、开始标签 (<tag>)、结束标签(</tag>)、自闭合标签 (<tag/>) 、属性名称、值、注释、字符、文件结尾或元素中的纯文本内容。

构建 DOM

创建第一个 token 后,树构建开始。 这实质上是基于先前解析的标签创建树状结构(称为文档对象模型)。

DOM 树描述了 HTML 文档的内容。 <html> 元素是文档树的第一个标签和根节点。 树反映了不同标签之间的关系和层次结构。 我们有父节点,嵌套在其他标签中的标签是子节点。 节点数越多,构建 DOM 树所需的时间就越长。 下面是我们从服务器获得的 HTML 文档示例的 DOM 树:

实际上,DOM 比我们在该模式中看到的更复杂,但我保持简单以便更好地理解(另外,我们将在以后的文章中更详细地讨论 DOM 及其重要性)。

此构建阶段是可重入的,这意味着在处理一个 token 时,分词器可能会恢复,导致在第一个 token 处理完成之前触发并处理更多 token。 从字节到创建 DOM,整个过程如下所示:

解析器从上到下逐行工作。 当解析器遇到非阻塞资源(例如图像)时,浏览器会向服务器请求这些图像并继续解析。 另一方面,如果它遇到阻塞资源(CSS 样式表、在 HTML 的 部分添加的 Javascrpt 文件或从 CDN 添加的字体),解析器将停止执行,直到所有这些阻塞资源都被下载。 这就是为什么,如果你正在使用 Javascript,建议在 HTML 文件的末尾添加<script> 标签,或者如果你想将它们保留在 <head> 标签中,你应该向它们添加 defer 或 async 属性( async 允许在下载脚本后立即执行异步操作,而 defer 只允许在整个文档被解析后执行。)。

预加载器 & 使页面更快

Internet Explorer、WebKit 和 Mozilla 都在 2008 年实现了预加载器,作为处理阻塞资源的一种方式,尤其是脚本(我们之前说过,当遇到脚本标签时,HTML 解析将停止,直到脚本被下载并执行)。

使用预加载器,当浏览器卡在脚本上时,第二个较轻的解析器会扫描 HTML 以查找需要检索的资源(样式表、脚本等)。 然后预加载器开始在后台检索这些资源,目的是在主 HTML 解析器到达它们时它们可能已经被下载(如果这些资源已经被缓存,则跳过此步骤)。

4.解析 CSS

解析完 HTML 之后,就该解析 CSS(在外部 CSS 文件和样式元素中找到)并构建 CSSOM 树(CSS 对象模型)。

当浏览器遇到 CSS 样式表时,无论是外部样式表还是嵌入式样式表,它都需要将文本解析为可用于设置布局样式的内容。 浏览器将 CSS 变成的数据结构称为 CSSOM。 DOM 和 CSSOM 遵循相似的概念,因为它们都是树,但它们是不同的数据结构。 就像从我们的 HTML 构建 DOM 一样,从 CSS 构建 CSSOM 被认为是一个「渲染阻塞 」过程。

词法分析和构建 CSSOM

与 HTML 解析类似,CSS 解析从词法分析开始。 CSS 解析器获取字节并将它们转换为字符,然后是标签,然后是节点,最后它们被链接到 CSSOM 中。 浏览器会执行一些称为选择器匹配的操作,这意味着每组样式都将与页面上的所有节点(元素)匹配。

浏览器从适用于节点的最通用规则开始(例如:如果节点是 body 元素的子节点,则所有 body 样式都由该节点继承),然后通过应用更具体的规则递归地优化计算出的样式。 这就是为什么我们说样式规则是级联的。

假设我们有下面的 HTML 和 CSS:

body {
  font-size: 16px;
  color: white;
} 

h1 {
  font-size: 32px;
}

section {
  color: tomato;
}

section .mainTitle {
  margin-left: 5px
}

div {
  font-size: 20px;
}

div p {
  font-size:  8px;
  color: yellow;
}

这段代码的 CSSOM 看起来像这样:

请注意,在上面的模式中,嵌套元素既有继承的样式(来自父级 - 例如:h1 从 body 继承其颜色,section 从 body 继承其字体大小)和它们自己的样式(可以覆盖继承的规则 是否来自父节点 - 例如:p 覆盖了从 div 继承的颜色和字体大小,而 mainTitle 没有从父节点获得其左边距)。

由于我们的 CSS 可以有多个来源,并且它们可以包含适用于同一节点的规则,因此浏览器必须决定最终应用哪个规则。 这就是优先级发挥作用的时候,如果您想了解更多相关信息,可以访问此页面。

想象一下,您在机场寻找您的朋友 John。 如果你想通过喊他的名字找到他,你可以喊 “ John ”。 可能不止一个 John 会同时出现在机场,所以他们可能都会做出回应。 更好的方法是用他的全名打电话给你的朋友,这样当你喊“John Doe”时,你就有更好的机会找到他,因为“ John Doe ”比“ John ”更具体。

同样,假设我们有这个元素:

<p>
  <a href="<https://dev.to/>">This is just a link!</a>
</p>

以及这些 CSS 样式:

a {
   color: red;
}

p  a {
   color: blue;
}

您认为浏览器会应用哪条规则? 答案是第二条规则,因为 p 标签中的所有 a 标签选择器比所有a 标签选择器都具有更高的优先级。 如果你想玩玩优先级,你可以使用这个 优先级计算器。

重点

CSS 规则是从右到左阅读的,这意味着如果我们有这样的代码: section p { color: blue; }, 浏览器将首先查找页面上的所有 p 标签,然后它会查看这些 p 标签中是否有一个 section 标签作为父标签。 如果查找能够命中,它将应用这个 CSS 规则

5. 执行 Javascript

在解析 CSS 并创建 CSSOM 的同时,还会下载其他资产,包括 JavaScript 文件。 这要归功于我们在之前文章中提到的预加载器。

预加载器就像一个解析器,它在主解析器处理 HTML 代码时扫描 HTML 文件。 它的作用是查找样式表、脚本或图片(也需要从服务器检索)等资源并请求它们。 希望在解析 HTML 时,这些资源已经下载并准备好进行处理。

所以,当我们从服务器获取 Javascript 文件后,代码被解释、编译、解析和执行。 计算机无法理解 Javascript 代码,只有浏览器可以。 JS 代码需要被翻译成计算机可以使用的东西,这是 Javascript 浏览器引擎的工作(不要与浏览器引擎混淆)。 根据浏览器的不同,JS 引擎可以有不同的名称和不同的工作方式。

Javascript 引擎

javascript 引擎(有时也称为 ECMAScript 引擎)是一种在浏览器中执行(运行)Javascript 代码的软件,而不仅仅是零部件(例如,V8 引擎是 Node.js 环境的核心组件)。

JavaScript 引擎通常由 Web 浏览器供应商开发,每个主要浏览器都有一个。 我们说过,目前使用最多的浏览器是 Chrome、Safari、Edge 和 Firefox。 每个都使用不同的 Javascript 引擎,它们是:

V8 V8 是 Google 的高性能 JavaScript 引擎。 它是用 C++ 编写的,用于 Chrome 和 Node.js 等。 它实现了 ECMAScript(一种 JavaScript 标准,旨在确保网页在不同 Web 浏览器之间的互操作性)和 WebAssembley。 它实现了 ECMA-262。

JavaScriptCore JavaScriptCore 是 WebKit 的内置 JavaScript 引擎,它为 Safari 浏览器、邮件和 macOS 上使用的其他应用程序提供支持。 它目前按照 ECMA-262 规范实现 ECMAScript。 它也被称为 SquirrelFish 或 SquirrelFish Extreme。

Chakra Chakra 是微软为其 Microsoft Edge 网络浏览器和其他 Windows 应用程序开发的 Javascript 引擎。 它实现了 ECMAScript 5.1,并且对 ECMAScript 6 有部分(不断增加的)支持。它是用 C++ 编写的。

SpiderMonkey SpiderMonkey 是 Mozilla 的 Javascript 和 WebAssembly 引擎。 它是用 C++、Javascript 和 Rust 编写的,用于为 Firefox、Servo 和其他项目提供支持。

一开始,Javascript 引擎只是简单的解释器。 我们今天使用的现代浏览器能够执行称为即时 (JIT) 编译的功能,这是编译和解释的混合体。

编译

在编译过程中,一个称为编译器的软件将用高级语言编写的代码一次性转换为机器代码。 创建一个目标文件,该文件可以在任何机器上运行。 采取这些步骤后,就可以执行代码了。

解释

在解释过程中,解释器逐行检查 Javascript 代码并立即执行。 没有进行编译,因此没有创建目标代码(代码的输出由解释器本身使用其内部机制创建)。 旧版本的 Javascript 使用这种类型的代码执行。

即时编译( JIT Compilation )

即时编译是给定语言的解释器的一个特性,它试图同时利用编译和解释。 是在纯编译期间,代码是在执行之前被编译,然而在 JIT 编译中,代码在执行时(在运行时)被编译。 所以我们可以说源代码是动态转换为机器代码的。 较新版本的 Javascript 使用这种类型的代码执行。

JIT 编译的一个很重要的方面就是将源代码编译成当前正在运行的机器的机器码指令。 这意味着生成的机器代码是针对正在运行的机器的 CPU 架构进行了优化。

简而言之,这三个过程可以总结为:

  • 编译器:编译代码
  • 解释器:运行代码
  • JIT 编译器:在运行代码时进行编译

今天,编译解释这两个术语之间的界限已经变得非常模糊,因此这个主题可以进行广泛的辩论。 如果你想了解更多关于这些过程的信息,你可以阅读这篇关于 Mozilla Hacks for starters 的文章。

请注意,我提到了旧版本和新版本的 Javascript。 不支持较新版本语言的浏览器将解释代码,而支持的浏览器将使用某些版本的 JIT 来执行代码(V8、Chakra JavaScriptCore 和 SpiderMonkey 引擎都使用 JIT)。 事实上,尽管 Javascript 是一种解释型语言(它不需要编译),但如今大多数浏览器都会使用 JIT 编译来运行代码,而不是纯粹的解释型语言。

Javascript 代码是如何处理的

当 Javascript 代码进入 Javascript 引擎时,它首先被解析。 这意味着代码被读取,并且在这种情况下,代码被转换为称为抽象语法树 (AST) 的数据结构。 代码将被拆分成与语言相关的部分(如 functionconst 关键字),然后所有这些部分将构建抽象语法树。

假设我们有一个文件,其中包含一个只做一件事的程序,那就是定义一个变量:

const age = 25;

这就是这行非常简单的代码看起来像抽象语法树的方式(我正在使用@babel/parser-7.16.12):

如果你想将一些 Javascript 转换为抽象语法树,你可以使用这个工具。 编写变量后得到的 AST 实际上要大得多,在屏幕截图中隐藏了更多节点。

构建 AST 后,它会被翻译成机器代码并立即执行,因为现代 Javascript 使用即时编译。 这段代码的执行将由 Javascript 引擎完成,利用称为“调用堆栈”的东西。

调用堆栈是解释器(如 Web 浏览器中的 JavaScript 解释器)跟踪其在调用多个函数的脚本中的位置的机制——当前正在运行的函数以及从该函数中调用的函数等。

6.创建可访问(无障碍)树

除了我们一直在讨论的所有这些树(DOM、CSSOM 和 AST)之外,浏览器还构建了一种称为可访问(无障碍)树的东西。

Web 开发中的可访问性(通常缩写为 A11y — 如“a”,然后是 11 个字符,然后是“y”)意味着让尽可能多的人能够使用网站,即使这些人的能力在某种程度上受到限制。 对很多人来说,技术让事情变得更容易。 对于残障人士,技术使事情成为可能。 可访问性意味着开发尽可能易于访问的内容,无论个人的身体和认知能力以及他们如何访问网络 (ACT)。

一般而言,残疾用户可以并且确实在使用具有各种辅助技术的网页。 他们使用屏幕阅读器、放大镜、眼动追踪、语音命令等。 为了让这些技术发挥作用,它们需要能够访问页面的内容。 由于他们无法直接读取 DOM,因此 ACT 开始发挥作用。

可访问性树是使用 DOM 构建的,稍后辅助设备将使用它来解析和解释我们正在访问的网页的内容。 ACT 就像 DOM 的语义版本,每次 DOM 更新时它都会更新。 每个需要暴露给辅助技术的 DOM 元素都会在 ACT 中有一个对应节点。 在未构建 ACT 之前,屏幕阅读器无法访问内容。

要查看可访问性树的实际的样子,您可以通过 Google Chrome 浏览器。 打开调试器 (F12) 并转到“元素”选项卡。 从那里,你可以在右侧选择“辅助功能”窗格。

我去 Google 并检查了搜索输入,这是我在“计算”属性下的“辅助功能”窗格中得到的:

使用语义 HTML 的重要性超出了本文的范围,但作为开发人员,我们都应该记住,我们构建的网站应该可供所有希望使用它们的人使用。 如果您想阅读有关该主题的更多信息,可以在此处找到一篇关于 Web 可访问性的很好的介绍性文章。 据互联网协会无障碍访问特别兴趣小组称,目前全世界有超过 13 亿人(约占世界人口的 15%)患有某种形式的残疾。

7.渲染树

在解析阶段构建的树(DOM、CSSOM)被组合成一种叫做渲染树的东西。 这用于计算最终将绘制到屏幕上的所有可见元素的布局。 渲染树的目的是确保页面内容以正确的顺序绘制元素。 它将作为在屏幕上显示像素的绘画过程的输入。

DOM 和 CSSOM 是使用 HTML 和 CSS 文件创建的。 这两个文件包含不同类型的信息,树的结构也不同,那么渲染树是如何创建的呢?

结合 DOM 和 CSSOM

  • 浏览器将开始在 DOM 树的根部施展魔法并遍历每个可见节点。 一些节点,如脚本或元标记是不可见的,因此它们被忽略。 还有一些节点会被 CSS 隐藏(例如 display: "none" 属性),它们也会被忽略。 我们只对可见节点感兴趣,因为只有它们对屏幕上的输入有影响。
  • 对于在 DOM 中找到的每个可见节点,将在 CSSOM 中找到相应的规则并应用它们。

以上步骤的结果将是一个包含所有可见节点、内容和样式的渲染树

布局(回流)阶段

渲染树包含有关显示哪些节点及其计算样式的信息,但不包含每个节点的尺寸或位置。

接下来需要做的是计算这些节点在设备视口(浏览器窗口内)内的确切位置及其大小。 这个阶段称为布局(在 Chrome、Opera、Safari 和 Internet Explorer 中)或重排(在 Firefox 中),但它们的意思相同。 浏览器在渲染树的根部开始这个过程并遍历它。

回流步骤不会只发生一次,而是每次我们更改 DOM 中影响页面布局的某些内容时,即使是部分更改,都会触发回流。 重新计算元素位置的情况示例如下:

  • 在 DOM 中添加或删除元素
  • 调整浏览器窗口大小
  • 更改元素的宽度、位置或使其浮动

让我们来看一个非常基本的 HTML 示例,其中内嵌了一些 CSS:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Reflow</title>
  </head>
  <body>
    <div style="width: 100%; height: 50%">
      <div style="width: 50%; height: 50%">This is the reflow stage!</div>
    </div>
  </body>
</html>

上面的代码只是说在视口内我们应该有两个 div,其中第二个嵌套在第一个里面。 父 div 占据视口宽度的 100%和高度的 50%。第二个 div 占据父 div 的 50% 这看起来像这样:

这个过程的输出是一个类似盒子的模型,它准确地捕获了每个元素需要在屏幕上的位置及其大小。 完成此步骤后,输出就可以传递到下一步,称为绘画阶段

绘画(重绘)阶段

在浏览器决定哪些节点需要可见并计算出它们在视口中的位置后,就可以在屏幕上绘制它们(渲染像素)了。 这个阶段也被称为光栅化阶段,浏览器将在布局阶段计算的每个盒子转换为屏幕上的实际像素。

就像布局阶段一样,绘画阶段不会只发生一次,而是每次我们改变屏幕上元素的外观时。 这些情况的例子是:

  • 改变元素的轮廓
  • 改变背景颜色
  • 改变不透明度或可见性

绘画意味着浏览器需要将元素的每个视觉部分绘制到屏幕上,包括文本、颜色、边框、阴影和替换元素(如按钮和图像),并且需要超快地完成。 为了确保重绘可以比初始绘制更快地完成,屏幕上的绘图通常被分解成几层。 如果发生这种情况,则需要进行合成。

分层和合成

传统意义上,网络浏览器完全依赖 CPU 来呈现网页内容。 但现在即使是最小的设备也有高性能的 GPU,所有大部分实现方案都围绕着 GPU 来寻求更好的体验。

合成是一种将页面的各个部分分成层的技术,分别绘制它们并在称为合成器线程的单独线程中合成为页面。 当文档的各个部分绘制在不同的层中并相互重叠时,合成是必要的,以确保它们以正确的顺序绘制到屏幕上并且内容被正确呈现。

通常,只有特定的任务会被重定向到 GPU,而这些任务可以由合成器线程单独处理。

为了找出哪些元素需要在哪一层,主线程遍历布局树并创建层树。 默认情况下,只有一层(这些层的实现方式因浏览器而异),但我们可以找到会触发重绘的元素,并为每个元素创建一个单独的层。 这样,重绘不应应用于整个页面,而且此过程将可以使用到 GPU

如果我们想向浏览器提示某些元素应该在一个单独的层上,我们可以使用 will-change CSS 属性。 实际上有一些特定的属性和元素表示新层的创建。 其中一些是 <video><canvas> 和任何具有 CSS opacity 属性、3D transformwill-change 和其他一些属性的元素。 这些节点连同它们的后代将被绘制到它们自己的图层上。

谨记

上面讨论的两种操作,回流和重绘,都是昂贵的,尤其是在像手机这样处理能力低的设备上。 这就是为什么在处理 DOM 更改时我们应该尝试优化它们(我将在我的 DOM 系列的未来一篇文章中详细讨论这一点)。 有些动作只会触发重绘,有些动作会同时触发回流和重绘。

总结

以上包含了浏览器的核心工作原理,希望对正在学习前端的你有所帮助。当然,这并不是所有的内容,后续我还会一直更新这篇文章,从更多方面去探讨浏览器的工作原理。最后感谢大家对本文的支持~欢迎点赞收藏,在评论区留下你的高见

本文为翻译文,原文地址:https://dev.to/arikaturika/how-web-browsers-work-part-1-with-illustrations-1nid

家好,我是 Echa。

今天来分享 50 个超实用的 Chrome 浏览器扩展!

JSON

1. JSON Viewer Pro

JSON Viewer Pro 用于可视化JSON文件。其核心功能包括:

  • 支持将JSON数据进行格式化,并使用属性或者图表进行展示;
  • 使用面包屑深入遍历 JSON 属性;
  • 在输入区写入自定义 JSON;
  • 导入本地 JSON 文件;
  • 使用上下文菜单下载 JSON 文件;
  • 网址过滤器;
  • 改变主题;
  • 自定义 CSS ;
  • 复制属性和值;

输入界面如下:

格式化之后:

2. JSONVue

JSONVue 是一个JSON数据查看器,主要用来格式化JSON数据:

网站技术

3. Library Sniffer

Library Sniffer 是一款给开发者使用的工具,能够探测当前网页所使用的类库、框架和服务器环境,为开发者提供了方便。

4. Wappalyzer

Wappalyzer 扩展可以用来识别网站背后的底层技术。通过此扩展,可以了解特定应用程序是否是用 React、Vue、Angular、PHP等编写的。还可以访问有关 Web 服务器、编程语言、框架、内容管理系统、分析的信息工具、数据库等。

5. WhatRuns

WhatRuns 扩展程序只需单击一下即可找到任何网站上使用的技术。

开发调试

6. PerfectPixel by WellDoneCode

使用PerfectPixel插件可以将设计图加载至网页中,与已成型的网页进行重叠对比,以帮助开发和设计人员规范网页像素精度。这是一款可以优化前端页面显示的Chrome插件。

7. Clear Cache

可以使用此扩展程序快速清除缓存,无需任何确认对话框、弹出窗口等。可以在选项页面上自定义要清除的数据和数量,包括:应用程序缓存、缓存、Cookie、下载、文件系统、表单数据、历史记录、索引数据库、本地存储、插件数据、密码和 WebSQL。

8. VisBug

VisBug 是一个使用 JavaScript 构建的开源网页设计调试工具,它可以让用户使用点击式和拖放式界面来查看网站的元素。

9. Debug CSS

Debug CSS 是一个帮助调试CSS的插件。他可以显示出页面元素的轮播,按住Ctrl,并将鼠标悬浮在元素上,即可查看其信息:

10. CSS Viewer

CSS Viewer 是一款适用于 Web 开发人员的高效 Chrome 扩展。顾名思义,CSS 查看器可以显示将鼠标悬停在任何网页上的元素的 CSS 属性。

11. EditThisCookie

EditThisCookie 是一个 cookie 管理器。可以添加,删除,编辑,搜索,锁定和屏蔽cookies。

12. React Developer Tools

React Developer Tools 是开源 JavaScript 库 React 的 Chrome DevTools 扩展。它允许我们在 Chrome 开发者工具中检查 React 组件层次结构。安装此插件之后,将在 Chrome DevTools 中获得两个新选项卡:"⚛️ Components" 和 "⚛️ Profiler":

  • Components 选项卡显示了在页面上呈现的根 React 组件,以及它们最终呈现的子组件;
  • Profiler 选项卡用来记录性能信息。

13. Vue.js devtools

Vue.js devtools 是一款基于chrome浏览器的用于调试Vue.js应用程序的插件,可以使得开发人员大大提高调试效率。支持用户对DOM结构数据结构进行解析和调试功能。

14. Augury

Augury 可以帮助开发人员在 Google Chrome 浏览器中调试和分析 Angular 应用程序。

15. Firebug Lite for Google Chrome

Firebug Lite是火狐浏览器中著名的开发者工具firebug插件移植到Chrome中的插件,在Chrome中安装了Firebug Lite插件以后,开发人员可以像在火狐浏览器中使用firebug一样熟悉的方式来调试网页内容,其包含了基本的HTML、CSS以及Javascript的调试功能,用于帮助网页前端开发工程师快速地调试网页,以便及时地找到网页中的BUG并及时修复。

16. HTML Validator

HTML Validator 在 Chrome 的开发者工具中添加了 HTML Validator。HTML 页面的错误数通过浏览器状态栏中的图标显示,详细信息可以在浏览器的开发者工具中查看。

17. Web Developer

Web Developer 扩展为带有各种 Web 开发工具的浏览器添加了一个工具栏按钮。该扩展适用于 Chrome 和 Firefox,并且可以在这些浏览器支持的任何平台上运行,包括 Windows、macOS 和 Linux。

18. Requestly

Requestly 是一款Chrome和Firefox浏览器插件,提供URL转发、修改HTTP请求和结果、插入脚本等功能。

19. Window Resizer

Window Resizer 主要用来调整浏览器窗口的大小以模拟各种屏幕分辨率。

20. Responsive Viewer

Responsive Viewer 是在一个视图中显示多个屏幕的 Chrome 扩展程序。该扩展将帮助前端开发人员在开发响应式网站/应用程序时测试多个屏幕。

21. Moesif Origin & CORS Changer

此插件允许直接从浏览器发送跨域请求,而不会收到跨域错误。可以使用此插件覆盖 Request Origin 标头,并将 Access-Control-Allow-Origin 设置为 *.

22. ColorPick Eyedropper

ColorPick Eyedropper 是一个放大的吸管和颜色选择器工具,可让从网页等中选择颜色值。

23. CSSPeeper

CSS Peeper 用于检查和复制元素样式的优秀工具,使用 CSSPeeper 可以将鼠标悬停在网页中的任何元素上,然后单击鼠标即可复制元素的样式。

24. Dimensions

Dimensions是一款能帮助使用者对网页上各种元素属性之间的距离进行测量的Chrome页面元素测量插件,该插件在点击启动插件图标后,可以对页面中图像、输入字段、按钮以及视频等页面元素之间上下左右的方位尺寸进行测量,同时还可以通过使用快捷键来快速启用或关闭该插件的功能,简单实用。

25. Site Palette

Site Palette 用于生成调色板。设计师和前端开发人员必备的工具。可以通过这款插件轻松获取网站的配色方案。

26. ColorZilla

ColorZilla 是一款功能强大地提取网页色彩的工具;也是个快速的对颜色进行调节的Chrome插件,许多的用户将这款软件称呼为颜色吸取插件,它提取的颜色是非常的多样化,还可生产css颜色的代码等。

  • 吸管器-获取页面上任何像素或区域的颜色;
  • 一个先进的颜色选择器类似于可以在Photoshop和Paint Shop Pro中找到的;
  • 网页颜色分析器-分析任何网页上的DOM元素颜色,找到相应的元素;
  • 终极CSS梯度发生器;
  • 调色板查看器与7预先安装调色板;
  • 颜色历史最近挑选的颜色;
  • 显示标签名称,类别,编号,大小等元素信息;
  • 光标下的轮廓元素;
  • 自动将生成或采样的颜色复制到CSS RGB,Hex和其他格式的剪贴板;
  • 使用键盘快速采样页面颜色的键盘快捷键。

字体

27. WhatFont

当我们想查看网页中文字的字体时,最常用的方法就是在控制台查看文字的字体样式。那还有没有更简单的方法呢?WhatFont 就是一个查看网页字体的Chrome扩展。只需要的点击扩展图标,再点需要查看为文字即可:

28. Fonts Ninja

Fonts Ninja 可以从任何网站识别字体、添加书签、试用并购买它们。

标签页

29. BrowserStack

使用 BrowserStack 快速启动扩展在任何浏览器中启动一个新的测试会话。最多可设置 12 个浏览器以实现快速访问并最大限度地减少切换浏览器所花费的时间。

30. Toby

Toby 是一款 Chrome 新标签页工具,能够将未读的标签页分组显示在新标签页中,这样就能把所有未看完的标签页都关闭了。分组相当于多个 Chrome 窗口,将你的标签页都拖进 Toby 中,就不需要实时开着占地方了。

31. daily.dev

该扩展提供了每日热门开发者新闻,不需要再浪费时间搜索高质量的文章了。

32. Momentum

Momentum 拥有漂亮的新标签页面,每日更新精彩背景壁纸图片,可设置每日新鲜事焦点以及跟踪待办事项,无广告,无弹窗。

33. The Great Suspender

The Great Suspender 是一个轻量级的扩展用来减少 Chrome 的内存占用。如果同时打开许多选项卡,在可配置的时间之后未查看的选项卡将在后台自动挂起,从而释放该选项卡消耗的内存和 CPU。

34. Session Buddy

Session Buddy是一个可以帮助用户查看、新增、编辑当前网站Session状态的Chrome插件。用户可以利用该插件保存网站当前的状态以便在关闭Chrome或关闭计算机后恢复,从而达到节省内存的作用。

Github

35. Octotree

Octotree 旨在让 GitHub 体验更好。通常,为了检查 Github 中的子文件夹,需要手动单击文件夹并导航。Octotree 扩展解决了这个问题。此扩展在项目的左侧显示存储库的目录结构,这有助于更好地理解文件夹结构。

1_EKF88oqIyX6FzgueCKdtXg.gif

36. File Icons for GitHub and GitLab

File Icons for GitHub and GitLab 可以将 GitHub 和 GitLab 上的原始文件图标替换为特定文件类型的图标。

网页测试

37. axe DevTools

ax DevTools 是一个快速、轻量级但功能强大的测试工具,由 Deque 开发的世界上最值得信赖的可访问性测试引擎 axe-core 驱动。使用 ax DevTools 在网站开发过程中查找并修复更多可访问性问题。

38. OctoLinker

OctoLinker 可以将特定语言的语句(如 include、require 或 import)转换为链接。当打开一个包含多个导入语句的文件并且想要快速打开它时,只需将鼠标悬停在链接的文件上并单击即可打开。

39. Web Developer Checklist

此扩展可帮助 Web 开发人员分析网页是否违反最佳实践。

40. Check My Links

Check My Links 是一个链接检查器,它可以抓取网页并查找损坏的链接。

41. Checkbot

Checkbot 是用于验证一组HTML页面上的链接的工具。Checkbot可以检查一个或多个服务器上的单个文档或一组文档。它会创建一个报告,该报告汇总了引起某种警告或错误的所有链接。

42. PageSpeed Insights

Google Page Speed Insighs 是一款旨在优化所有设备上的网页、提高网页加载速度的工具。

43. Meta SEO Inspector

META SEO inspector是一款可以帮助用户分析网页的meta信息并得到SEO评估的谷歌浏览器插件。

隐私广告

44. Ghostery

Ghostery 是强大的隐私保护扩展程序。其主要有以下功能:

  • 拦截广告:Ghostery 内置的广告拦截工具可以移除网页上的广告,防止网页杂乱无章,让你专注于想看的内容。
  • 保护隐私:利用 Ghostery 可以查看和拦截所浏览的网站上的跟踪器,控制收集数据的跟踪器。增强反跟踪功能还能将数据匿名化,进一步保护隐私。
  • 提高浏览速度:Ghostery 的智能拦截功能可以自动拦截和取消拦截跟踪器来满足网页质量标准,提高网页加载速度,优化网页性能。

45. AdBlock

AdBlock 用来在YouTube、Facebook、Twitch和其他你喜爱的网站上拦截广告和弹窗。

效率工具

46. Marinara

番茄工作法(Pomodoro®)时间管理助理。• 长短两种休息时间 • 带有倒计时显示的工具栏图标 • 追踪Pomodoro历史和统计讯息 • 可配置的长休间隔 • 可配置的定时器时长 • 桌面与新标签页通知 • 超过20种音效可选的声音通知 • 计时器秒针走动音效

47. Loom

Loom 可以用来快速录制视频,并且能够将录制的视频上传到指定的网页中,Loom还支持在用户点击启动插件时,立即捕捉屏幕图像,同时开始视频录制操作,还可以将录制好的视频复制到粘贴板中存储。

48. GoFullPage

GoFullPage 是一款全屏截图插件(整个网页截图),完整捕获您当前页面的屏幕,进行滚动截图,而无需任何额外的权限。单击扩展程序图标,然后将其传输到屏幕快照的新标签页中,可以在其中将其下载为图像或PDF,甚至只需拖动即可,保存到桌面。

49. BetterViewer

BetterViewer 可以提供更好的图像查看体验,旨在替代基于 Chrome 浏览器中内置的图像查看模式。使用时,只需在页面右键点击图片,选择“在新标签页中打开图片”即可。

50. svg-grabber

svg-grabber 是一个快速预览并从网站获取所有 svg 的工具。可以用来预览、下载和复制网站中所有 SVG 图标和插图的代码。

常,我们希望限制元素相对于其父元素的宽度,同时使其具有动态性。因此,有一个基础宽度或高度的能力,使其扩展的基础上,可用的空间。比如说,我们有一个按钮,它的宽度应该是最小的,不应该低于它的宽度。这就是最大和最小属性变得方便的地方。

在本文中,我们将详细介绍CSS的最大和最小宽度和高度属性,并使用可能的用例和技巧详细解释每一个属性。

width 属性

首先要讨论的是与宽度相关的属性。我们有min-width和max-width,它们中的每一个都很重要,都有自己的用例。

Min Width

设置min-width的值时,其好处在于防止width属性使用的值变得小于min-width的指定值。 请注意,min-width的默认值是auto,它解析为0。

让我们举一个基本的例子来说明这一点。

我们有一个按钮,里面有一个变化的文本。文本的范围可能从一个单词到多个单词。为了确保即使只有一个单词,它也有最小宽度,应该使用min-width。

最小宽度为100px,这样即使按钮的内容很短,比如Done,或者只有一个图标,它仍然足够大,可以被注意到。在使用阿拉伯语等多语言网站时,这一点非常重要。 考虑以下来自Twitter的示例:

在以前的情况下,按钮上带有单词“تم”,表示完成。 按钮的宽度太小,因此在后面的案例中,我增加了它的最小宽度。

min-width 和 padding

在内容较长的情况下,min-width可以扩展按钮的宽度,而水平方向上的padding应该被添加,以实现一个合适的外观按钮。

Max Width

在设置max-width值时,它的好处在于防止width属性使用的值超过max-width的指定值。max-width的默认值是none。

max-width的常见且简单的用例是将其与图像一起使用。 考虑以下示例:

图像比它的父元素大。通过使用max-width: 100%,图像的宽度不会超过其父图像的宽度。如果图像比父图像小,则max-width: 100%不会对图像产生实际影响,因为它比父图像小。

使用最小宽度和最大宽度

当min-width和max-width都用于一个元素时,它们中的哪一个将覆盖另一个?换句话说,哪个优先级更高?

html

<div class="wrapper">
  <div class="sub"></div>
</div>

css

.sub {
  width: 100px;
  min-width: 50%;
  max-width: 100%;
}

初始width值为100px,并在其上加上min-width和max-width值。 结果是元素宽度未超过其包含的块/父元素的50%。

height 属性

除了最小和最大宽度属性外,我们还具有与高度相同的属性。

min-height

设置min-height的值时,其好处在于防止使用的height属性值变得小于min-height的指定值。 请注意,最小高度的默认值为auto,它解析为0。

我们用一个简单的例子来演示一下。

我们有一个带有描述文本的部分。目标是为section设置一个最小高度,这样它就可以处理短或长内容。考虑下面的基本情况

.sub {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  min-height: 100px;
  color: #fff;
  background: #3c78dB;
}

最小高度为100px,使用flexbox时,内容水平和垂直居中。 如果内容更长,会发生什么? 例如一段?

是的,你猜对了!section的高度将展开以包含新内容。有了它,我们就可以构建灵活的组件,并对其内容做出响应。

事例源码:https://codepen.io/shadeed/pen/cfb600cf30acdae9cf6f9cb5347a37cf

max-height

在设置max-height值时,它的好处在于防止height属性使用的值超过max-height的指定值。注意,max-height的默认值是none。

考虑下面的示例,其中我为内容设置了max-height。 但是,因为它大于指定的空间,所以会发生溢出。 因此,文本超出了其父边界。

最小和最大属性的用例

我们将介绍min-width,min-height,max-width和max-height的一些常见和不常见的用例。

标签列表

当有一个标签列表时,建议限制一个标签的最小宽度,这样如果它的内容很短,它的外观就不会受到影响。

通过具有这种灵活性,无论内容有多短,标签都将看起来不错。 但是,如果内容作者输入了一个非常长的标签名称,而他使用的内容管理系统没有标签的最大字符长度,将会发生什么情况呢? 我们也可以使用max-width。

.c-tag {
  display: inline-block;
  min-width: 100px;
  max-width: 250px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  /*Other styles*/
}

通过使用max-width,标签宽度将被限制为特定值。 但是,这还不够,标签名称应被截断。

事例地址:https://codepen.io/shadeed/pen/320e42b7ad75c438a9e633417d737d16

按钮

对于按钮的最小值和最大值有不同的用例,因为按钮组件有多种变体。考虑下面的图:

请注意,按钮的“Get”宽度太小。 如果不设置最小宽度,则由于任何原因而没有文本时,情况可能会变得更糟。 在这种情况下,设置最小宽度很重要。

使用 flexbox 将最小宽度设置为零

min-width的默认值是auto,它被计算为0。当一个元素是一个flex项时,min-width的值不会计算为零。flex 项目的最小大小等于其内容的大小。

根据CSSWG:

默认情况下,flex项目不会缩小到它们的最小内容大小(最长单词或固定大小元素的长度)以下。要更改此设置,请设置min-width或 min-height属性。

考虑下面的例子

这个人的名字有一个很长的单词,这导致了溢出和水平滚动。尽管如此,我还是在标题中添加了下面的CSS来截断它

.c-person__name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

由于title是flex项目,因此解决方案是重置min-width并将其强制为零。

.c-person__name {
    /*Other styles*/
    min-width: 0;
}

下面是修复后的样子

根据CSSWG:

在弹性项目的主轴上可见溢出的项目上,当在弹性项目的主轴min-size属性中指定时,指定自动最小尺寸。

意味着,将overflow设置为visible值以外的值会导致min-width被计算为0,这解决了我们不设置min-width: 0的问题。

事例源码:https://codepen.io/shadeed/pen/398ccffcd437a2fb042f5ce3bdd68c57

使用 flexbox 将最小高度设置为零

虽然与min-width相比,这是一个不太常见的问题,但是它可能发生。 只是为了确认,问题与不能少于其内容的弹性项目有关。 结果min-height值被设置为与内容一样长。

考虑以下示例:

用红色表示的文本应该在父文本中裁剪。因为面板主体是一个flex项目,所以它的min-height与它的内容相等。为了防止这种情况,我们应该重新设置最小高度值。看看HTML和CSS是怎么样的。

HTML

<div class="c-panel">
  <h2 class="c-panel__title"><!-- Title --></h2>
  <div class="c-panel__body">
    <div class="c-panel__content"><!-- Content --></div>
  </div>
</div>

CSS

.c-panel {
  display: flex;
  flex-direction: column;
  height: 180px;
}

.c-panel__body {
  min-height: 0;
}

.c-panel__content {
  overflow-y: scroll;
  height: 100%;
}

通过向面板主体添加min-height: 0,这将重置该属性,并且现在应该可以正常工作。

事例源码:https://codepen.io/shadeed/pen/dea75b84b1fcfd03e5c21173a40afc20?editors=0100

混合最小宽度和最大宽度

在某些情况下,我们有一个最小宽度的元素,但同时,它没有最大宽度。这可能会导致组件太宽,而我们并不想这样做。考虑以下示例

由于宽度是以像素为单位定义的,因此不能保证上面的方法适用于移动视口。为了解决这个问题,我们可以使用百分比来代替像素作为最小和最大属性。考虑下面这个具有article主体的示例。

我为图像添加了以下CSS:

img {
  min-width: 35%;
  max-width: 70%;
}

事例源码:https://codepen.io/shadeed/pen/11f49fd1a35ad06ce241bee17c3d3124

#### 页面包装器/容器

最常用的`max-width`用例之一是页面包装器或容器。通过向页面添加最大宽度,我们可以确保内容对用户来说是可读的、易于浏览的。

下面是一个包装器的例子,它是居中的,左右两边有水平的填充。

.wrapper {
    max-width: 1170px;
    padding-left: 16px;
    padding-right: 16px;
    margin-left: auto;
    margin-right: auto;
}

最大宽度和ch单位

ch 是一个相对于数字0的大小,1ch 就是数字 0 的宽度。如定义一个3ch的宽度,那么就只能装下 3个0。

<!-- HTML代码 -->

<div>0000</div>

/* CSS代码 */

div {
  width: 3ch;
  background: powderblue;
}

在前面的wrapper元素示例中,我们可以利用ch单元,因为它是一个article 主体。

.wrapper {
    max-width: 70ch;
    /* Other styles */
}

对高度未知的元素进行动画处理

在某些情况下,我们面临着使手风琴或移动菜单具有意想不到的内容高度的挑战。在这种情况下,max-height可能是一个很好的解决方案。

请考虑以下示例:

单击菜单按钮后,菜单应随动画从上到下滑动。 如果没有固定的高度(不建议这样做),除非使用JavaScript,否则这是不可能的。 但是,对于max-height,这是可能的。 想法是为高度添加一个较大的值,例如max-height:20rem,可能无法达到,然后我们可以使用动画从max-height: 0变换到max-height: 20rem。

.c-nav {
    max-height: 0;
    overflow: hidden;
    transition: 0.3s linear;
}

.c-nav.is-active {
    max-height: 22rem;
}

点击菜单按钮可以看到动画的运行。

事例源码:https://codepen.io/shadeed/pen/164c7ef67f5d4541bddb8bc12b2772da

Hero 元素的最小高度

一般来说,我不喜欢给元素添加固定的高度。我觉得这样做,会破坏流式布局的结构。但有些情况设置固定高度却很有用。

考虑下面的例子,在这里我们有一个设置了固定高度的hero部分。

是,当内容较长时,它会溢出并离开hero包装器,这可不太好。

为了预先解决这个问题,我们可以使用min-height来代替height。我们可以用这种方式先解决问题,尽管这可能会导致页面看起来很奇怪,但是我认为应该首先防止内容管理系统(CMS)中发生这样的事情。这样,问题就解决了,看起来也不错。

内容溢出的问题不仅在于内容是否大于固定的hero 高度。它可以发生在屏幕大小调整作为文本换行的结果。

如果改用min-height,则上述情况根本不会发生。

模态组件

对于模态组件,它需要最小和最大宽度,以便可以适应移动设备到PC的屏幕上的适应。

思路1

.c-modal__body {
    width: 600px;
    max-width: 100%;
}

思路2

.c-modal__body {
    width: 100%;
    max-width: 600px;
}

对于我来说,我更喜欢第二个思路,因为我只需要定义max-width: 600px。modal是一个<div>元素,因此它已经具有其父元素的100%宽度,对吗?

考虑下面为模态设计简化的测试案例。 请注意,如果可用视口空间不足,则宽度如何更改为其父级的100%。

事例源码:https://codepen.io/shadeed/pen/5dcb1c4c6773cc3a97a766c327c36443

最小高度和粘性页脚

当一个网站的内容不够长,它希望看到页脚粘到底部。让我们用一个可视化的例子来更好地展示这一点。

请注意,页脚未粘贴在浏览器窗口的末尾。 那是因为内容不足以达到浏览器窗口高度的长度。 修复后,其外观应如下所示:

首先,将body元素作为flexbox容器,然后将其最小高度设置为视口高度的100%。

事例源码:https://codepen.io/shadeed/pen/aeb14f2819b9cc4805275b88c2d55645?editors=1100

最大宽度/高度和视口单位的流体比率

为了使比例容器能够根据视口大小进行响应缩放,引入了padding hack。 现在,我们可以通过组合CSS中的视口单位和最大宽度/高度来模仿相同的行为。

我们有一个尺寸为644 * 1000像素的图像。 为了使其流畅,我们需要以下内容:

  • 纵横比:高度/宽度
  • 容器的宽度:可以是固定数字,也可以是动态数字(100%)
  • 设置height为视口宽度的100%乘以纵横比
  • 设置max-heigh,该高度是容器的宽度乘以纵横比
  • max-width设置为等于容器宽度

人才们的 【三连】 就是小智不断分享的最大动力,如果本篇博客有任何错误和建议,欢迎人才们留言,最后,谢谢大家的观看。


作者:Ahmad shaded 译者:前端小智 来源:sitepoint 原文:https://www.impressivewebs.com/min-max-width-height-css