我叫洋茄子炒鸡蛋,我的身边发生了无法想象的灾难,我要活下去,去救小薇,还有更多的人。
不对,重来。
我叫洋茄子炒鸡蛋,我的身边发生了非常可怕的事情,那就是我的室友全部转行了了,只有我一只程序员!
忘了说了,我是一名创业型公司的前端开发。
至今没写过一个完整的项目。
额,坦白说吧,我连项目中常见的bug都得百度去解决。
但以上这些都不是最糟糕的事。
糟糕的是,我穿越了。
最糟糕的是,我穿越到了一个充满内卷、无限加班的996福报宗门。
最最糟糕的是,我穿越成了一个刚入行的菜鸡切图仔!
(╯°Д°)╯︵┻━┻
天坑啊!
我发誓,下辈子,绝对不做程序员了。
CSS入门修行
前言
作为一名前端切图仔,提到切图就会想到
CSS
这门入门级功法,在宗门中的修行者都必须掌握的核心功法。这门功法修行到极致,可以可以有效地帮助提升网页性能
,释放各种威力巨大的动态视觉交互式绝学。这门功法修行条件也很简单,只需要一个浏览器一个编辑器
即可开始修行。当然,如果是外出历练与人斗法还需准备更加趁手的编辑器
和运行环境
的凝练。
浏览器
浏览器是一种用于
访问和浏览互联网
的软件应用程序。浏览器的主要功能包括导航、渲染、脚本执行、插件支持、书签和历史记录管理以及安全性等。用户通过输入URL或点击链接来获取并展示网页上的信息,浏览器负责解析HTML
、CSS
和JavaScript
等网页语言,将其转换成用户可读的文档或媒体内容。现代浏览器还提供了多种附加功能,如扩展程序、插件支持、下载管理、搜索功能、隐私保护等。浏览器通常由两部分组成:用户界面和浏览器核心。用户界面负责用户的交互操作,如输入网址、显示菜单等,而浏览器核心则负责网页的解析、渲染和执行
脚本。不同的浏览器可能使用不同的浏览器核心,如Trident(IE内核)
、Gecko(Firefox内核)
、WebKit(Safari内核)
和Blink(Chrome内核)
。这些浏览器核心大多开源,并可移植到不同的操作系统上。
浏览器的组成
虽然目前修行界的浏览器
势力家族众多,但是浏览器
的结构还是由以下几部分组成的:
-
用户界面(User Interface, UI):
- 地址栏:用于输入网站
URL
,通过HTTP/HTTPS
等协议发起网络请求 - 前进/后退按钮:允许用户在浏览历史中导航
- 书签菜单:存储和访问常用或重要网站的快捷方式
- 工具栏:包含各种功能按钮,如刷新、停止加载、设置等
- 菜单栏:提供浏览器的设置和扩展管理等高级选项
- 地址栏:用于输入网站
-
浏览器引擎(Browser Engine):
- 负责协调用户界面和渲染引擎之间的交互
- 处理用户的操作,更新 UI 来反映渲染引擎的状态变化
-
渲染引擎(Rendering Engine):
- 解析
HTML
和CSS
,构建DOM
树和CSSOM
树,进而形成渲染树 - 负责页面的布局
Layout
和绘制Painting
- 执行
JavaScript
代码,与 JS 引擎交互 - 处理网络请求和响应,比如
HTTP/HTTPS
通信 - 支持资源的缓存和加载,如图片、字体等
- 解析
-
JavaScript 引擎(JS Engine):
- 解析和执行
JavaScript
代码 - 使用即时编译(JIT)技术提升性能,生成并执行中间代码(如V8引擎的字节码)
- 提供内存管理和垃圾回收机制
- 解析和执行
-
数据存储:
- 包括
Cookie
、Web Storage
(localStorage
和sessionStorage
)、IndexedDB
等,用于在用户设备上持久化存储数据
- 包括
-
网络模块:
- 负责处理
HTTP/HTTPS
请求,实现与服务器的通信
- 负责处理
-
其他组件:
- 加密模块:处理
SSL/TLS
加密,确保安全的通信 - 媒体播放器:支持音频、视频的播放
- WebGL:用于处理图形和 3D 渲染
- 加密模块:处理
这些组件协同工作,为用户提供完整的网页浏览体验。
浏览器大战
在上古1990年代末至2000年代初,由网景公司(Netscape CommunicationsCorporation)
的Netscape Navigator
和微软公司
的InternetExplorer(IE)
之间展开了一场激烈的修真界竞争。这场竞争不仅关乎修行资源份额,还涉及互联网标准
的制定和操作系统集成
的策略。
起源:
1994年,Netscape Navigator
的推出迅速获得了巨大的成功,其市场份额快速增长,尤其是在商业领域。
Netscape Navigator
的流行引起了微软的注意,微软决定进入浏览器市场,以保护其 Windows
操作系统的主导地位。
微软的反击:
1995年,微软推出了 Internet Explorer 1.0
,随后通过与 Windows
操作系统的深度集成,特别是通过 Windows 95
和后续版本中的“捆绑销售”
策略,向用户免费提供 IE
。
微软还采取了“浏览器战争”
的策略,包括向网站开发者提供经济激励,以确保他们的网站优化为 IE
友好。
资源的争夺:
到1998年,由于微软的策略,Internet Explorer
的市场份额超过了 Netscape Navigator
,成为了市场领导者。
这期间,Netscape
尝试通过发布开源的 Mozilla
项目来反击,但未能阻止 IE 的崛起。
反垄断诉讼:
网景的衰落引发了美国司法部对微软的反垄断诉讼,指控其滥用市场支配地位,将 IE
与 Windows
捆绑销售。
2001年,微软与美国政府达成和解,同意不再捆绑销售 IE
,但此时 IE
已经占据了主导地位。
后续影响:
虽然 IE
在一段时间内保持领先地位,但随着 Firefox
、Chrome
和其他浏览器的出现,市场逐渐多元化。
在2000年代后期,尤其是谷歌的 Chrome
凭借其速度、安全性、稳定性和开放源代码特性,重新定义了浏览器战争,最终在2010年代中期超越了 IE
,成为全球最受欢迎的浏览器。
浏览器大战不仅改变了互联网的格局,也促进了浏览器技术的快速发展,推动了 Web
标准的制定,比如 HTML5
等,以及对浏览器性能和安全性的更高要求。
世界五大浏览器:
Chrome ---- 谷歌公司
2008年发布
Safari ---- 苹果公司
2003年发布
Firefox ---- 网景公司
2002年发布
Opera ---- ASA公司
1996年发布
IExplorer/Edge ---- 微软公司
1995年发布
浏览器的内核
相同的一套代码在不同的浏览器中展示的页面可能不相同,因为浏览器是通过内核对网页代码进行解析并渲染成一个可视化的页面,不同浏览器的内核对代码的解析也有所不同,这就是浏览器的差异性。目前被大规模使用的浏览器内核有以下五个:
-
Blink 内核:自2013年起,谷歌决定从
Webkit
分支出来,创建了自己的渲染引擎Blink
。这个决定的主要原因是希望更快地创新和减少维护旧代码的负担。Blink
现在是许多现代浏览器的基础,包括Chrome
、Opera
(自2013年以后的版本)以及一些基于Chromium
的浏览器。 -
Webkit 内核:
Webkit
起源于KDE
项目的一个分支KHTML
,后来被苹果采用并发展为Safari
的内核。它也是早期Chrome
的内核,直到Blink
的诞生。除了Safari
,还有一些较小的浏览器,如Konqueror
和Arora
,也使用Webkit
。 -
Gecko 内核:
Gecko
是第一个完全遵循W3C
标准的浏览器内核,旨在推动Web
的标准化。Firefox
的广泛使用使得Gecko
在很长一段时间内具有重要地位,尽管它的市场份额在Blink
和Webkit
之后。 -
Presto 内核:欧朋(
Opera
)在2004年至2013年间使用Presto
,该内核以其快速渲染和低内存占用而著称。然而,为了更好地适应移动市场和提高与Web
标准的兼容性,Opera
在2013年后转向了Blink
。 -
Trident 内核:微软的
Trident
内核在IE
时代占据主导地位,但由于其对Web
标准的支持相对滞后,以及对新特性的缓慢更新,逐渐失去了市场份额。随着Edge
的推出,微软开始转向Chromium
项目,以提供更好的跨平台兼容性和性能。
这些内核的发展历程反映了浏览器市场的竞争和技术创新,以及对 Web
标准的不断追求。随着时间的推移,浏览器内核的合并和分化将继续影响着网页的展示和开发者的体验。
浏览器的渲染过程
浏览器从网络请求得到 HTML
、CSS
、JS
等资源,然后进行解析、构建、渲染、布局、绘制、合成
等一系列操作,到最后呈现给用户一个完整的页面。
解析HTML文档:
浏览器接收到 HTML
文档后,开始从头到尾解析,构建 DOM
树(Document Object Model Tree
),这是一个逻辑结构,表示了 HTML
文档的元素和它们的层级关系。
解析CSS样式:
同时或稍后,浏览器会下载 CSS
文件并解析它们,生成 CSSOM
(CSS Object Model Tree
),这个树结构包含了所有 CSS
规则及其对应的元素。
合并DOM和CSSOM:
DOM
树和 CSSOM
树结合生成渲染树(Render Tree
)。渲染树只包含那些会影响页面视觉呈现的节点,例如,<script>
标签(如果它不在<head>
中)和<style>
标签不会出现在渲染树中。
布局(Layout):
渲染树的每个节点都需要确定其在屏幕上的精确位置和大小。这个过程称为布局或重排(Reflow
),计算出每个元素的位置和大小,形成一个布局模型。
绘制(Painting):
根据布局结果,浏览器开始绘制各个渲染树节点,将其转化为像素,这一过程称为绘制或重绘(Repaint
)。绘制通常按层进行,以提高效率。
合成与显示:
绘制完成后,浏览器将绘制的结果组合成一个或多个图层(Composite
),然后发送给 GPU
进行硬件加速的合成,最后显示在屏幕上。
在整个渲染过程中,浏览器可能会受到以下因素的影响而触发重新布局、重绘或重新合成:
DOM
树的修改,如添加、删除或改变元素。CSSOM
树的更改,如修改样式。- 页面尺寸的变化,如窗口大小调整。
- 动画和过渡效果。
- 为了优化性能,现代浏览器使用了各种策略,如
延迟加载
、分块渲染
、层分离
等,来减少不必要的重排和重绘。开发者可以通过理解这些原理来编写更高效的代码,避免不必要的性能开销。
回流重绘
在浏览器的渲染过程中,回流(Reflow)
和 重绘(Repaint)
是两个关键的步骤,它们涉及到页面元素的更新和视觉呈现。只要掌握了它们就可以编写出性能更好的 CSS
代码。
渲染过程概述
- 解析HTML:浏览器构建
DOM
树,代表页面的结构。 - 解析CSS:浏览器创建
CSS
对象模型(CSSOM
)树,表示页面的样式信息。 - 合并 DOM 和 CSSOM:将
DOM
树和CSSOM
树组合成渲染树(Render Tree),渲染树只包含可见的元素和它们的样式信息。 - 布局(Layout):基于渲染树,浏览器计算每个元素的精确位置和大小,这就是回流的过程。
- 绘制(Painting):浏览器根据布局信息对每个元素进行绘制,更新屏幕,其中涉及重绘。
- 合成(Compositing):现代浏览器还会进行合成阶段,将不同图层合并到屏幕上,以提高渲染性能。
回流 (Reflow)
回流
是浏览器重新计算元素的几何属性(如位置和尺寸)以及它们相互之间的关系的过程。可理解成将整个网页清空,将整个页面重新渲染一次。
当浏览器发现元素的更改可能影响到其他元素的位置或大小时,就会触发浏览器回流并重新生成渲染树。这些更改可能包括但不限于:
- 添加或删除 DOM 元素
- 改变元素的尺寸(边距、填充、边框、宽度、高度)
- 改变元素的内容,例如文本长度增加或减少
- 浏览器窗口尺寸改变(触发
resize
事件) - 修改 CSS 样式,尤其是影响布局的样式(如
display
属性)
回流是一个昂贵的过程,因为它可能导致整个DOM树或部分DOM树的重新布局,甚至影响到其后的渲染工作。为了优化性能,浏览器通常会延迟回流,直到一批更改累积到一定程度再统一处理。
重绘 (Repaint)
重绘
是浏览器重新应用样式和颜色到元素表面的过程,但不涉及元素的位置或大小的改变。当元素的外观改变,但这些改变不影响其他元素的布局时,就会发生重绘,例如:
- 更改元素的背景色、边框颜色、字体颜色等视觉属性
- 修改透明度或过渡效果
- 显示或隐藏元素(如果只是简单地改变可见性,但元素仍然占据相同的空间,不会触发回流)
重绘相对回流来说通常更轻量级,因为它只涉及到视觉样式的变化,而不涉及布局的调整。相比回流,重绘就会更温和一些。
性能优化
渲染树的节点发生改变,但是不影响该节点的几何属性。由此可见,回流对浏览器性能的消耗是高于重绘的,而且回流一定会伴随重绘,重绘却不一定伴随回流。利用这一点可以解决一些因为回流重绘导致的性能问题。如果浏览器频繁出现回流重绘的操作,就会出现一定程度的性能问题。一个节点的回流会导致其父节点、子节点或兄弟节点的回流。在性能较高的设备上也许感官不大,但是发生在一些低配安卓手机上,就会降低页面加载速度
和增加手机电量消耗
。常见导致回流重绘的情况:
- 重构页面布局
- 页面尺寸、窗口大小的变化
- 盒模型修改
- 文字改变
那么,我们日常开发过程中有办法去避免或者减少回流重绘的产生吗?
以下这些优化技巧可以帮助开发者提高网页性能,减少不必要的资源消耗,提升用户体验。
- 使用
transform:translate3d(x,0,0)
代替top
- 避免直接改变几何属性,因为这会导致回流。使用
transform
可以只触发重绘,并可能利用GPU
加速。
- 避免直接改变几何属性,因为这会导致回流。使用
- 使用
visibility:hidden
替换display:none
visibility:hidden
不改变元素布局,仅隐藏内容,避免回流,但占用空间。display:none
移除元素及其子元素,影响布局,导致回流。
- 避免使用
Table
布局 (现如今应该很少有人用这个布局了吧)Table
布局修改一处可能影响整体,应使用更灵活的布局方式,如Flexbox
或Grid
。
- 避免样式节点层级过多
- 减少
CSS
选择器复杂度,以提高解析速度和减少渲染开销。
- 减少
- 将频繁回流或重绘的节点设置为图层
- 使用
will-change
属性或特定元素(如<video>
、<iframe>
)创建独立图层,减少影响。
- 使用
- 动态改变类名而不改变样式
- 预定义样式并用类名切换,减少直接操作
DOM
引起的回流。
- 预定义样式并用类名切换,减少直接操作
- 避免节点属性值放在循环里当成循环变量
- 提前获取不变的
DOM
属性值,避免每次循环都访问DOM
。
- 提前获取不变的
// 🙈🙈🙈
for (let i = 0; i < 10000; i++) {
const top = document.getElementById("css").style.top;
console.log(top);
}
// 😊😊😊
const top = document.getElementById("css").style.top;
for (let i = 0; i < 10000; i++) {
console.log(top);
}
- 使用
requestAnimationFrame
作为动画速度帧代替setInterval
- 以浏览器最佳刷新率运行动画,减少不必要的回流和重绘。
在实际开发中,结合使用这些策略可以显著改善页面加载速度和交互响应。
CSS简介
CSS 是层叠样式表 ( Cascading Style Sheets )
的简称。是一种用于描述 HTML
或 XML
(包括如SVG
、MathML
等各种 XML
方言)文档样式的样式表语言。它的主要作用是分离网页的内容( HTML
或 XML
)与其表现形式(如字体、颜色和布局),使得内容的结构和外观可以独立地进行管理和更新。
CSS代码规范
编写 CSS
代码时,遵循一定的规范可以帮助提高代码的可读性、可维护性和团队协作效率,可以快速定位到问题代码,防止属性重复编写。以下是一些常见的 CSS
编码规范:
编码格式:
使用 UTF-8
无 BOM
编码。
文件名使用小写字母和短横线分隔,如 styles.css
。
命名约定:
使用小写字母和短横线 -
连接单词,避免使用下划线 _
或驼峰式命名。
类名应具有描述性,避免使用过于通用的名称。
使用语义化的 HTML
元素选择器优先,必要时再用类选择器。
避免使用 ID
选择器,除非有特殊需求。
代码组织:
将相关的样式组织在一起,例如,将同组件相关的样式放在一起。
使用注释分隔不同的部分,如头部样式、主体样式、脚部样式等。
注释应简洁明了,描述样式的目的或作用。
代码缩进:
使用2个空格进行缩进,避免使用制表符(tab
)。
空格和换行:
选择器与大括号 {
之间应有一个空格。
属性与冒号 :
之间无空格,冒号后跟一个空格。
声明结束分号 ;
后通常换行。
属性顺序:
可以按照某种逻辑顺序排列属性,如位置(positioning
)、盒模型(box model
)、颜色(colors
)、文本(text
)、其他(other
)。仅供参考
布局属性
-
显示:
display
visibility
-
溢出:
overflow
overflow-x
overflow-y
-
浮动:
float
clear
-
定位:
position
left
right
top
bottom
z-index
-
列表:
list-style
list-style-type
list-style-position
list-style-image
-
表格:
table-layout
border-collapse
border-spacing
caption-side
empty-cells
-
弹性:
flex-flow
flex-direction
flex-wrap
justify-content
align-content
align-items
align-self
flex
flex-grow
flex-shrink
flex-basis
order
-
多列:
columns
column-width
column-count
column-gap
column-rule
column-rule-width
column-rule-style
column-rule-color
column-span
column-fill
column-break-before
column-break-after
column-break-inside
-
格栅:
grid-columns
grid-rows
尺寸属性
-
模型:
box-sizing
-
边距:
margin
margin-left
margin-right
margin-top
margin-bottom
-
填充:
padding
padding-left
padding-right
padding-top
padding-bottom
-
边框:
border
border-width
border-style
border-color
border-colors
border-[direction]-<param>
-
圆角:
border-radius
border-top-left-radius
border-top-right-radius
border-bottom-left-radius
border-bottom-right-radius
-
框图:
border-image
border-image-source
border-image-slice
border-image-width
border-image-outset
border-image-repeat
-
大小:
width
min-width
max-width
height
min-height
max-height
界面属性
-
外观:
appearance
-
轮廓:
outline
outline-width
outline-style
outline-color
outline-offset
outline-radius
outline-radius-[direction]
-
背景:
background
background-color
background-image
background-repeat
background-repeat-x
background-repeat-y
background-position
background-position-x
background-position-y
background-size
background-origin
background-clip
background-attachment
bakground-composite
-
遮罩:
mask
mask-mode
mask-image
mask-repeat
mask-repeat-x
mask-repeat-y
mask-position
mask-position-x
mask-position-y
mask-size
mask-origin
mask-clip
mask-attachment
mask-composite
mask-box-image
mask-box-image-source
mask-box-image-width
mask-box-image-outset
mask-box-image-repeat
mask-box-image-slice
-
滤镜:
box-shadow
box-reflect
filter
mix-blend-mode
opacity
, -
裁剪:
object-fit
clip
-
事件:
resize
zoom
cursor
pointer-events
touch-callout
user-modify
user-focus
user-input
user-select
user-drag
文字属性
-
模式:
line-height
line-clamp
vertical-align
direction
unicode-bidi
writing-mode
ime-mode
-
文本:
text-overflow
text-decoration
text-decoration-line
text-decoration-style
text-decoration-color
text-decoration-skip
text-underline-position
text-align
text-align-last
text-justify
text-indent
text-stroke
text-stroke-width
text-stroke-color
text-shadow
text-transform
text-size-adjust
-
字体:
src
font
font-family
font-style
font-stretch
font-weight
font-variant
font-size
font-size-adjust
color
-
内容:
overflow-wrap
word-wrap
word-break
word-spacing
letter-spacing
white-space
caret-color
tab-size
content
counter-increment
counter-reset
quotes
page
page-break-before
page-break-after
page-break-inside
交互属性
-
模式:
will-change
perspective
perspective-origin
backface-visibility
-
变换:
transform
transform-origin
transform-style
-
过渡:
transition
transition-property
transition-duration
transition-timing-function
transition-delay
-
动画:
animation
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-play-state
animation-fill-mode
减少冗余:
避免重复的样式,利用继承和组合选择器。
使用 CSS
预处理器(如 Sass
或 Less
)来组织代码并减少重复。
注释:
使用/* ... */
添加注释,注释要清晰,描述代码的功能或目的。
不要在注释中包含过时的信息。
浏览器前缀:
对于需要浏览器前缀的属性,按厂商顺序添加,如 -webkit-
, -moz-
, -ms-
, -o-
和无前缀版本。
代码压缩:
在生产环境中,使用工具(如 Autoprefixer
和 CSS Minifier
)自动添加浏览器前缀并压缩代码,以减小文件大小。
遵循这些规范可以提高代码质量,并使代码更易于理解和维护。当然,具体的规范可能会根据团队或项目的偏好有所不同。
总结
希望本文能够帮助你 CSS 有一个基础的了解,此篇是学习 CSS 的准备篇章,主要简单介绍浏览器、回流重绘、CSS 的简介和 CSS 书写的代码规范。祝你在前端开发的路上越走越远!