Skip to content

浏览器渲染原理

INFO

这部分内容是【渡一教育 - WEB前端大师课 - 浏览器渲染原理】的学习笔记。

啥叫渲染 —— Render

将 html 字符串变为屏幕上的像素信息,这个过程叫渲染

js
// 示意
function render(html) {
    return pixels
}

面试题

浏览器输入 url 到显示页面期间,都做了什么事。

  1. 网络

    网络进程中的网络线程拿到 html。

    生成渲染任务,放入消息队列。

  2. 渲染

    渲染主线程在消息队列中拿到渲染任务,进行渲染

alt text

面试题

相关面试题:浏览器是如何渲染页面的?

渲染时间点

alt text

每个阶段都有输入和输出,上一个阶段的输入会变成下个阶段的输出。

  • 输入 HTML 字符串
  1. 解析 HTML
  2. 样式计算
  3. 布局
  4. 分层
  5. 绘制
  6. 分块
  7. 光栅化
  • 得到像素信息

1. 解析 HTML —— Parse HTML

总的来说,就是将 HTML 转化为两棵树:DOM 树和 CSSOM 树。

alt text

DOM 树

alt text

js
> document
< #document (https://www.baidu.com)
> typeof document
< 'object'
> console.dir(document)
< #document
f: (…)
jQuery110205025669316202075: 9
location: Location {ancestorOrigins: DOMStringList, href: 'https://www.baidu.com/', origin: 'https://www.baidu.com', protocol: 'https:', host: 'www.baidu.com', …}
...

DOM 树是在 C++ 中的对象,DOM 树的 JS 对象是为了能方便地方位 C++ 中的 DOM 树。

CSSOM 树

alt text

  • HTML 中有哪些样式
    • 内部样式表 <style>
    • 外部样式表 <link...>
    • 内联样式表 <div style...
    • 浏览器默认样式表

p 元素、div 元素独占一行,等默认行为,是因为浏览器默认样式。

除了浏览器默认样式,JS 都能操作。平时操作最多的是内联样式。dom.style

另外两个样式可以用下面的方式操作。

js
> document.styleSheets[0]
CSSStyleSheet {
    ownerRule: null, 
    type: 'text/css', 
    href: 'https://pss.bdstatic.com/r/www/static/font/cosmic/pc/cos-icon_99f656e.css', 
    ownerNode: link, 
    parentStyleSheet: null, …}
    cssRules: (…)
    disabled: false
    href: "https://pss.bdstatic.com/r/www/static/font/cosmic/pc/cos-icon_99f656e.css"
    media: MediaList {length: 0, mediaText: ''}
    ownerNode: 
    linkownerRule: null
    parentStyleSheet: null
    rules: (…)
    title: null
    type: "text/css"
    [[Prototype]]: CSSStyleSheet
}
> document.styleSheets
< StyleSheetList {
    0: CSSStyleSheet,
    1: CSSStyleSheet,
    2: CSSStyleSheet,
    3: CSSStyleSheet,
    ...
    length: 21
}
> document.styleSheets[1].cssRules
< 0: CSSStyleRule {selectorText: '#form .bdsug', style: CSSStyleDeclaration, styleMap: StylePropertyMap, cssRules: CSSRuleList, type: 1, …}
1: CSSStyleRule {selectorText: '.bdsug', style: CSSStyleDeclaration, styleMap: StylePropertyMap, cssRules: CSSRuleList, type: 1, …}
2: CSSStyleRule {selectorText: '.bdsug li', style: CSSStyleDeclaration, styleMap: StylePropertyMap, cssRules: CSSRuleList, type: 1, …}
3: CSSStyleRule {selectorText: '.bdsug li.bdsug-s', style: CSSStyleDeclaration, styleMap: StylePropertyMap, cssRules: CSSRuleList, type: 1, …}
4: CSSStyleRule {selectorText: '.bdsug-store span, .bdsug-store b', style: CSSStyleDeclaration, styleMap: StylePropertyMap, cssRules: CSSRuleList, type: 1, …}
5: CSSStyleRule {selectorText: '.bdsug-store-del', style: CSSStyleDeclaration, styleMap: StylePropertyMap, cssRules: CSSRuleList, type: 1, …}
...

使用这种方式甚至可以添加样式。

js
> document.styleSheets[1].addRule('div', 'border: 1px red solid !important')
< -1

alt text

这种做法的好处是不会在标签中体现,而是直接操作样式表。

  • 为什么要转换为 DOM 和 CSSOM 树
    • 为了后续不需要再操作字符串
    • 为 JS 操作 DOM 和 CSSOM 提供支持

HTML 过程解析过程中遇到 CSS 怎么办

预解析线程快速浏览文档,遇到 CSS 后交给网络进程去下载,下载完成后交给主线程处理。

CSS 不会阻塞主线程。

alt text

HTML 解析过程中遇到 JS 怎么办

主线程暂停一切,等待下载完成后,将 JS 脚本放到 v8 引擎中执行完毕。

alt text

为什么会这样

因为 JS 可能会修改当前 DOM 树。

思考

  • 为什么 JS 没有生成树?

    • JS 执行一遍就完事了,不需要。
    • DOM 和 CSSOM 都是给 JS 用的。

2. 样式计算 —— Recalculate Style

将计算后的 CSS 属性放到 DOM 树上,得到带有最终样式的 DOM 树。

alt text

CSS 属性值的计算过程就是在这一步发生的。

相关内容 —— CSS 属性值的计算过程

  • 层叠
  • 继承
  • ...

相关内容 —— 视觉格式化模型

  • 盒模型
  • 包含块
  • 流式布局
  • 浮动布局
  • BFC
  • ...

最终样式

就是计算后的样式(Computed Style),每个元素的所有的 CSS 属性都必须有值。

在【浏览器 F12 - 元素 - 点击一个元素 - 计算样式(Computed) - 勾选全部显示(Show all)】中可以看到。

alt text

在计算过程中,有的值会变化。例如在样式表中设置的 em,计算后都会变成 px。例如我们在页面上为一个元素设置相对大小的字号。

alt text

我们可以在 Computed 中看到已经计算为了绝对尺寸。

alt text

alt text

获取计算后的样式

js
> getComputedStyle

// 有点多,结果给隐藏了,点右面看
js
> temp1
< <a href="https:​/​/​haokan.baidu.com/​?sfrom=baidu-top" target="_blank" class="mnav c-font-normal c-color-t" style="font-size:​ 2em;​">​视频​</a>
> getComputedStyle(temp1)
< {
    "0": "accent-color",
    "1": "align-content",
    "2": "align-items",
    "3": "align-self",
    "4": "alignment-baseline",
    "5": "anchor-name",
    "6": "animation-composition",
    "7": "animation-delay",
    "8": "animation-direction",
    "9": "animation-duration",
    "10": "animation-fill-mode",
    "11": "animation-iteration-count",
    "12": "animation-name",
    "13": "animation-play-state",
    "14": "animation-range-end",
    "15": "animation-range-start",
    "16": "animation-timeline",
    "17": "animation-timing-function",
    "18": "app-region",
    "19": "appearance",
    "20": "backdrop-filter",
    "21": "backface-visibility",
    "22": "background-attachment",
    "23": "background-blend-mode",
    "24": "background-clip",
    "25": "background-color",
    "26": "background-image",
    "27": "background-origin",
    "28": "background-position",
    "29": "background-repeat",
    "30": "background-size",
    "31": "baseline-shift",
    "32": "baseline-source",
    "33": "block-size",
    "34": "border-block-end-color",
    "35": "border-block-end-style",
    "36": "border-block-end-width",
    "37": "border-block-start-color",
    "38": "border-block-start-style",
    "39": "border-block-start-width",
    "40": "border-bottom-color",
    "41": "border-bottom-left-radius",
    "42": "border-bottom-right-radius",
    "43": "border-bottom-style",
    "44": "border-bottom-width",
    "45": "border-collapse",
    "46": "border-end-end-radius",
    "47": "border-end-start-radius",
    "48": "border-image-outset",
    "49": "border-image-repeat",
    "50": "border-image-slice",
    "51": "border-image-source",
    "52": "border-image-width",
    "53": "border-inline-end-color",
    "54": "border-inline-end-style",
    "55": "border-inline-end-width",
    "56": "border-inline-start-color",
    "57": "border-inline-start-style",
    "58": "border-inline-start-width",
    "59": "border-left-color",
    "60": "border-left-style",
    "61": "border-left-width",
    "62": "border-right-color",
    "63": "border-right-style",
    "64": "border-right-width",
    "65": "border-start-end-radius",
    "66": "border-start-start-radius",
    "67": "border-top-color",
    "68": "border-top-left-radius",
    "69": "border-top-right-radius",
    "70": "border-top-style",
    "71": "border-top-width",
    "72": "bottom",
    "73": "box-shadow",
    "74": "box-sizing",
    "75": "break-after",
    "76": "break-before",
    "77": "break-inside",
    "78": "buffered-rendering",
    "79": "caption-side",
    "80": "caret-color",
    "81": "clear",
    "82": "clip",
    "83": "clip-path",
    "84": "clip-rule",
    "85": "color",
    "86": "color-interpolation",
    "87": "color-interpolation-filters",
    "88": "color-rendering",
    "89": "column-count",
    "90": "column-gap",
    "91": "column-rule-color",
    "92": "column-rule-style",
    "93": "column-rule-width",
    "94": "column-span",
    "95": "column-width",
    "96": "contain-intrinsic-block-size",
    "97": "contain-intrinsic-height",
    "98": "contain-intrinsic-inline-size",
    "99": "contain-intrinsic-size",
    "100": "contain-intrinsic-width",
    "101": "container-name",
    "102": "container-type",
    "103": "content",
    "104": "cursor",
    "105": "cx",
    "106": "cy",
    "107": "d",
    "108": "direction",
    "109": "display",
    "110": "dominant-baseline",
    "111": "empty-cells",
    "112": "field-sizing",
    "113": "fill",
    "114": "fill-opacity",
    "115": "fill-rule",
    "116": "filter",
    "117": "flex-basis",
    "118": "flex-direction",
    "119": "flex-grow",
    "120": "flex-shrink",
    "121": "flex-wrap",
    "122": "float",
    "123": "flood-color",
    "124": "flood-opacity",
    "125": "font-family",
    "126": "font-kerning",
    "127": "font-optical-sizing",
    "128": "font-palette",
    "129": "font-size",
    "130": "font-size-adjust",
    "131": "font-stretch",
    "132": "font-style",
    "133": "font-synthesis-small-caps",
    "134": "font-synthesis-style",
    "135": "font-synthesis-weight",
    "136": "font-variant",
    "137": "font-variant-alternates",
    "138": "font-variant-caps",
    "139": "font-variant-east-asian",
    "140": "font-variant-ligatures",
    "141": "font-variant-numeric",
    "142": "font-variant-position",
    "143": "font-weight",
    "144": "grid-auto-columns",
    "145": "grid-auto-flow",
    "146": "grid-auto-rows",
    "147": "grid-column-end",
    "148": "grid-column-start",
    "149": "grid-row-end",
    "150": "grid-row-start",
    "151": "grid-template-areas",
    "152": "grid-template-columns",
    "153": "grid-template-rows",
    "154": "height",
    "155": "hyphenate-character",
    "156": "hyphenate-limit-chars",
    "157": "hyphens",
    "158": "image-orientation",
    "159": "image-rendering",
    "160": "initial-letter",
    "161": "inline-size",
    "162": "inset-area",
    "163": "inset-block-end",
    "164": "inset-block-start",
    "165": "inset-inline-end",
    "166": "inset-inline-start",
    "167": "isolation",
    "168": "justify-content",
    "169": "justify-items",
    "170": "justify-self",
    "171": "left",
    "172": "letter-spacing",
    "173": "lighting-color",
    "174": "line-break",
    "175": "line-height",
    "176": "list-style-image",
    "177": "list-style-position",
    "178": "list-style-type",
    "179": "margin-block-end",
    "180": "margin-block-start",
    "181": "margin-bottom",
    "182": "margin-inline-end",
    "183": "margin-inline-start",
    "184": "margin-left",
    "185": "margin-right",
    "186": "margin-top",
    "187": "marker-end",
    "188": "marker-mid",
    "189": "marker-start",
    "190": "mask-clip",
    "191": "mask-composite",
    "192": "mask-image",
    "193": "mask-mode",
    "194": "mask-origin",
    "195": "mask-position",
    "196": "mask-repeat",
    "197": "mask-size",
    "198": "mask-type",
    "199": "math-depth",
    "200": "math-shift",
    "201": "math-style",
    "202": "max-block-size",
    "203": "max-height",
    "204": "max-inline-size",
    "205": "max-width",
    "206": "min-block-size",
    "207": "min-height",
    "208": "min-inline-size",
    "209": "min-width",
    "210": "mix-blend-mode",
    "211": "object-fit",
    "212": "object-position",
    "213": "object-view-box",
    "214": "offset-anchor",
    "215": "offset-distance",
    "216": "offset-path",
    "217": "offset-position",
    "218": "offset-rotate",
    "219": "opacity",
    "220": "order",
    "221": "orphans",
    "222": "outline-color",
    "223": "outline-offset",
    "224": "outline-style",
    "225": "outline-width",
    "226": "overflow-anchor",
    "227": "overflow-clip-margin",
    "228": "overflow-wrap",
    "229": "overflow-x",
    "230": "overflow-y",
    "231": "overlay",
    "232": "overscroll-behavior-block",
    "233": "overscroll-behavior-inline",
    "234": "padding-block-end",
    "235": "padding-block-start",
    "236": "padding-bottom",
    "237": "padding-inline-end",
    "238": "padding-inline-start",
    "239": "padding-left",
    "240": "padding-right",
    "241": "padding-top",
    "242": "paint-order",
    "243": "perspective",
    "244": "perspective-origin",
    "245": "pointer-events",
    "246": "position",
    "247": "position-anchor",
    "248": "position-try-fallbacks",
    "249": "position-try-order",
    "250": "position-visibility",
    "251": "r",
    "252": "resize",
    "253": "right",
    "254": "rotate",
    "255": "row-gap",
    "256": "ruby-align",
    "257": "ruby-position",
    "258": "rx",
    "259": "ry",
    "260": "scale",
    "261": "scroll-behavior",
    "262": "scroll-margin-block-end",
    "263": "scroll-margin-block-start",
    "264": "scroll-margin-inline-end",
    "265": "scroll-margin-inline-start",
    "266": "scroll-padding-block-end",
    "267": "scroll-padding-block-start",
    "268": "scroll-padding-inline-end",
    "269": "scroll-padding-inline-start",
    "270": "scroll-timeline-axis",
    "271": "scroll-timeline-name",
    "272": "scrollbar-color",
    "273": "scrollbar-gutter",
    "274": "scrollbar-width",
    "275": "shape-image-threshold",
    "276": "shape-margin",
    "277": "shape-outside",
    "278": "shape-rendering",
    "279": "speak",
    "280": "stop-color",
    "281": "stop-opacity",
    "282": "stroke",
    "283": "stroke-dasharray",
    "284": "stroke-dashoffset",
    "285": "stroke-linecap",
    "286": "stroke-linejoin",
    "287": "stroke-miterlimit",
    "288": "stroke-opacity",
    "289": "stroke-width",
    "290": "tab-size",
    "291": "table-layout",
    "292": "text-align",
    "293": "text-align-last",
    "294": "text-anchor",
    "295": "text-decoration",
    "296": "text-decoration-color",
    "297": "text-decoration-line",
    "298": "text-decoration-skip-ink",
    "299": "text-decoration-style",
    "300": "text-emphasis-color",
    "301": "text-emphasis-position",
    "302": "text-emphasis-style",
    "303": "text-indent",
    "304": "text-overflow",
    "305": "text-rendering",
    "306": "text-shadow",
    "307": "text-size-adjust",
    "308": "text-spacing-trim",
    "309": "text-transform",
    "310": "text-underline-position",
    "311": "text-wrap",
    "312": "timeline-scope",
    "313": "top",
    "314": "touch-action",
    "315": "transform",
    "316": "transform-origin",
    "317": "transform-style",
    "318": "transition-behavior",
    "319": "transition-delay",
    "320": "transition-duration",
    "321": "transition-property",
    "322": "transition-timing-function",
    "323": "translate",
    "324": "unicode-bidi",
    "325": "user-select",
    "326": "vector-effect",
    "327": "vertical-align",
    "328": "view-timeline-axis",
    "329": "view-timeline-inset",
    "330": "view-timeline-name",
    "331": "view-transition-class",
    "332": "view-transition-name",
    "333": "visibility",
    "334": "white-space-collapse",
    "335": "widows",
    "336": "width",
    "337": "will-change",
    "338": "word-break",
    "339": "word-spacing",
    "340": "writing-mode",
    "341": "x",
    "342": "y",
    "343": "z-index",
    "344": "zoom",
    "345": "-webkit-border-horizontal-spacing",
    "346": "-webkit-border-image",
    "347": "-webkit-border-vertical-spacing",
    "348": "-webkit-box-align",
    "349": "-webkit-box-decoration-break",
    "350": "-webkit-box-direction",
    "351": "-webkit-box-flex",
    "352": "-webkit-box-ordinal-group",
    "353": "-webkit-box-orient",
    "354": "-webkit-box-pack",
    "355": "-webkit-box-reflect",
    "356": "-webkit-font-smoothing",
    "357": "-webkit-line-break",
    "358": "-webkit-line-clamp",
    "359": "-webkit-locale",
    "360": "-webkit-mask-box-image",
    "361": "-webkit-mask-box-image-outset",
    "362": "-webkit-mask-box-image-repeat",
    "363": "-webkit-mask-box-image-slice",
    "364": "-webkit-mask-box-image-source",
    "365": "-webkit-mask-box-image-width",
    "366": "-webkit-print-color-adjust",
    "367": "-webkit-rtl-ordering",
    "368": "-webkit-tap-highlight-color",
    "369": "-webkit-text-combine",
    "370": "-webkit-text-decorations-in-effect",
    "371": "-webkit-text-fill-color",
    "372": "-webkit-text-orientation",
    "373": "-webkit-text-security",
    "374": "-webkit-text-stroke-color",
    "375": "-webkit-text-stroke-width",
    "376": "-webkit-user-drag",
    "377": "-webkit-user-modify",
    "378": "-webkit-writing-mode",
    "accentColor": "auto",
    "additiveSymbols": "",
    "alignContent": "normal",
    "alignItems": "normal",
    "alignSelf": "auto",
    "alignmentBaseline": "auto",
    "all": "",
    "anchorName": "none",
    "animation": "none 0s ease 0s 1 normal none running",
    "animationComposition": "replace",
    "animationDelay": "0s",
    "animationDirection": "normal",
    "animationDuration": "0s",
    "animationFillMode": "none",
    "animationIterationCount": "1",
    "animationName": "none",
    "animationPlayState": "running",
    "animationRange": "normal",
    "animationRangeEnd": "normal",
    "animationRangeStart": "normal",
    "animationTimeline": "auto",
    "animationTimingFunction": "ease",
    "appRegion": "none",
    "appearance": "none",
    "ascentOverride": "",
    "aspectRatio": "auto",
    "backdropFilter": "none",
    "backfaceVisibility": "visible",
    "background": "rgba(0, 0, 0, 0) none repeat scroll 0% 0% / auto padding-box border-box",
    "backgroundAttachment": "scroll",
    "backgroundBlendMode": "normal",
    "backgroundClip": "border-box",
    "backgroundColor": "rgba(0, 0, 0, 0)",
    "backgroundImage": "none",
    "backgroundOrigin": "padding-box",
    "backgroundPosition": "0% 0%",
    "backgroundPositionX": "0%",
    "backgroundPositionY": "0%",
    "backgroundRepeat": "repeat",
    "backgroundSize": "auto",
    "basePalette": "",
    "baselineShift": "0px",
    "baselineSource": "auto",
    "blockSize": "23px",
    "border": "0px none rgb(34, 34, 34)",
    "borderBlock": "0px none rgb(34, 34, 34)",
    "borderBlockColor": "rgb(34, 34, 34)",
    "borderBlockEnd": "0px none rgb(34, 34, 34)",
    "borderBlockEndColor": "rgb(34, 34, 34)",
    "borderBlockEndStyle": "none",
    "borderBlockEndWidth": "0px",
    "borderBlockStart": "0px none rgb(34, 34, 34)",
    "borderBlockStartColor": "rgb(34, 34, 34)",
    "borderBlockStartStyle": "none",
    "borderBlockStartWidth": "0px",
    "borderBlockStyle": "none",
    "borderBlockWidth": "0px",
    "borderBottom": "0px none rgb(34, 34, 34)",
    "borderBottomColor": "rgb(34, 34, 34)",
    "borderBottomLeftRadius": "0px",
    "borderBottomRightRadius": "0px",
    "borderBottomStyle": "none",
    "borderBottomWidth": "0px",
    "borderCollapse": "separate",
    "borderColor": "rgb(34, 34, 34)",
    "borderEndEndRadius": "0px",
    "borderEndStartRadius": "0px",
    "borderImage": "none",
    "borderImageOutset": "0",
    "borderImageRepeat": "stretch",
    "borderImageSlice": "100%",
    "borderImageSource": "none",
    "borderImageWidth": "1",
    "borderInline": "0px none rgb(34, 34, 34)",
    "borderInlineColor": "rgb(34, 34, 34)",
    "borderInlineEnd": "0px none rgb(34, 34, 34)",
    "borderInlineEndColor": "rgb(34, 34, 34)",
    "borderInlineEndStyle": "none",
    "borderInlineEndWidth": "0px",
    "borderInlineStart": "0px none rgb(34, 34, 34)",
    "borderInlineStartColor": "rgb(34, 34, 34)",
    "borderInlineStartStyle": "none",
    "borderInlineStartWidth": "0px",
    "borderInlineStyle": "none",
    "borderInlineWidth": "0px",
    "borderLeft": "0px none rgb(34, 34, 34)",
    "borderLeftColor": "rgb(34, 34, 34)",
    "borderLeftStyle": "none",
    "borderLeftWidth": "0px",
    "borderRadius": "0px",
    "borderRight": "0px none rgb(34, 34, 34)",
    "borderRightColor": "rgb(34, 34, 34)",
    "borderRightStyle": "none",
    "borderRightWidth": "0px",
    "borderSpacing": "0px 0px",
    "borderStartEndRadius": "0px",
    "borderStartStartRadius": "0px",
    "borderStyle": "none",
    "borderTop": "0px none rgb(34, 34, 34)",
    "borderTopColor": "rgb(34, 34, 34)",
    "borderTopLeftRadius": "0px",
    "borderTopRightRadius": "0px",
    "borderTopStyle": "none",
    "borderTopWidth": "0px",
    "borderWidth": "0px",
    "bottom": "0px",
    "boxShadow": "none",
    "boxSizing": "content-box",
    "breakAfter": "auto",
    "breakBefore": "auto",
    "breakInside": "auto",
    "bufferedRendering": "auto",
    "captionSide": "top",
    "caretColor": "rgb(34, 34, 34)",
    "clear": "none",
    "clip": "auto",
    "clipPath": "none",
    "clipRule": "nonzero",
    "color": "rgb(34, 34, 34)",
    "colorInterpolation": "srgb",
    "colorInterpolationFilters": "linearrgb",
    "colorRendering": "auto",
    "colorScheme": "normal",
    "columnCount": "auto",
    "columnFill": "balance",
    "columnGap": "normal",
    "columnRule": "0px none rgb(34, 34, 34)",
    "columnRuleColor": "rgb(34, 34, 34)",
    "columnRuleStyle": "none",
    "columnRuleWidth": "0px",
    "columnSpan": "none",
    "columnWidth": "auto",
    "columns": "auto auto",
    "contain": "none",
    "containIntrinsicBlockSize": "none",
    "containIntrinsicHeight": "none",
    "containIntrinsicInlineSize": "none",
    "containIntrinsicSize": "none",
    "containIntrinsicWidth": "none",
    "container": "none",
    "containerName": "none",
    "containerType": "normal",
    "content": "normal",
    "contentVisibility": "visible",
    "counterIncrement": "none",
    "counterReset": "none",
    "counterSet": "none",
    "cursor": "pointer",
    "cx": "0px",
    "cy": "0px",
    "d": "none",
    "descentOverride": "",
    "direction": "ltr",
    "display": "inline-block",
    "dominantBaseline": "auto",
    "emptyCells": "show",
    "fallback": "",
    "fieldSizing": "fixed",
    "fill": "rgb(0, 0, 0)",
    "fillOpacity": "1",
    "fillRule": "nonzero",
    "filter": "none",
    "flex": "0 1 auto",
    "flexBasis": "auto",
    "flexDirection": "row",
    "flexFlow": "row nowrap",
    "flexGrow": "0",
    "flexShrink": "1",
    "flexWrap": "nowrap",
    "float": "none",
    "floodColor": "rgb(0, 0, 0)",
    "floodOpacity": "1",
    "font": "24px / 23px Arial, sans-serif",
    "fontDisplay": "",
    "fontFamily": "Arial, sans-serif",
    "fontFeatureSettings": "normal",
    "fontKerning": "auto",
    "fontOpticalSizing": "auto",
    "fontPalette": "normal",
    "fontSize": "24px",
    "fontSizeAdjust": "none",
    "fontStretch": "100%",
    "fontStyle": "normal",
    "fontSynthesis": "weight style small-caps",
    "fontSynthesisSmallCaps": "auto",
    "fontSynthesisStyle": "auto",
    "fontSynthesisWeight": "auto",
    "fontVariant": "normal",
    "fontVariantAlternates": "normal",
    "fontVariantCaps": "normal",
    "fontVariantEastAsian": "normal",
    "fontVariantLigatures": "normal",
    "fontVariantNumeric": "normal",
    "fontVariantPosition": "normal",
    "fontVariationSettings": "normal",
    "fontWeight": "400",
    "forcedColorAdjust": "auto",
    "gap": "normal",
    "grid": "none / none / none / row / auto / auto",
    "gridArea": "auto",
    "gridAutoColumns": "auto",
    "gridAutoFlow": "row",
    "gridAutoRows": "auto",
    "gridColumn": "auto",
    "gridColumnEnd": "auto",
    "gridColumnGap": "normal",
    "gridColumnStart": "auto",
    "gridGap": "normal",
    "gridRow": "auto",
    "gridRowEnd": "auto",
    "gridRowGap": "normal",
    "gridRowStart": "auto",
    "gridTemplate": "none",
    "gridTemplateAreas": "none",
    "gridTemplateColumns": "none",
    "gridTemplateRows": "none",
    "height": "23px",
    "hyphenateCharacter": "auto",
    "hyphenateLimitChars": "auto",
    "hyphens": "manual",
    "imageOrientation": "from-image",
    "imageRendering": "auto",
    "inherits": "",
    "initialLetter": "normal",
    "initialValue": "",
    "inlineSize": "48px",
    "inset": "0px",
    "insetArea": "none",
    "insetBlock": "0px",
    "insetBlockEnd": "0px",
    "insetBlockStart": "0px",
    "insetInline": "0px",
    "insetInlineEnd": "0px",
    "insetInlineStart": "0px",
    "isolation": "auto",
    "justifyContent": "normal",
    "justifyItems": "normal",
    "justifySelf": "auto",
    "left": "0px",
    "letterSpacing": "normal",
    "lightingColor": "rgb(255, 255, 255)",
    "lineBreak": "auto",
    "lineGapOverride": "",
    "lineHeight": "23px",
    "listStyle": "outside none disc",
    "listStyleImage": "none",
    "listStylePosition": "outside",
    "listStyleType": "disc",
    "margin": "19px 24px 0px 0px",
    "marginBlock": "19px 0px",
    "marginBlockEnd": "0px",
    "marginBlockStart": "19px",
    "marginBottom": "0px",
    "marginInline": "0px 24px",
    "marginInlineEnd": "24px",
    "marginInlineStart": "0px",
    "marginLeft": "0px",
    "marginRight": "24px",
    "marginTop": "19px",
    "marker": "none",
    "markerEnd": "none",
    "markerMid": "none",
    "markerStart": "none",
    "mask": "none",
    "maskClip": "border-box",
    "maskComposite": "add",
    "maskImage": "none",
    "maskMode": "match-source",
    "maskOrigin": "border-box",
    "maskPosition": "0% 0%",
    "maskRepeat": "repeat",
    "maskSize": "auto",
    "maskType": "luminance",
    "mathDepth": "0",
    "mathShift": "normal",
    "mathStyle": "normal",
    "maxBlockSize": "none",
    "maxHeight": "none",
    "maxInlineSize": "none",
    "maxWidth": "none",
    "minBlockSize": "0px",
    "minHeight": "0px",
    "minInlineSize": "0px",
    "minWidth": "0px",
    "mixBlendMode": "normal",
    "navigation": "",
    "negative": "",
    "objectFit": "fill",
    "objectPosition": "50% 50%",
    "objectViewBox": "none",
    "offset": "none 0px auto 0deg",
    "offsetAnchor": "auto",
    "offsetDistance": "0px",
    "offsetPath": "none",
    "offsetPosition": "normal",
    "offsetRotate": "auto 0deg",
    "opacity": "1",
    "order": "0",
    "orphans": "2",
    "outline": "rgb(34, 34, 34) none 0px",
    "outlineColor": "rgb(34, 34, 34)",
    "outlineOffset": "0px",
    "outlineStyle": "none",
    "outlineWidth": "0px",
    "overflow": "visible",
    "overflowAnchor": "auto",
    "overflowClipMargin": "0px",
    "overflowWrap": "normal",
    "overflowX": "visible",
    "overflowY": "visible",
    "overlay": "none",
    "overrideColors": "",
    "overscrollBehavior": "auto",
    "overscrollBehaviorBlock": "auto",
    "overscrollBehaviorInline": "auto",
    "overscrollBehaviorX": "auto",
    "overscrollBehaviorY": "auto",
    "pad": "",
    "padding": "0px",
    "paddingBlock": "0px",
    "paddingBlockEnd": "0px",
    "paddingBlockStart": "0px",
    "paddingBottom": "0px",
    "paddingInline": "0px",
    "paddingInlineEnd": "0px",
    "paddingInlineStart": "0px",
    "paddingLeft": "0px",
    "paddingRight": "0px",
    "paddingTop": "0px",
    "page": "auto",
    "pageBreakAfter": "auto",
    "pageBreakBefore": "auto",
    "pageBreakInside": "auto",
    "pageOrientation": "",
    "paintOrder": "normal",
    "perspective": "none",
    "perspectiveOrigin": "24px 11.5px",
    "placeContent": "normal",
    "placeItems": "normal",
    "placeSelf": "auto",
    "pointerEvents": "auto",
    "position": "relative",
    "positionAnchor": "auto",
    "positionTry": "none",
    "positionTryFallbacks": "none",
    "positionTryOrder": "normal",
    "positionVisibility": "always",
    "prefix": "",
    "quotes": "auto",
    "r": "0px",
    "range": "",
    "resize": "none",
    "right": "0px",
    "rotate": "none",
    "rowGap": "normal",
    "rubyAlign": "space-around",
    "rubyPosition": "over",
    "rx": "auto",
    "ry": "auto",
    "scale": "none",
    "scrollBehavior": "auto",
    "scrollMargin": "0px",
    "scrollMarginBlock": "0px",
    "scrollMarginBlockEnd": "0px",
    "scrollMarginBlockStart": "0px",
    "scrollMarginBottom": "0px",
    "scrollMarginInline": "0px",
    "scrollMarginInlineEnd": "0px",
    "scrollMarginInlineStart": "0px",
    "scrollMarginLeft": "0px",
    "scrollMarginRight": "0px",
    "scrollMarginTop": "0px",
    "scrollPadding": "auto",
    "scrollPaddingBlock": "auto",
    "scrollPaddingBlockEnd": "auto",
    "scrollPaddingBlockStart": "auto",
    "scrollPaddingBottom": "auto",
    "scrollPaddingInline": "auto",
    "scrollPaddingInlineEnd": "auto",
    "scrollPaddingInlineStart": "auto",
    "scrollPaddingLeft": "auto",
    "scrollPaddingRight": "auto",
    "scrollPaddingTop": "auto",
    "scrollSnapAlign": "none",
    "scrollSnapStop": "normal",
    "scrollSnapType": "none",
    "scrollTimeline": "none",
    "scrollTimelineAxis": "block",
    "scrollTimelineName": "none",
    "scrollbarColor": "auto",
    "scrollbarGutter": "auto",
    "scrollbarWidth": "auto",
    "shapeImageThreshold": "0",
    "shapeMargin": "0px",
    "shapeOutside": "none",
    "shapeRendering": "auto",
    "size": "",
    "sizeAdjust": "",
    "speak": "normal",
    "speakAs": "",
    "src": "",
    "stopColor": "rgb(0, 0, 0)",
    "stopOpacity": "1",
    "stroke": "none",
    "strokeDasharray": "none",
    "strokeDashoffset": "0px",
    "strokeLinecap": "butt",
    "strokeLinejoin": "miter",
    "strokeMiterlimit": "4",
    "strokeOpacity": "1",
    "strokeWidth": "1px",
    "suffix": "",
    "symbols": "",
    "syntax": "",
    "system": "",
    "tabSize": "8",
    "tableLayout": "auto",
    "textAlign": "center",
    "textAlignLast": "auto",
    "textAnchor": "start",
    "textCombineUpright": "none",
    "textDecoration": "none solid rgb(34, 34, 34)",
    "textDecorationColor": "rgb(34, 34, 34)",
    "textDecorationLine": "none",
    "textDecorationSkipInk": "auto",
    "textDecorationStyle": "solid",
    "textDecorationThickness": "auto",
    "textEmphasis": "none rgb(34, 34, 34)",
    "textEmphasisColor": "rgb(34, 34, 34)",
    "textEmphasisPosition": "over",
    "textEmphasisStyle": "none",
    "textIndent": "0px",
    "textOrientation": "mixed",
    "textOverflow": "clip",
    "textRendering": "auto",
    "textShadow": "none",
    "textSizeAdjust": "auto",
    "textSpacingTrim": "normal",
    "textTransform": "none",
    "textUnderlineOffset": "auto",
    "textUnderlinePosition": "auto",
    "textWrap": "wrap",
    "timelineScope": "none",
    "top": "0px",
    "touchAction": "auto",
    "transform": "none",
    "transformBox": "view-box",
    "transformOrigin": "24px 11.5px",
    "transformStyle": "flat",
    "transition": "all",
    "transitionBehavior": "normal",
    "transitionDelay": "0s",
    "transitionDuration": "0s",
    "transitionProperty": "all",
    "transitionTimingFunction": "ease",
    "translate": "none",
    "types": "",
    "unicodeBidi": "normal",
    "unicodeRange": "",
    "userSelect": "auto",
    "vectorEffect": "none",
    "verticalAlign": "baseline",
    "viewTimeline": "none",
    "viewTimelineAxis": "block",
    "viewTimelineInset": "auto",
    "viewTimelineName": "none",
    "viewTransitionClass": "none",
    "viewTransitionName": "none",
    "visibility": "visible",
    "webkitAlignContent": "normal",
    "webkitAlignItems": "normal",
    "webkitAlignSelf": "auto",
    "webkitAnimation": "none 0s ease 0s 1 normal none running",
    "webkitAnimationDelay": "0s",
    "webkitAnimationDirection": "normal",
    "webkitAnimationDuration": "0s",
    "webkitAnimationFillMode": "none",
    "webkitAnimationIterationCount": "1",
    "webkitAnimationName": "none",
    "webkitAnimationPlayState": "running",
    "webkitAnimationTimingFunction": "ease",
    "webkitAppRegion": "none",
    "webkitAppearance": "none",
    "webkitBackfaceVisibility": "visible",
    "webkitBackgroundClip": "border-box",
    "webkitBackgroundOrigin": "padding-box",
    "webkitBackgroundSize": "auto",
    "webkitBorderAfter": "0px none rgb(34, 34, 34)",
    "webkitBorderAfterColor": "rgb(34, 34, 34)",
    "webkitBorderAfterStyle": "none",
    "webkitBorderAfterWidth": "0px",
    "webkitBorderBefore": "0px none rgb(34, 34, 34)",
    "webkitBorderBeforeColor": "rgb(34, 34, 34)",
    "webkitBorderBeforeStyle": "none",
    "webkitBorderBeforeWidth": "0px",
    "webkitBorderBottomLeftRadius": "0px",
    "webkitBorderBottomRightRadius": "0px",
    "webkitBorderEnd": "0px none rgb(34, 34, 34)",
    "webkitBorderEndColor": "rgb(34, 34, 34)",
    "webkitBorderEndStyle": "none",
    "webkitBorderEndWidth": "0px",
    "webkitBorderHorizontalSpacing": "0px",
    "webkitBorderImage": "none",
    "webkitBorderRadius": "0px",
    "webkitBorderStart": "0px none rgb(34, 34, 34)",
    "webkitBorderStartColor": "rgb(34, 34, 34)",
    "webkitBorderStartStyle": "none",
    "webkitBorderStartWidth": "0px",
    "webkitBorderTopLeftRadius": "0px",
    "webkitBorderTopRightRadius": "0px",
    "webkitBorderVerticalSpacing": "0px",
    "webkitBoxAlign": "stretch",
    "webkitBoxDecorationBreak": "slice",
    "webkitBoxDirection": "normal",
    "webkitBoxFlex": "0",
    "webkitBoxOrdinalGroup": "1",
    "webkitBoxOrient": "horizontal",
    "webkitBoxPack": "start",
    "webkitBoxReflect": "none",
    "webkitBoxShadow": "none",
    "webkitBoxSizing": "content-box",
    "webkitClipPath": "none",
    "webkitColumnBreakAfter": "auto",
    "webkitColumnBreakBefore": "auto",
    "webkitColumnBreakInside": "auto",
    "webkitColumnCount": "auto",
    "webkitColumnGap": "normal",
    "webkitColumnRule": "0px none rgb(34, 34, 34)",
    "webkitColumnRuleColor": "rgb(34, 34, 34)",
    "webkitColumnRuleStyle": "none",
    "webkitColumnRuleWidth": "0px",
    "webkitColumnSpan": "none",
    "webkitColumnWidth": "auto",
    "webkitColumns": "auto auto",
    "webkitFilter": "none",
    "webkitFlex": "0 1 auto",
    "webkitFlexBasis": "auto",
    "webkitFlexDirection": "row",
    "webkitFlexFlow": "row nowrap",
    "webkitFlexGrow": "0",
    "webkitFlexShrink": "1",
    "webkitFlexWrap": "nowrap",
    "webkitFontFeatureSettings": "normal",
    "webkitFontSmoothing": "auto",
    "webkitHyphenateCharacter": "auto",
    "webkitJustifyContent": "normal",
    "webkitLineBreak": "auto",
    "webkitLineClamp": "none",
    "webkitLocale": "auto",
    "webkitLogicalHeight": "23px",
    "webkitLogicalWidth": "48px",
    "webkitMarginAfter": "0px",
    "webkitMarginBefore": "19px",
    "webkitMarginEnd": "24px",
    "webkitMarginStart": "0px",
    "webkitMask": "none",
    "webkitMaskBoxImage": "none",
    "webkitMaskBoxImageOutset": "0",
    "webkitMaskBoxImageRepeat": "stretch",
    "webkitMaskBoxImageSlice": "0 fill",
    "webkitMaskBoxImageSource": "none",
    "webkitMaskBoxImageWidth": "auto",
    "webkitMaskClip": "border-box",
    "webkitMaskComposite": "add",
    "webkitMaskImage": "none",
    "webkitMaskOrigin": "border-box",
    "webkitMaskPosition": "0% 0%",
    "webkitMaskPositionX": "0%",
    "webkitMaskPositionY": "0%",
    "webkitMaskRepeat": "repeat",
    "webkitMaskSize": "auto",
    "webkitMaxLogicalHeight": "none",
    "webkitMaxLogicalWidth": "none",
    "webkitMinLogicalHeight": "0px",
    "webkitMinLogicalWidth": "0px",
    "webkitOpacity": "1",
    "webkitOrder": "0",
    "webkitPaddingAfter": "0px",
    "webkitPaddingBefore": "0px",
    "webkitPaddingEnd": "0px",
    "webkitPaddingStart": "0px",
    "webkitPerspective": "none",
    "webkitPerspectiveOrigin": "24px 11.5px",
    "webkitPerspectiveOriginX": "",
    "webkitPerspectiveOriginY": "",
    "webkitPrintColorAdjust": "economy",
    "webkitRtlOrdering": "logical",
    "webkitRubyPosition": "before",
    "webkitShapeImageThreshold": "0",
    "webkitShapeMargin": "0px",
    "webkitShapeOutside": "none",
    "webkitTapHighlightColor": "rgba(0, 0, 0, 0.18)",
    "webkitTextCombine": "none",
    "webkitTextDecorationsInEffect": "none",
    "webkitTextEmphasis": "none rgb(34, 34, 34)",
    "webkitTextEmphasisColor": "rgb(34, 34, 34)",
    "webkitTextEmphasisPosition": "over",
    "webkitTextEmphasisStyle": "none",
    "webkitTextFillColor": "rgb(34, 34, 34)",
    "webkitTextOrientation": "vertical-right",
    "webkitTextSecurity": "none",
    "webkitTextSizeAdjust": "auto",
    "webkitTextStroke": "0px rgb(34, 34, 34)",
    "webkitTextStrokeColor": "rgb(34, 34, 34)",
    "webkitTextStrokeWidth": "0px",
    "webkitTransform": "none",
    "webkitTransformOrigin": "24px 11.5px",
    "webkitTransformOriginX": "",
    "webkitTransformOriginY": "",
    "webkitTransformOriginZ": "",
    "webkitTransformStyle": "flat",
    "webkitTransition": "all",
    "webkitTransitionDelay": "0s",
    "webkitTransitionDuration": "0s",
    "webkitTransitionProperty": "all",
    "webkitTransitionTimingFunction": "ease",
    "webkitUserDrag": "auto",
    "webkitUserModify": "read-only",
    "webkitUserSelect": "auto",
    "webkitWritingMode": "horizontal-tb",
    "whiteSpace": "normal",
    "whiteSpaceCollapse": "collapse",
    "widows": "2",
    "width": "48px",
    "willChange": "auto",
    "wordBreak": "normal",
    "wordSpacing": "0px",
    "wordWrap": "normal",
    "writingMode": "horizontal-tb",
    "x": "0px",
    "y": "0px",

:::info 面试题
[样式计算具体步骤](./meeting_question.md#computed_style)

3. 布局 —— Layout

根据 DOM 树中的样式,计算出每个节点的尺寸和位置。

alt text

这个过程很复杂,因为页面上元素之间是会互相影响的。

尺寸

因为有的元素宽高是相对的,所以在上一步样式计算中是不会进行宽高的计算的。在当前这步才能计算。

位置

相对包含块的位置。

DOM 树和 Layout 树不一定是一一对应的

因为 Layout 树是找到每个节点的几何信息的,所以有些隐藏的节点是不会在 Layout 树中的。

DOM 树中存在但布局树中不存在的

  • head
  • display:none

DOM 树中不存在但布局树中存在的

  • ::before 伪元素

head 节点为什么是隐藏的

  • 浏览器默认样式中让 head 隐藏

匿名行盒块盒

alt text

  • 内容必须在行盒中
  • 行盒和块盒不能相邻
  • 布局树会添加匿名行盒和块盒 (这三条是 w3c 说的。)

布局树不是 DOM 对象

布局树是 C++ 对象,JS 操作不到。

4. 分层 —— Layer

分层是现代浏览器新引入的机制。为了只更新频繁变动的部分。

alt text

在【浏览器 F12 - 右上角三个点 - 更多工具(More tools)- 图层(Layers)】中。

alt text

浏览器内部有分层策略,不需要我们关心。有些跟堆叠上下文相关的 CSS 属性会影响到分层。

  • z-index
  • opacity
  • transform

不是一定会有影响,只是会影响浏览器的决策。

有一个特殊的 CSS 属性 will-change,会影响分层决策。如果某个元素会频繁变化,但浏览器还没为其单独分层,可以使用这个属性让浏览器把它单独分层。

css
will-change: transform;

面试题

分层

5. 绘制 —— Painted

alt text

生成绘制指令。例如

  • 将笔尖移动到 10, 30
  • 画一个 200 * 300 的矩形
  • 使用红色填充
  • 将笔尖移动到 ...

类似 canvas,实际上 canvas 中用的就是浏览器内核中的绘制指令。

渲染主线程的工作到此为止了,剩余步骤交给其它线程处理。

alt text

面试题

绘制

6. 分块 —— Tiling

将每一层都划分为小的区域,按优先级处理。

优先级

先画视口附近的块。

多线程处理

合成线程做分块,启动更多线程一起处理。

alt text

可以使用系统工具(Mac 系统的活动监视器)来查看。

alt text

面试题

分块

7. 光栅化 —— Raster

将每个块变成位图。

会优先处理视口附近的块。

alt text

光栅化过程中会使用 GPU 进行加速。

alt text

alt text

面试题

光栅化

8. 画 —— Draw

将每个块按照指引信息(quad)交给 GPU 进程,GPU 进程将其交给硬件(显卡),最终呈现。

alt text

为什么要在 GPU 进程中中转

而不是直接交给硬件呢?

因为渲染主线程和合成进程都在渲染进程中,是沙盒环境,而找硬件是系统调用。因此浏览网页过程中不会导致计算机遭受攻击。

transform 是在这步才进行处理的

因为 transform 是在 GPU 中进行矩阵变换。

transform 为什么效率高

GPU 处理矩阵变换快

面试题

完整过程

alt text

  • 解析 html 生成 dom 树和 cssom 树

  • 计算样式 让每个 dom 得到最终样式

  • 布局 计算每个 dom 节点的几何信息

    布局树和 dom 树不一样,不能一一对应

  • 分层 为了提高后续的渲染效率,把页面分为图层,单独进行绘制

  • 绘制 产生绘制指令

  • 分块 绘制指令交给合成线程进行分块

  • 光栅化 对每个层的每个小块进行光栅化,输出位图。优先处理视口附近的小块。

评论区
评论区空空如也
发送评论
名字
0 / 20
邮箱
0 / 100
评论内容
0 / 140
由于是非实名评论,所以不提供删除功能。如果你需要删除你发送的评论,或者是其他人的评论对你造成了困扰,请 发邮件给我 。同时评论区会使用 AI + 人工的方式进行审核,以达到合规要求。

© thebestxt.cc
辽ICP备16009524号-8
本站所有文章版权所有,转载请注明出处