整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          你不知道的瀏覽器渲染原理

          瀏覽器的內核是指支持瀏覽器運行的最核心的程序,分為兩個部分的,一是渲染引擎,另一個是 JS 引擎。渲染引擎在不同的瀏覽器中也不是都相同的。目前市面上常見的瀏覽器內核可以分為這四種:Trident(IE)、Gecko(火狐)、Blink(Chrome、Opera)、Webkit(Safari)。這里面大家最耳熟能詳的可能就是 Webkit 內核了,Webkit 內核是當下瀏覽器世界真正的霸主。

          本文我們就以 Webkit 為例,對現代瀏覽器的渲染過程進行一個深度的剖析。

          想閱讀更多優質文章請猛戳GitHub 博客。

          頁面加載過程

          在介紹瀏覽器渲染過程之前,我們簡明扼要介紹下頁面的加載過程,有助于更好理解后續渲染過程。

          要點如下:

          • 瀏覽器根據 DNS 服務器得到域名的 IP 地址;
          • 向這個 IP 的機器發送 HTTP 請求;
          • 服務器收到、處理并返回 HTTP 請求;
          • 瀏覽器得到返回內容。

          例如在瀏覽器輸入https://juejin.im/timeline,然后經過 DNS 解析,juejin.im對應的 IP 是36.248.217.149(不同時間、地點對應的 IP 可能會不同)。然后瀏覽器向該 IP 發送 HTTP 請求。

          服務端接收到 HTTP 請求,然后經過計算(向不同的用戶推送不同的內容),返回 HTTP 請求,返回的內容如下:


          其實就是一堆 HMTL 格式的字符串,因為只有 HTML 格式瀏覽器才能正確解析,這是 W3C 標準的要求。接下來就是瀏覽器的渲染過程。

          瀏覽器渲染過程


          瀏覽器渲染過程大體分為如下三部分:

          1)瀏覽器會解析三個東西:

          一是 HTML/SVG/XHTML,HTML 字符串描述了一個頁面的結構,瀏覽器會把 HTML 結構字符串解析轉換 DOM 樹形結構。


          二是 CSS,解析 CSS 會產生 CSS 規則樹,它和 DOM 結構比較像。


          三是 Javascript 腳本,等到 Javascript 腳本文件加載后, 通過 DOM API 和 CSSOM API 來操作 DOM Tree 和 CSS Rule Tree。


          2)解析完成后,瀏覽器引擎會通過 DOM Tree 和 CSS Rule Tree 來構造 Rendering Tree。

          • Rendering Tree 渲染樹并不等同于 DOM 樹,渲染樹只會包括需要顯示的節點和這些節點的樣式信息。
          • CSS 的 Rule Tree 主要是為了完成匹配并把 CSS Rule 附加上 Rendering Tree 上的每個 Element(也就是每個 Frame)。
          • 然后,計算每個 Frame 的位置,這又叫 layout 和 reflow 過程。

          3)最后通過調用操作系統 Native GUI 的 API 繪制。

          接下來我們針對這其中所經歷的重要步驟詳細闡述

          構建 DOM

          瀏覽器會遵守一套步驟將 HTML 文件轉換為 DOM 樹。宏觀上,可以分為幾個步驟:


          瀏覽器從磁盤或網絡讀取 HTML 的原始字節,并根據文件的指定編碼(例如 UTF-8)將它們轉換成字符串。

          在網絡中傳輸的內容其實都是 0 和 1 這些字節數據。當瀏覽器接收到這些字節數據以后,它會將這些字節數據轉換為字符串,也就是我們寫的代碼。

          將字符串轉換成 Token,例如:<html>、<body>等。Token 中會標識出當前 Token 是“開始標簽”或是“結束標簽”亦或是“文本”等信息

          這時候你一定會有疑問,節點與節點之間的關系如何維護?

          事實上,這就是 Token 要標識“起始標簽”和“結束標簽”等標識的作用。例如“title”Token 的起始標簽和結束標簽之間的節點肯定是屬于“head”的子節點。


          上圖給出了節點之間的關系,例如:“Hello”Token 位于“title”開始標簽與“title”結束標簽之間,表明“Hello”Token 是“title”Token 的子節點。同理“title”Token 是“head”Token 的子節點。

          • 生成節點對象并構建 DOM

          事實上,構建 DOM 的過程中,不是等所有 Token 都轉換完成后再去生成節點對象,而是一邊生成 Token 一邊消耗 Token 來生成節點對象。換句話說,每個 Token 被生成后,會立刻消耗這個 Token 創建出節點對象。注意:帶有結束標簽標識的 Token 不會創建節點對象。

          接下來我們舉個例子,假設有段 HTML 文本:

          復制代碼

          <html>
          <head>
           <title>Web page parsing</title>
          </head>
          <body>
           <div>
           <h1>Web page parsing</h1>
           <p>This is an example Web page.</p>
           </div>
          </body>
          </html>
          

          上面這段 HTML 會解析成這樣:


          構建 CSSOM

          DOM 會捕獲頁面的內容,但瀏覽器還需要知道頁面如何展示,所以需要構建 CSSOM。

          構建 CSSOM 的過程與構建 DOM 的過程非常相似,當瀏覽器接收到一段 CSS,瀏覽器首先要做的是識別出 Token,然后構建節點并生成 CSSOM。


          在這一過程中,瀏覽器會確定下每一個節點的樣式到底是什么,并且這一過程其實是很消耗資源的。因為樣式你可以自行設置給某個節點,也可以通過繼承獲得。在這一過程中,瀏覽器得遞歸 CSSOM 樹,然后確定具體的元素到底是什么樣式。

          注意:CSS 匹配 HTML 元素是一個相當復雜和有性能問題的事情。所以,DOM 樹要小,CSS 盡量用 id 和 class,千萬不要過渡層疊下去

          構建渲染樹

          當我們生成 DOM 樹和 CSSOM 樹以后,就需要將這兩棵樹組合為渲染樹。


          在這一過程中,不是簡單的將兩者合并就行了。渲染樹只會包括需要顯示的節點和這些節點的樣式信息,如果某個節點是 display: none 的,那么就不會在渲染樹中顯示。

          我們或許有個疑惑:瀏覽器如果渲染過程中遇到 JS 文件怎么處理

          渲染過程中,如果遇到<script>就停止渲染,執行 JS 代碼。因為瀏覽器有 GUI 渲染線程與 JS 引擎線程,為了防止渲染出現不可預期的結果,這兩個線程是互斥的關系。JavaScript 的加載、解析與執行會阻塞 DOM 的構建,也就是說,在構建 DOM 時,HTML 解析器若遇到了 JavaScript,那么它會暫停構建 DOM,將控制權移交給 JavaScript 引擎,等 JavaScript 引擎運行完畢,瀏覽器再從中斷的地方恢復 DOM 構建。

          也就是說,如果你想首屏渲染的越快,就越不應該在首屏就加載 JS 文件,這也是都建議將 script 標簽放在 body 標簽底部的原因。當然在當下,并不是說 script 標簽必須放在底部,因為你可以給 script 標簽添加 defer 或者 async 屬性(下文會介紹這兩者的區別)。

          JS 文件不只是阻塞 DOM 的構建,它會導致 CSSOM 也阻塞 DOM 的構建

          原本 DOM 和 CSSOM 的構建是互不影響,井水不犯河水,但是一旦引入了 JavaScript,CSSOM 也開始阻塞 DOM 的構建,只有 CSSOM 構建完畢后,DOM 再恢復 DOM 構建。

          這是什么情況?

          這是因為 JavaScript 不只是可以改 DOM,它還可以更改樣式,也就是它可以更改 CSSOM。因為不完整的 CSSOM 是無法使用的,如果 JavaScript 想訪問 CSSOM 并更改它,那么在執行 JavaScript 時,必須要能拿到完整的 CSSOM。所以就導致了一個現象,如果瀏覽器尚未完成 CSSOM 的下載和構建,而我們卻想在此時運行腳本,那么瀏覽器將延遲腳本執行和 DOM 構建,直至其完成 CSSOM 的下載和構建。也就是說,在這種情況下,瀏覽器會先下載和構建 CSSOM,然后再執行 JavaScript,最后在繼續構建 DOM


          布局與繪制

          當瀏覽器生成渲染樹以后,就會根據渲染樹來進行布局(也可以叫做回流)。這一階段瀏覽器要做的事情是要弄清楚各個節點在頁面中的確切位置和大小。通常這一行為也被稱為“自動重排”。

          布局流程的輸出是一個“盒模型”,它會精確地捕獲每個元素在視口內的確切位置和尺寸,所有相對測量值都將轉換為屏幕上的絕對像素。

          布局完成后,瀏覽器會立即發出“Paint Setup”和“Paint”事件,將渲染樹轉換成屏幕上的像素。

          以上我們詳細介紹了瀏覽器工作流程中的重要步驟,接下來我們討論幾個相關的問題:

          幾點補充說明

          1.async 和 defer 的作用是什么?有什么區別?

          接下來我們對比下 defer 和 async 屬性的區別:


          其中藍色線代表 JavaScript 加載;紅色線代表 JavaScript 執行;綠色線代表 HTML 解析。

          1)情況 1<script src="script.js"></script>

          沒有 defer 或 async,瀏覽器會立即加載并執行指定的腳本,也就是說不等待后續載入的文檔元素,讀到就加載并執行。

          2)情況 2<script async src="script.js"></script> (異步下載)

          async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在于,如果已經加載好,就會開始執行——無論此刻是 HTML 解析階段還是 DOMContentLoaded 觸發之后。需要注意的是,這種方式加載的 JavaScript 依然會阻塞 load 事件。換句話說,async-script 可能在 DOMContentLoaded 觸發之前或之后執行,但一定在 load 觸發之前執行。

          3)情況 3 <script defer src="script.js"></script>(延遲執行)

          defer 屬性表示延遲執行引入的 JavaScript,即這段 JavaScript 加載時 HTML 并未停止解析,這兩個過程是并行的。整個 document 解析完畢且 defer-script 也加載完成之后(這兩件事情的順序無關),會執行所有由 defer-script 加載的 JavaScript 代碼,然后觸發 DOMContentLoaded 事件。

          defer 與相比普通 script,有兩點區別:載入 JavaScript 文件時不阻塞 HTML 的解析,執行階段被放到 HTML 標簽解析完成之后。

          在加載多個 JS 腳本的時候,async 是無順序的加載,而 defer 是有順序的加載。

          2. 為什么操作 DOM 慢?

          把 DOM 和 JavaScript 各自想象成一個島嶼,它們之間用收費橋梁連接。——《高性能 JavaScript》

          JS 是很快的,在 JS 中修改 DOM 對象也是很快的。在 JS 的世界里,一切是簡單的、迅速的。但 DOM 操作并非 JS 一個人的獨舞,而是兩個模塊之間的協作。

          因為 DOM 是屬于渲染引擎中的東西,而 JS 又是 JS 引擎中的東西。當我們用 JS 去操作 DOM 時,本質上是 JS 引擎和渲染引擎之間進行了“跨界交流”。這個“跨界交流”的實現并不簡單,它依賴了橋接接口作為“橋梁”(如下圖)。


          過“橋”要收費——這個開銷本身就是不可忽略的。我們每操作一次 DOM(不管是為了修改還是僅僅為了訪問其值),都要過一次“橋”。過“橋”的次數一多,就會產生比較明顯的性能問題。因此“減少 DOM 操作”的建議,并非空穴來風。

          3. 你真的了解回流和重繪嗎?

          渲染的流程基本上是這樣(如下圖黃色的四個步驟):

          1. 計算 CSS 樣式

          2. 構建 Render Tree

          3.Layout – 定位坐標和大小

          4. 正式開畫


          注意:上圖流程中有很多連接線,這表示了 Javascript 動態修改了 DOM 屬性或是 CSS 屬性會導致重新 Layout,但有些改變不會重新 Layout,就是上圖中那些指到天上的箭頭,比如修改后的 CSS rule 沒有被匹配到元素。

          這里重要要說兩個概念,一個是 Reflow,另一個是 Repaint

          重繪:當我們對 DOM 的修改導致了樣式的變化、卻并未影響其幾何屬性(比如修改了顏色或背景色)時,瀏覽器不需重新計算元素的幾何屬性、直接為該元素繪制新的樣式(跳過了上圖所示的回流環節)。

          回流:當我們對 DOM 的修改引發了 DOM 幾何尺寸的變化(比如修改元素的寬、高或隱藏元素等)時,瀏覽器需要重新計算元素的幾何屬性(其他元素的幾何屬性和位置也會因此受到影響),然后再將計算的結果繪制出來,這個過程就是回流(也叫重排)。

          我們知道,當網頁生成的時候,至少會渲染一次。在用戶訪問的過程中,還會不斷重新渲染。重新渲染會重復回流 + 重繪或者只有重繪。

          回流必定會發生重繪,重繪不一定會引發回流。重繪和回流會在我們設置節點樣式時頻繁出現,同時也會很大程度上影響性能。回流所需的成本比重繪高的多,改變父節點里的子節點很可能會導致父節點的一系列回流。

          1)常見引起回流屬性和方法

          任何會改變元素幾何信息 (元素的位置和尺寸大小) 的操作,都會觸發回流,

          • 添加或者刪除可見的 DOM 元素;
          • 元素尺寸改變——邊距、填充、邊框、寬度和高度;
          • 內容變化,比如用戶在 input 框中輸入文字;
          • 瀏覽器窗口尺寸改變——resize 事件發生時;
          • 計算 offsetWidth 和 offsetHeight 屬性;
          • 設置 style 屬性的值。

          2)常見引起重繪屬性和方法


          3)如何減少回流、重繪

          • 使用 transform 替代 top;
          • 使用 visibility 替換 display: none ,因為前者只會引起重繪,后者會引發回流(改變了布局);
          • 不要把節點的屬性值放在一個循環里當成循環里的變量。

          復制代碼

          for(let i = 0; i < 1000; i++) {
           // 獲取 offsetTop 會導致回流,因為需要去獲取正確的值
           console.log(document.querySelector('.test').style.offsetTop)
          }
          
          • 不要使用 table 布局,可能很小的一個小改動會造成整個 table 的重新布局;
          • 動畫實現的速度的選擇,動畫速度越快,回流次數越多,也可以選擇使用 requestAnimationFrame;
          • CSS 選擇符從右往左匹配查找,避免節點層級過多;
          • 將頻繁重繪或者回流的節點設置為圖層,圖層能夠阻止該節點的渲染行為影響別的節點。比如對于 video 標簽來說,瀏覽器會自動將該節點變為圖層。

          性能優化策略

          基于上面介紹的瀏覽器渲染原理,DOM 和 CSSOM 結構構建順序,初始化可以對頁面渲染做些優化,提升頁面性能。

          • JS 優化: <script> 標簽加上 defer 屬性 和 async 屬性 用于在不阻塞頁面文檔解析的前提下,控制腳本的下載和執行。
          • defer 屬性: 用于開啟新的線程下載腳本文件,并使腳本在文檔解析完成后執行。
          • async 屬性: HTML5 新增屬性,用于異步下載腳本文件,下載完畢立即解釋執行代碼。
          • CSS 優化: <link> 標簽的 rel 屬性 中的屬性值設置為 preload 能夠讓你在你的 HTML 頁面中可以指明哪些資源是在頁面加載完成后即刻需要的,最優的配置加載順序,提高渲染性能。

          總結

          綜上所述,我們得出這樣的結論:

          • 瀏覽器工作流程:構建 DOM -> 構建 CSSOM -> 構建渲染樹 -> 布局 -> 繪制。
          • CSSOM 會阻塞渲染,只有當 CSSOM 構建完畢后才會進入下一個階段構建渲染樹。
          • 通常情況下 DOM 和 CSSOM 是并行構建的,但是當瀏覽器遇到一個不帶 defer 或 async 屬性的 script 標簽時,DOM 構建將暫停,如果此時又恰巧瀏覽器尚未完成 CSSOM 的下載和構建,由于 JavaScript 可以修改 CSSOM,所以需要等 CSSOM 構建完畢后再執行 JS,最后才重新 DOM 構建。

          參考文章

          • https://segmentfault.com/q/1010000000640869
          • https://coolshell.cn/articles/9666.html
          • https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5c024ecbf265da616a476638
          • https://mp.weixin.qq.com/s?__biz=MzA5NzkwNDk3MQ==&mid=2650588806&idx=1&sn=408a54e7c8102fd6944c9a40b119015a&chksm=8891d6a2bfe65fb42f493fe9a4dab672dd7e440f31e753196cee0cfbc6696e4f8dd3a669e040&mpshare=1&scene=1&srcid=1228ZrXsmbZKcgCSu7zTVDwy#
          • https://juejin.im/book/5b936540f265da0a9624b04b/section/5bac3a4df265da0aa81c043c
          • https://juejin.im/book/5c47343bf265da612b13e5c0/section/5c4737375188255de8397ae3
          • https://juejin.im/book/5a8f9ddcf265da4e9f6fb959/section/5a8f9f7bf265da4e82635e46

          更多內容,請關注前端之巔。

          今天課堂筆記主要講的是HTML5零基礎需要學習和掌握的知識點,我們一起來看主要培訓課程內容:

            1)CSS Bug:CSS樣式在各瀏覽器中解析不一致的情況,或者說CSS樣式在瀏覽器中不能正確顯示的問題稱為CSS bug.

            2)CSS Hack: CSS中,Hack是指一種兼容CSS在不同瀏覽器中正確顯示的技巧方法,因為它們都屬于個人對CSS代碼的非官方的修改,或非官方的補丁。有些人更喜歡使用patch(補丁)來描述這種行為。

            3)Filter:表示過濾器的意思,它是一種對特定的瀏覽器或瀏覽器組顯示或隱藏規則或聲明的方法。本質上講,Filter是一種用來過濾不同瀏覽器的Hack類型。

            *使用Hack帶來的一些副作用

            降低了CSS代碼的可讀性,增加了代碼的負擔。

            *設計CSS Hack和 Filter通常有兩種方法

            1)一種是利用瀏覽器自身的Bug,來隱藏或顯示樣式或聲明;

            2)另一種是利用瀏覽器對CSS支持的不完善,如對某些規則或語法還沒有形成支持,來隱藏或顯示樣式。

            IE6常見CSS解析Bug及hack

            1)圖片間隙

            A)在元素中直接插入圖片時,圖片下方會產生約3像素的間隙(該bug出現在IE6及更低版本中)

            hack1:將

          #FormatImgID_0#轉為塊狀元素,給#FormatImgID_1#添加聲明:display:block;

            hack2:將img設置vertical-align:top/middle/bottom;只要不為baseline

            2) 雙倍浮向(雙倍邊距)

            描述:當Ie6及更低版本瀏覽器在解析浮動元素時,會錯誤地把浮向邊邊界加倍顯示。

            hack:給浮動元素添加聲明:display:inline;

            3)默認高度(IE6)

            描述:在IE6及以下版本中,部分塊元素擁有默認高度(低于16px高度)

            hack1:給元素添加聲明:font-size:0;

            hack2:給元素添加聲明:overflow:hidden;

            4)百分比bug

            描述:在IE6及以下版本中在解析百分比時,會按四舍五入方式計算從而導致50%加50%大于100%的情況。

            hack:給右面的浮動元素添加聲明:clear:right; 意思:清除右浮動。

            5)表單元素高度及對齊方式不一致(IE,MOZ,C,O,S)

            描述:表單元素行高對齊方式不一致

            hack:給表單元素添加聲明:float:left;或vertical-align:top;

            2)表單元素中按鈕的解析是按怪異盒模型解析的。

            3)直接去掉表單控件的邊框時用border:0;border:none;不能兼容ie7以下瀏覽器。

            *透明寫法

            1.opacity:0~1;IE8以上的瀏覽器

            2.filter:alpha(opacity=1~100); IE9及IE9以下的瀏覽器

            6)列表階梯BUG(IE6及更低版本的瀏覽器中)

            bug1:在給的子元素中使用了Float:left;父元素中沒有設置浮動屬性,li階梯狀效果。

            hack:給父元素設置浮動便能解決此問題

            bug2:當給LI里的A轉成塊元素,并設置了固定高度時,且給父元素寫了浮動后在IE6及更低的版本瀏覽器里會出現垂直顯示。

            hack:給a也設置左浮動便可解決。

            8)鼠標指針bug

            描述:cursor屬性的hand屬性值只有IE瀏覽器識別,其它瀏覽器不識別該聲明,cursor屬性的pointer屬性值IE6.0以上版本及其它內核瀏覽器都識別該聲明。

            hack:如統一某元素鼠標指針形狀為手型,應添加聲明:cursor:pointer;

            擴展內容:

            鼠標指針

            cursor:crosshair(十字架)

            pointer(手形)

            move(移動)

            e-resize(左右方向)

            ne-resize(向右及向上移動)

            nw-resize(向上及向左移動)

            n-resize(向上移動)

            se-resize(向下及向右)

            sw-resize(向下及向左)

            s-resize(向下移動)

            w-resize(向左移動)

            text(文本)

            wait(等待狀態)

            help(幫助)

          覽器兼容

          瀏覽器

          瀏覽器大戰

          第一次瀏覽器大戰發生在上個世紀90年代,微軟發布了它的IE瀏覽器,和網景公司的Netscape Navigator瀏覽器大打出手。 ?

          第二次瀏覽器大戰發生在20世紀。 ?

          戰爭產物:Internet Explorer 9


          13年市場比重


          14年市場比重

          15年市場比重

          17年市場比重

          19年市場比重


          瀏覽器內核 ( 現代4大內核 )

          Trident 代表作:IE

          元老級內核之一,由微軟開發,并于1997年10月首次在ie 4.0中使用,憑借其windows壟斷優勢,Trident市場占有率一直很高。然而壟斷并非,沒有競爭就沒有進步,長期以往,Trident內核一度停滯不前,更新緩慢,甚至一度與W3C標準脫節。2011年,從ie 9開始,Trident開始支持HTML5和CSS 3,因此我們也經常會看到有些網站在瀏覽時會提示用戶(在Internet Explorer 9.0+以上瀏覽效果最佳)。前端程序員做瀏覽器兼容一般也不再會考慮ie 8之前的瀏覽器了。

          Gecko 代表作:Mozilla

          元老級內核之一,由Netscape公司Mozilla組織開發。1998年,Netscape在于IE瀏覽器競爭失利之后,成立了非正式組織Mozilla,由其開發新一代內核,后命名為“Gecko”。FireFox也是這班人開發出來了,因此這也就是Mozilla一直使用的內核。 Gecko的特點是代碼完全公開,因此其開發程度很高,全世界的程序員都可以為其編寫代碼,增加功能。

          WebKit : 蘋果 & 谷歌舊版本

          這是蘋果公司開發的內核,也是其旗下產品Ssfari瀏覽器使用的內核。Webkit引擎包含了WebCode排版引擎和JavaScriptCode解析引擎,分別是從KDE的KHTML和KJS衍生而來,它們都是自由軟件,在GPL條約下授權,同時支持BSD系統開發。 Chrome、360極速瀏覽器以及搜狗高速瀏覽器也使用Webkit作為內核(在腳本理解方面,Chorome使用自己研發的V8引擎)。

          Blink : 代表作:谷歌 & 歐鵬

          這是由Google和Opera Software開發的瀏覽器排版引擎,Google計算將這個渲染引擎作為Chromium計劃的一部分,并且在2013年4月公布了這一消息。這一渲染引擎是開源引擎Webkit中WebCore組件的一個分支,并且在Chrome(28及往后版本)、Opera(15及往后版本)和Yandex瀏覽器中使用

          Presto ( Opera前內核 已經廢棄 )


          為什么會出現瀏覽器兼容問題?

          由于各大主流瀏覽器由不同的廠家開發,所用的核心架構和代碼也很難重和,這就為各種莫名其妙的Bug(代碼錯誤)提供了溫床。再加上各大廠商出于自身利益考慮而設置的種種技術壁壘,都讓CSS應用起來比想象得要麻煩。瀏覽器的兼容問題是我們必須去克服的。

          CSS Bug、CSS Hack和Filter

          • CSS Bug: CSS樣式在各瀏覽器中解析不一致的情況,或者說CSS樣式在瀏覽器中不能正確顯示的問題稱為CSS bug.
          • CSS Hack: CSS中,Hack是指一種兼容CSS在不同瀏覽器中正確顯示的技巧方法,因為它們都屬于個人對CSS代碼的非官方的修改,或非官方的補丁。有些人更喜歡使用patch(補丁)來描述這種行為。
          • Filter:表示過濾器的意思,它是一種對特定的瀏覽器或瀏覽器組顯示或隱藏規則或聲明的方法。本質上講,Filter是一種用來過濾不同瀏覽器的Hack類型。


          常見的BUG

          IE低版本常見CSS解析Bug及hack

          1)圖片有邊框BUG

          當圖片加<a href=“#”></a>在IE上會出現邊框

          Hack:給圖片加border:0;或者border:0 none;


          2)圖片間隙

          div中的圖片間隙BUG

          描述:在div中插入圖片時,圖片會將div下方撐大大約三像素。

          hack1:將</div>與<img>寫在一行上;

          hack2:將<img>轉為塊狀元素,給<img>添加聲明:display:block;


          3) 雙倍浮向(雙倍邊距)(只有IE6出現)

          描述:當Ie6及更低版本瀏覽器在解析浮動元素時,會錯誤地把浮向邊邊界(margin)加倍顯示。

          hack:給浮動元素添加聲明:display:inline;


          4)默認高度(IE6、IE7)

          描述:在IE6及以下版本中,部分塊元素擁有默認高度(在16px左右;)

          hack1:給元素添加聲明:font-size:0;

          hack2:給元素添加聲明:overflow:hidden;

          非IE BUG

          5)表單元素對齊不一致

          描述:表單元素行高對齊方式不一致

          hack:給表單元素添加聲明:float:left;


          6)按鈕元素默認大小不一

          描述:各瀏覽器中按鈕元素大小不一致

          hack1: 統一大小/(用a標記模擬)

          hack2:input外邊套一個標簽,在這個標簽里寫按鈕的樣式,把input的邊框去掉。

          hack3:如果這個按鈕是一個圖片,直接把圖片作為按鈕的背景圖即可。


          7)鼠標指針bug

          描述:cursor屬性的hand屬性值只有IE9以下瀏覽器識別,其它瀏覽器不識別該聲明,cursor屬性的pointer屬性值IE6.0以上版本及其它內核瀏覽器都識別該聲明。

          hack: 如統一某元素鼠標指針形狀為手型,

          應添加聲明:cursor:pointer cursor: ;

          auto默認

          crosshair加號

          text文本

          wait等待

          help幫助

          progress過程

          inherit繼承

          move移動

          ne-resize向上或向右移動

          pointer手形

          8)透明屬性

          兼容其他瀏覽器寫法:opacity:value;(value的取值范圍0-1; 例:opacity:0.5;)

          IE瀏覽器寫法:filter:alpha(opacity=value);取值范圍 1-100(整數)

          過濾器

          1.下劃線屬性過濾器

          當在一個屬性前面增加了一個下劃線后,由于符合標準的瀏覽器不能識別帶有下劃線的屬性而忽略了這個聲明,但是在IE6及更低版本瀏覽器中會繼續解析這個規則。


          語法:選擇符{_屬性:屬性值;}


          2. !important


          關鍵字過濾器 它表示所附加的聲明具有最高優先級的意思。但由于IE6及更低版本不能識別它, 我們可以利用IE6的這個Bug作為過濾器來兼容IE6和其它標準瀏覽器。


          語法:選擇符{屬性:屬性值!important;}


          3. *屬性過濾器


          當在一個屬性前面增加了*后,該屬性只能被IE7瀏覽器識別,其它瀏覽器混略該屬 性的作用。


          語法:選擇符{*屬性:屬性值;}


          4. :IE版本識別;其它瀏覽器都不識別

          語法:選擇符{屬性:屬性值;}


          5. >5. \0 : IE8 及以上版本識別;其它瀏覽器都不識別


          主站蜘蛛池模板: 日韩视频一区二区在线观看 | 国产主播在线一区| 白丝爆浆18禁一区二区三区| 2021国产精品一区二区在线| 久久精品国产一区二区三区肥胖 | 免费一区二区三区| 中文字幕一区精品| 91国在线啪精品一区| 中文字幕一区二区三区四区| 精品久久久久中文字幕一区| 精品国产一区二区22| 色婷婷AV一区二区三区浪潮| 亚洲Aⅴ无码一区二区二三区软件| 日本在线电影一区二区三区| 精品日韩亚洲AV无码一区二区三区| 在线免费观看一区二区三区| 亚洲AV无码一区二区三区牲色 | 搜日本一区二区三区免费高清视频| 久久精品午夜一区二区福利| 久久精品国产一区二区三区肥胖| 综合久久一区二区三区| 中文字幕在线观看一区 | 亚洲天堂一区二区三区四区| 亚洲一区二区三区AV无码| 国产无吗一区二区三区在线欢| 天堂一区二区三区精品| 精品国产一区二区三区www| 麻豆精品人妻一区二区三区蜜桃| 欧美激情国产精品视频一区二区| 亚洲高清一区二区三区| 国产日韩精品视频一区二区三区| 国产91大片精品一区在线观看 | 国产精品无码一区二区在线观一| 天美传媒一区二区三区| 国产美女在线一区二区三区| 久久青青草原一区二区| 国产精品福利区一区二区三区四区| 久久精品岛国av一区二区无码| 亚洲色偷偷偷网站色偷一区| 国内精品视频一区二区三区八戒 | 久久国产精品无码一区二区三区 |