整合營銷服務商

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

          免費咨詢熱線:

          25.HTML CSS動畫和過渡

          25.HTML CSS動畫和過渡

          現代網頁設計中,動畫和過渡是提升用戶體驗的重要手段。通過使用 CSS,我們可以在不影響頁面性能的前提下,實現平滑和吸引人的視覺效果。本文將介紹 CSS 動畫和過渡的基礎知識,并通過幾個例子展示如何在你的網站中應用它們。

          CSS 過渡(Transitions)

          CSS 過渡允許你在 CSS 屬性值之間創建平滑的動畫效果。當一個元素的屬性值改變時,過渡效果會在一定時間內平滑地過渡到新的屬性值。

          基本語法

          transition: property duration timing-function delay;
          
          • property:指定要添加過渡效果的 CSS 屬性。
          • duration:過渡效果的持續時間。
          • timing-function:定義速度曲線的函數。
          • delay:過渡效果的延遲時間。

          例子 1:鼠標懸停放大圖片

          img:hover {
            transform: scale(1.2);
            transition: transform 0.3s ease-in-out;
          }
          

          這個例子中,當鼠標懸停在圖片上時,圖片會在0.3秒內放大到原來的1.2倍大小,過渡效果為ease-in-out。

          CSS 動畫(Animations)

          CSS 動畫提供了更強大的控制,允許你創建復雜的動畫序列,通過定義關鍵幀(keyframes)來控制動畫的中間狀態。

          基本語法

          @keyframes animation-name {
            from {
              /* 初始狀態 */
            }
            to {
              /* 結束狀態 */
            }
          }
          

          或者使用百分比來定義多個關鍵幀:

          @keyframes animation-name {
            0% { /* 初始狀態 */ }
            50% { /* 中間狀態 */ }
            100% { /* 結束狀態 */ }
          }
          

          例子 2:無限旋轉圖標

          @keyframes spin {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
          }
          
          .icon-spin {
            animation: spin 2s linear infinite;
          }
          

          這個例子創建了一個名為spin的動畫,使得圖標無限期地旋轉。

          實戰例子

          接下來,我們將通過幾個實戰例子來展示 CSS 動畫和過渡的具體應用。

          例子 3:按鈕點擊波紋效果

          .button {
            position: relative;
            overflow: hidden;
            transition: background-color 0.3s;
          }
          
          .button:after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 5px;
            height: 5px;
            background: rgba(255, 255, 255, 0.7);
            opacity: 0;
            border-radius: 100%;
            transform: scale(1, 1) translate(-50%);
            transform-origin: 50% 50%;
          }
          
          .button:active:after {
            width: 300px;
            height: 300px;
            opacity: 1;
            transition: width 0.5s, height 0.5s, opacity 0s 0.5s;
          }
          

          在這個例子中,當按鈕被點擊時,會產生一個波紋效果,模擬水波紋擴散。

          例子 4:淡入淡出切換效果

          .fade-in {
            animation: fadeIn 1s ease-in-out;
          }
          
          @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
          }
          
          .fade-out {
            animation: fadeOut 1s ease-in-out;
          }
          
          @keyframes fadeOut {
            from { opacity: 1; }
            to { opacity: 0; }
          }
          

          這個例子中定義了兩個動畫,一個用于元素的淡入,另一個用于元素的淡出。

          示例

          <!DOCTYPE html>
          <html lang="en">
          <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>CSS Animation and Transition Example</title>
          <style>
            body {
              font-family: 'Arial', sans-serif;
              margin: 0;
              padding: 0;
              background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
              background-size: 400% 400%;
              animation: gradientBG 15s ease infinite;
              display: flex;
              justify-content: center;
              align-items: center;
              flex-direction: column;
              min-height: 100vh;
            }
          
            @keyframes gradientBG {
              0% { background-position: 0% 50%; }
              50% { background-position: 100% 50%; }
              100% { background-position: 0% 50%; }
            }
          
            .logo {
              font-size: 2em;
              color: #007bff;
              margin-bottom: 20px;
              animation: spin 3s linear infinite;
            }
          
            .scrolling-text {
              margin: 20px 0;
              background-color: #333;
              color: #fff;
              padding: 10px;
              white-space: nowrap;
              overflow: hidden;
              position: relative;
            }
          
            .scrolling-text p {
              position: absolute;
              width: 100%;
              height: 100%;
              margin: 0;
              line-height: 50px;
              text-align: center;
              /* Starting position */
              transform: translateX(100%);
              /* Apply animation to this element */
              animation: scroll-text 10s linear infinite;
            }
          
            @keyframes scroll-text {
              0% { transform: translateX(100%); }
              100% { transform: translateX(-100%); }
            }
          
            .interactive-card {
              background-color: #fff;
              box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
              padding: 20px;
              margin: 20px;
              border-radius: 10px;
              transition: transform 0.3s ease, box-shadow 0.3s ease;
            }
          
            .interactive-card:hover {
              transform: translateY(-10px);
              box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
            }
          
            .color-block {
              width: 100px;
              height: 100px;
              background-color: #17a2b8;
              margin: 20px;
              border-radius: 50%;
              transition: background-color 0.5s ease, transform 0.5s ease;
            }
          
            .color-block:hover {
              background-color: #28a745;
              transform: rotate(180deg);
            }
          </style>
          </head>
          <body>
          
          <div class="logo">
            <i class="fas fa-sync-alt"></i> Animated Logo
          </div>
          
          <div class="scrolling-text">
            <p>This text scrolls infinitely. Pay attention to how it moves smoothly from right to left.</p>
          </div>
          
          <div class="interactive-card">
            <h3>Interactive Card</h3>
            <p>Hover over this card to see it move. It's a simple yet effective way to add interactivity to your design.</p>
          </div>
          
          <div class="color-block"></div>
          
          </body>
          </html>
          

          • .logo 類定義了一個徽標,它具有字體大小和顏色,并應用了一個名為 spin 的關鍵幀動畫,使徽標無限旋轉。
          • .scrolling-text 類定義了一個包含滾動文本的容器,設置了背景顏色、文字顏色和內邊距。
          • .scrolling-text p 選擇器定義了滾動文本的樣式,包括動畫 scroll-text,使文本從右向左無限滾動。
          • .interactive-card 類定義了一個交互式卡片,它具有背景顏色、陰影、內邊距和圓角。當鼠標懸停時,它會向上移動并增加陰影,這是通過 transition 屬性實現的。
          • .color-block 類定義了一個顏色塊,設置了寬度、高度、背景顏色和圓角。當鼠標懸停時,它的背景顏色會改變,并且會旋轉 180 度。
          • body 的背景被設置為一個線性漸變,包含四種顏色。通過 background-size 屬性,我們擴大了背景尺寸,這樣動畫在運行時會有更多的空間進行顏色的過渡。
          • @keyframes gradientBG 關鍵幀動畫被創建來改變背景的位置,從而在不同的顏色之間產生平滑過渡的效果。
          • 該動畫被設置為無限循環,并且每次循環持續 15 秒,通過 ease 時間函數來平滑過渡。

          結語

          CSS 動畫和過渡是前端開發者的強大工具,它們可以在不犧牲性能的情況下為用戶提供流暢、引人注目的界面交互。通過掌握這些技術,你可以創造出更加動態和生動的網頁體驗。記住,動畫應該用來增強用戶體驗,而不是分散用戶的注意力,適量而恰當地使用動畫效果是關鍵。

          多大公司面試喜歡問這樣一道面試題,輸入URL到看見頁面發生了什么? 簡單來說,共有以下幾個過程:

          1. DNS解析
          2. 發起TCP連接
          3. 發送HTTP請求
          4. 服務器處理請求并返回HTTP報文
          5. 瀏覽器解析渲染頁面
          6. 連接結束。

          DNS解析

          DNS解析實際上就是尋找你所需要的資源的過程。假設你輸入www.baidu.com,而這個網址并不是百度的真實地址,互聯網中每一臺機器都有唯一標識的IP地址,這個才是關鍵,但是它不好記,亂七八糟一串數字誰記得住啊,所以就需要一個網址和IP地址的轉換,也就是DNS解析。下面看看具體的解析過程

          具體解析

          DNS解析其實是一個遞歸的過程

          輸入www.google.com網址后,首先在本地的域名服務器中查找,沒找到去根域名服務器查找,沒有再去com頂級域名服務器查找,,如此的類推下去,直到找到IP地址,然后把它記錄在本地,供下次使用。大致過程就是.-> .com ->google.com. -> www.google.com。 (你可能覺得我多寫 .,并木有,這個.對應的就是根域名服務器,默認情況下所有的網址的最后一位都是.,既然是默認情況下,為了方便用戶,通常都會省略,瀏覽器在請求DNS的時候會自動加上)DNS優化

          既然已經懂得了解析的具體過程,我們可以看到上述一共經過了N個過程,每個過程有一定的消耗和時間的等待,因此我們得想辦法解決一下這個問題!

          DNS緩存

          DNS存在著多級緩存,從離瀏覽器的距離排序的話,有以下幾種: 瀏覽器緩存,系統緩存,路由器緩存,IPS服務器緩存,根域名服務器緩存,頂級域名服務器緩存,主域名服務器緩存

          DNS負載均衡

          不知道你們有沒有注意這樣一件事,你訪問baidu.com的時候,每次響應的并非是同一個服務器(IP地址不同),一般大公司都有成百上千臺服務器來支撐訪問,假設只有一個服務器,那它的性能和存儲量要多大才能支撐這樣大量的訪問呢?DNS可以返回一個合適的機器的IP給用戶,例如可以根據每臺機器的負載量,該機器離用戶地理位置的距離等等,這種過程就是DNS負載均衡

          發起TCP連接

          TCP提供一種可靠的傳輸,這個過程涉及到三次握手,四次揮手,下面我們詳細看看 TCP提供一種面向連接的,可靠的字節流服務。 其首部的數據格式如下

          字段分析

          • 源端口:源端口和IP地址的作用是標識報文的返回地址。
          • 目的端口:端口指明接收方計算機上的應用程序接口。

          TCP報頭中的源端口號和目的端口號同IP數據報中的源IP與目的IP唯一確定一條TCP連接。

          • 序號:是TCP可靠傳輸的關鍵部分。序號是該報文段發送的數據組的第一個字節的序號。在TCP傳送的流中,每一個字節都有一個序號。比如一個報文段的序號為300,報文段數據部分共有100字節,則下一個報文段的序號為400。所以序號確保了TCP傳輸的有序性。
          • 確認序號:即ACK,指明下一個期待收到的字節序號,表明該序號之前的所有數據已經正確無誤的收到。確認號只有當ACK標志為1時才有效。比如建立連接時,SYN報文的ACK標志位為0。
          • 首部長度/數據偏移:占4位,它指出TCP報文的數據距離TCP報文段的起始處有多遠。由于首部可能含有可選項內容,因此TCP報頭的長度是不確定的,報頭不包含任何任選字段則長度為20字節,4位首部長度字段所能表示的最大值為1111,轉化為10進制為15,15*32/8=60,故報頭最大長度為60字節。首部長度也叫數據偏移,是因為首部長度實際上指示了數據區在報文段中的起始偏移值。
          • 保留:占6位,保留今后使用,但目前應都位0。
          • 控制位:URG ACK PSH RST SYN FIN,共6個,每一個標志位表示一個控制功能。
          • 緊急URG:當URG=1,表明緊急指針字段有效。告訴系統此報文段中有緊急數據
          • 確認ACK:僅當ACK=1時,確認號字段才有效。TCP規定,在連接建立后所有報文的傳輸都必須把ACK置1。
          • 推送PSH:當兩個應用進程進行交互式通信時,有時在一端的應用進程希望在鍵入一個命令后立即就能收到對方的響應,這時候就將PSH=1。
          • 復位RST:當RST=1,表明TCP連接中出現嚴重差錯,必須釋放連接,然后再重新建立連接。
          • 同步SYN:在連接建立時用來同步序號。當SYN=1,ACK=0,表明是連接請求報文,若同意連接,則響應報文中應該使SYN=1,ACK=1。
          • 終止FIN:用來釋放連接。當FIN=1,表明此報文的發送方的數據已經發送完畢,并且要求釋放。
          • 窗口:滑動窗口大小,用來告知發送端接受端的緩存大小,以此控制發送端發送數據的速率,從而達到流量控制。窗口大小時一個16bit字段,因而窗口大小最大為65535。
          • 校驗和:奇偶校驗,此校驗和是對整個的 TCP 報文段,包括 TCP 頭部和 TCP 數據,以 16 位字進行計算所得。由發送端計算和存儲,并由接收端進行驗證。
          • 緊急指針:只有當 URG 標志置 1 時緊急指針才有效。緊急指針是一個正的偏移量,和順序號字段中的值相加表示緊急數據最后一個字節的序號。 TCP 的緊急方式是發送端向另一端發送緊急數據的一種方式。
          • 選項和填充:最常見的可選字段是最長報文大小,又稱為MSS(Maximum Segment Size),每個連接方通常都在通信的第一個報文段(為建立連接而設置SYN標志為1的那個段)中指明這個選項,它表示本端所能接受的最大報文段的長度。選項長度不一定是32位的整數倍,所以要加填充位,即在這個字段中加入額外的零,以保證TCP頭是32的整數倍。
          • 數據部分: TCP 報文段中的數據部分是可選的。在一個連接建立和一個連接終止時,雙方交換的報文段僅有 TCP 首部。如果一方沒有數據要發送,也使用沒有任何數據的首部來確認收到的數據。在處理超時的許多情況中,也會發送不帶任何數據的報文段。

          需要注意的是: (A)不要將確認序號Ack與標志位中的ACK搞混了。 (B)確認方Ack=發起方Req+1,兩端配對。

          三次握手

          第一次握手:

          客戶端發送syn包(Seq=x)到服務器,并進入SYN_SEND狀態,等待服務器確認;

          第二次握手:

          服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(Seq=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

          第三次握手:

          客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

          握手過程中傳送的包里不包含數據,三次握手完畢后,客戶端與服務器才正式開始傳送數據。理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去。

          為什么會采用三次握手,若采用二次握手可以嗎? 四次呢?

          建立連接的過程是利用客戶服務器模式,假設主機A為客戶端,主機B為服務器端。

          采用三次握手是為了防止失效的連接請求報文段突然又傳送到主機B,因而產生錯誤。失效的連接請求報文段是指:主機A發出的連接請求沒有收到主機B的確認,于是經過一段時間后,主機A又重新向主機B發送連接請求,且建立成功,順序完成數據傳輸。考慮這樣一種特殊情況,主機A第一次發送的連接請求并沒有丟失,而是因為網絡節點導致延遲達到主機B,主機B以為是主機A又發起的新連接,于是主機B同意連接,并向主機A發回確認,但是此時主機A根本不會理會,主機B就一直在等待主機A發送數據,導致主機B的資源浪費。

          采用兩次握手不行,原因就是上面說的失效的連接請求的特殊情況。而在三次握手中, client和server都有一個發syn和收ack的過程, 雙方都是發后能收, 表明通信則準備工作OK.

          為什么不是四次握手呢? 大家應該知道通信中著名的藍軍紅軍約定, 這個例子說明, 通信不可能100%可靠, 而上面的三次握手已經做好了通信的準備工作, 再增加握手, 并不能顯著提高可靠性, 而且也沒有必要。

          四次揮手

          數據傳輸完畢后,雙方都可釋放連接。最開始的時候,客戶端和服務器都是處于ESTABLISHED狀態,假設客戶端主動關閉,服務器被動關閉。

          第一次揮手:

          客戶端發送一個FIN,用來關閉客戶端到服務器的數據傳送,也就是客戶端告訴服務器:我已經不會再給你發數據了(當然,在fin包之前發送出去的數據,如果沒有收到對應的ack確認報文,客戶端依然會重發這些數據),但是,此時客戶端還可以接受數據。 FIN=1,其序列號為seq=u(等于前面已經傳送過來的數據的最后一個字節的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即使不攜帶數據,也要消耗一個序號。

          第二次揮手:

          服務器收到FIN包后,發送一個ACK給對方并且帶上自己的序列號seq,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號)。此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處于半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。

          此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最后的數據)。

          第三次揮手:

          服務器發送一個FIN,用來關閉服務器到客戶端的數據傳送,也就是告訴客戶端,我的數據也發送完了,不會再給你發數據了。由于在半關閉狀態,服務器很可能又發送了一些數據,假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最后確認)狀態,等待客戶端的確認。

          第四次揮手:

          主動關閉方收到FIN后,發送一個ACK給被動關閉方,確認序號為收到序號+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連接還沒有釋放,必須經過2?MSL(最長報文段壽命)的時間后,當客戶端撤銷相應的TCB后,才進入CLOSED狀態。

          服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB后,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些

          至此,完成四次揮手。

          為什么客戶端最后還要等待2MSL?

          MSL(Maximum Segment Lifetime),TCP允許不同的實現可以設置不同的MSL值。

          第一,保證客戶端發送的最后一個ACK報文能夠到達服務器,因為這個ACK報文可能丟失,站在服務器的角度看來,我已經發送了FIN+ACK報文請求斷開了,客戶端還沒有給我回應,應該是我發送的請求斷開報文它沒有收到,于是服務器又會重新發送一次,而客戶端就能在這個2MSL時間段內收到這個重傳的報文,接著給出回應報文,并且會重啟2MSL計時器。

          第二,防止類似與“三次握手”中提到了的“已經失效的連接請求報文段”出現在本連接中。客戶端發送完最后一個確認報文后,在這個2MSL時間中,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。這樣新的連接中不會出現舊連接的請求報文。

          為什么建立連接是三次握手,關閉連接確是四次揮手呢?

          建立連接的時候, 服務器在LISTEN狀態下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發送給客戶端。 而關閉連接時,服務器收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,而自己也未必全部數據都發送給對方了,所以己方可以立即關閉,也可以發送一些數據給對方后,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送,從而導致多了一次。

          發送HTTP請求

          首先科補一個小知識,HTTP的端口為80/8080,而HTTPS的端口為443

          發送HTTP請求的過程就是構建HTTP請求報文并通過TCP協議中發送到服務器指定端口 請求報文由請求行請求報頭請求正文組成。

          請求行

          請求行的格式為Method Request-URL HTTP-Version CRLF eg: GET index.html HTTP/1.1 常用的方法有: GET,POST, PUT, DELETE, OPTIONS, HEAD。

          常見的請求方法區別

          這里主要展示POST和GET的區別

          常見的區別

          • GET在瀏覽器回退時是無害的,而POST會再次提交請求。
          • GET產生的URL地址可以被Bookmark,而POST不可以。
          • GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
          • GET請求只能進行url編碼,而POST支持多種編碼方式。
          • GET請求參數會被完整保留在瀏覽器歷史記錄里,而POST中的參數不會被保留。
          • GET請求在URL中傳送的參數是有長度限制的,而POST么有。
          • 對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
          • GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感信息。
          • GET參數通過URL傳遞,POST放在Request body中。

          注意一點你也可以在GET里面藏body,POST里面帶參數

          重點區別

          GET會產生一個TCP數據包,而POST會產生兩個TCP數據包。

          詳細的說就是:

          • 對于GET方式的請求,瀏覽器會把http header和data一并發送出去,服務器響應200(返回數據);
          • 而對于POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。

          注意一點,并不是所有的瀏覽器都會發送兩次數據包,Firefox就發送一次

          請求報頭

          請求報頭允許客戶端向服務器傳遞請求的附加信息和客戶端自身的信息。

          從圖中可以看出,請求報頭中使用了Accept, Accept-Encoding, Accept-Language, Cache-Control, Connection, Cookie等字段。Accept用于指定客戶端用于接受哪些類型的信息,Accept-Encoding與Accept類似,它用于指定接受的編碼方式。Connection設置為Keep-alive用于告訴客戶端本次HTTP請求結束之后并不需要關閉TCP連接,這樣可以使下次HTTP請求使用相同的TCP通道,節省TCP連接建立的時間。

          請求正文

          當使用POST, PUT等方法時,通常需要客戶端向服務器傳遞數據。這些數據就儲存在請求正文中。在請求包頭中有一些與請求正文相關的信息,例如: 現在的Web應用通常采用Rest架構,請求的數據格式一般為json。這時就需要設置Content-Type: application/json。

          更重要的事情-HTTP緩存

          HTTP屬于客戶端緩存,我們常認為瀏覽器有一個緩存數據庫,用來保存一些靜態文件,下面我們分為以下幾個方面來簡單介紹HTTP緩存

          • 緩存的規則
          • 緩存的方案
          • 緩存的優點
          • 不同刷新的請求執行過程

          緩存的規則

          緩存規則分為強制緩存協商緩存

          強制緩存

          當緩存數據庫中有客戶端需要的數據,客戶端直接將數據從其中拿出來使用(如果數據未失效),當緩存服務器沒有需要的數據時,客戶端才會向服務端請求。

          協商緩存

          又稱對比緩存。客戶端會先從緩存數據庫拿到一個緩存的標識,然后向服務端驗證標識是否失效,如果沒有失效服務端會返回304,這樣客戶端可以直接去緩存數據庫拿出數據,如果失效,服務端會返回新的數據

          強制緩存的優先級高于協商緩存,若兩種緩存皆存在,且強制緩存命中目標,則協商緩存不再驗證標識。

          緩存的方案

          上面的內容讓我們大概了解了緩存機制是怎樣運行的,但是,服務器是如何判斷緩存是否失效呢?我們知道瀏覽器和服務器進行交互的時候會發送一些請求數據和響應數據,我們稱之為HTTP報文。報文中包含首部header和主體部分body。與緩存相關的規則信息就包含在header中。boby中的內容是HTTP請求真正要傳輸的部分。舉個HTTP報文header部分的例子如下:

          我們依舊分為強制緩存和協商緩存來分析。

          強制緩存

          對于強制緩存,服務器響應的header中會用兩個字段來表明——Expires和Cache-Control。

          Expires

          Exprires的值為服務端返回的數據到期時間。當再次請求時的請求時間小于返回的此時間,則直接使用緩存數據。但由于服務端時間和客戶端時間可能有誤差,這也將導致緩存命中的誤差,另一方面,Expires是HTTP1.0的產物,故現在大多數使用Cache-Control替代。

          Cache-Control

          Cache-Control有很多屬性,不同的屬性代表的意義也不同。

          • private:客戶端可以緩存
          • public:客戶端和代理服務器都可以緩存
          • max-age=t:緩存內容將在t秒后失效
          • no-cache:需要使用協商緩存來驗證緩存數據
          • no-store:所有內容都不會緩存。

          協商緩存

          協商緩存需要進行對比判斷是否可以使用緩存。瀏覽器第一次請求數據時,服務器會將緩存標識與數據一起響應給客戶端,客戶端將它們備份至緩存中。再次請求時,客戶端會將緩存中的標識發送給服務器,服務器根據此標識判斷。若未失效,返回304狀態碼,瀏覽器拿到此狀態碼就可以直接使用緩存數據了。

          對于協商緩存來說,緩存標識我們需要著重理解一下,下面我們將著重介紹它的兩種緩存方案。

          Last-Modified

          Last-Modified:服務器在響應請求時,會告訴瀏覽器資源的最后修改時間。

          • if-Modified-Since:瀏覽器再次請求服務器的時候,請求頭會包含此字段,后面跟著在緩存中獲得的最后修改時間。服務端收到此請求頭發現有if-Modified-Since,則與被請求資源的最后修改時間進行對比,如果一致則返回304和響應報文頭,瀏覽器只需要從緩存中獲取信息即可。 從字面上看,就是說:從某個時間節點算起,是否文件被修改了
          • 如果真的被修改:那么開始傳輸響應一個整體,服務器返回:200 OK
          • 如果沒有被修改:那么只需傳輸響應header,服務器返回:304 Not Modified
          • if-Unmodified-Since:從字面上看, 就是說: 從某個時間點算起, 是否文件沒有被修改
          • 如果沒有被修改:則開始`繼續'傳送文件: 服務器返回: 200 OK
          • 如果文件被修改:則不傳輸,服務器返回: 412 Precondition failed (預處理錯誤)

          這兩個的區別是一個是修改了才下載一個是沒修改才下載。

          Last-Modified 說好卻也不是特別好,因為如果在服務器上,一個資源被修改了,但其實際內容根本沒發生改變,會因為Last-Modified時間匹配不上而返回了整個實體給客戶端(即使客戶端緩存里有個一模一樣的資源)。為了解決這個問題,HTTP1.1推出了Etag。

          Etag

          Etag:服務器響應請求時,通過此字段告訴瀏覽器當前資源在服務器生成的唯一標識(生成規則由服務器決定)

          • If-None-Match:再次請求服務器時,瀏覽器的請求報文頭部會包含此字段,后面的值為在緩存中獲取的標識。服務器接收到次報文后發現If-None-Match則與被請求資源的唯一標識進行對比。
          • 不同,說明資源被改動過,則響應整個資源內容,返回狀態碼200。
          • 相同,說明資源無心修改,則響應header,瀏覽器直接從緩存中獲取數據信息。返回狀態碼304.

          但是實際應用中由于Etag的計算是使用算法來得出的,而算法會占用服務端計算的資源,所有服務端的資源都是寶貴的,所以就很少使用Etag了。

          緩存的優點

          • 減少了冗余的數據傳遞,節省寬帶流量
          • 減少了服務器的負擔,大大提高了網站性能
          • 加快了客戶端加載網頁的速度 這也正是HTTP緩存屬于客戶端緩存的原因。

          不同刷新的請求執行過程

          瀏覽器地址欄中寫入URL,回車

          • 瀏覽器發現緩存中有這個文件了,不用繼續請求了,直接去緩存拿。(最快)

          F5

          • F5就是告訴瀏覽器,別偷懶,好歹去服務器看看這個文件是否有過期了。于是瀏覽器就戰戰兢兢的發送一個請求帶上If-Modify-since。

          Ctrl+F5

          • 告訴瀏覽器,你先把你緩存中的這個文件給我刪了,然后再去服務器請求個完整的資源文件下來。于是客戶端就完成了強行更新的操作.

          服務器處理請求并返回HTTP報文

          它會對TCP連接進行處理,對HTTP協議進行解析,并按照報文格式進一步封裝成HTTP Request對象,供上層使用。這一部分工作一般是由Web服務器去進行,我使用過的Web服務器有Tomcat, Nginx和Apache等等 HTTP報文也分成三份,狀態碼響應報頭響應報文

          狀態碼

          狀態碼是由3位數組成,第一個數字定義了響應的類別,且有五種可能取值:

          • 1xx:指示信息–表示請求已接收,繼續處理。
          • 2xx:成功–表示請求已被成功接收、理解、接受。
          • 3xx:重定向–要完成請求必須進行更進一步的操作。
          • 4xx:客戶端錯誤–請求有語法錯誤或請求無法實現。
          • 5xx:服務器端錯誤–服務器未能實現合法的請求。 平時遇到比較常見的狀態碼有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500

          常見狀態碼區別

          200 成功

          請求成功,通常服務器提供了需要的資源。

          204 無內容

          服務器成功處理了請求,但沒有返回任何內容。

          301 永久移動

          請求的網頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。

          302 臨時移動

          服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以后的請求。

          304 未修改

          自從上次請求后,請求的網頁未修改過。 服務器返回此響應時,不會返回網頁內容。

          400 錯誤請求

          服務器不理解請求的語法。

          401 未授權

          請求要求身份驗證。 對于需要登錄的網頁,服務器可能返回此響應。

          403 禁止

          服務器拒絕請求。

          404 未找到

          服務器找不到請求的網頁。

          422 無法處理

          請求格式正確,但是由于含有語義錯誤,無法響應

          500 服務器內部錯誤

          服務器遇到錯誤,無法完成請求。

          響應報頭

          常見的響應報頭字段有: Server, Connection...。

          響應報文

          你從服務器請求的HTML,CSS,JS文件就放在這里面

          瀏覽器解析渲染頁面

          • 這個圖就是Webkit解析渲染頁面的過程。解析HTML形成DOM樹
          • 解析CSS形成CSSOM 樹
          • 合并DOM樹和CSSOM樹形成渲染樹
          • 瀏覽器開始渲染并繪制頁面 這個過程涉及兩個比較重要的概念回流重繪,DOM結點都是以盒模型形式存在,需要瀏覽器去計算位置和寬度等,這個過程就是回流。等到頁面的寬高,大小,顏色等屬性確定下來后,瀏覽器開始繪制內容,這個過程叫做重繪。瀏覽器剛打開頁面一定要經過這兩個過程的,但是這個過程非常非常非常消耗性能,所以我們應該盡量減少頁面的回流和重繪

          性能優化之回流重繪

          回流

          當Render Tree中部分或全部元素的尺寸、結構、或某些屬性發生改變時,瀏覽器重新渲染部分或全部文檔的過程稱為回流。

          會導致回流的操作:

          • 頁面首次渲染
          • 瀏覽器窗口大小發生改變
          • 元素尺寸或位置發生改變
          • 元素內容變化(文字數量或圖片大小等等)
          • 元素字體大小變化
          • 添加或者刪除可見的DOM元素
          • 激活CSS偽類(例如::hover)
          • 查詢某些屬性或調用某些方法

          一些常用且會導致回流的屬性和方法:

          • clientWidth、clientHeight、clientTop、clientLeft
          • offsetWidth、offsetHeight、offsetTop、offsetLeft
          • scrollWidth、scrollHeight、scrollTop、scrollLeft
          • scrollIntoView()、scrollIntoViewIfNeeded()
          • getComputedStyle()
          • getBoundingClientRect()
          • scrollTo()

          重繪

          當頁面中元素樣式的改變并不影響它在文檔流中的位置時(例如:color、background-color、visibility等),瀏覽器會將新樣式賦予給元素并重新繪制它,這個過程稱為重繪。

          優化

          CSS

          • 避免使用table布局。
          • 盡可能在DOM樹的最末端改變class。
          • 避免設置多層內聯樣式。
          • 將動畫效果應用到position屬性為absolute或fixed的元素上。
          • 避免使用CSS表達式(例如:calc())。

          JavaScript

          • 避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式列表定義為class并一次性更改class屬性。
          • 避免頻繁操作DOM,創建一個documentFragment,在它上面應用所有DOM操作,最后再把它添加到文檔中。
          • 也可以先為元素設置display: none,操作結束后再把它顯示出來。因為在display屬性為none的元素上進行的DOM操作不會引發回流和重繪。
          • 避免頻繁讀取會引發回流/重繪的屬性,如果確實需要多次使用,就用一個變量緩存起來。
          • 對具有復雜動畫的元素使用絕對定位,使它脫離文檔流,否則會引起父元素及后續元素頻繁回流。

          動高亮效果

          • 源碼
          
          <style>
            a {
              text-decoration: none;
              color: #8c7ae6;
              font-size: 24px;
              box-shadow: inset 0 0 0 #8c7ae6;
          
              transition: all 300ms ease-in-out;
            }
          
            a:hover {
              box-shadow: inset 180px 0 0 0 #8c7ae6;
              color: white;
            }
          
          </style>
          <a href="#">Hover this link</a>

          文本交換效果

          • 源碼
          <style>
            a {
              overflow: hidden;
              position: relative;
              display: inline-block;
            }
          
            a::before,
            a::after {
              content: "";
              position: absolute;
              width: 100%;
              left: 0;
            }
            a::before {
              background-color: #54b3d6;
              height: 2px;
              bottom: 0;
              transform-origin: 100% 50%;
              transform: scaleX(0);
              transition: transform 0.3s ease-in-out;
            }
            a::after {
              content: attr(data-replace);
              height: 100%;
              top: 0;
              transform-origin: 100% 50%;
              transform: translate3d(200%, 0, 0);
              transition: transform 0.3s ease-in-out;
              color: #54b3d6;
            }
          
            a:hover::before {
              transform-origin: 0% 50%;
              transform: scaleX(1);
            }
            a:hover::after {
              transform: translate3d(0, 0, 0);
            }
          
            a span {
              display: inline-block;
              transition: transform 0.3s ease-in-out;
            }
          
            a:hover span {
              transform: translate3d(-200%, 0, 0);
            }
          
            body {
              display: grid;
              font-size: 27px;
              height: 100vh;
              place-items: center;
            }
          
            a {
              text-decoration: none;
              color: #18272f;
              font-weight: 700;
              vertical-align: top;
            }
          </style>
          
          <p>Hover <a href="#" id="style-2" data-replace="this link">
            <span>this link</span>
          </a></p>

          背景拉伸效果

          • 源碼
          <style>
            a {
              text-decoration: none;
              color: #18272f;
              font-weight: 700;
              position: relative;
            }
          
            a::before {
              content: "";
              background-color: #00a8ff;
              position: absolute;
              left: 0;
              bottom: 3px;
              width: 100%;
              height: 8px;
              z-index: -1;
              transition: all 300ms ease-in-out;
            }
          
            a:hover::before {
              bottom: 0;
              height: 100%;
            }
          
            body {
              display: grid;
              font-size: 27px;
              line-height: 1.5;
              height: 100vh;
              place-items: center;
            }
          </style>
          
          <p>Hover this <a href="#">cool</a> link.</p>

          從右到左顏色交換效果

          • 源碼
          <style>
            a {
              background-image: linear-gradient(to right, #54b3d6, #54b3d6 50%, #000 50%);
              background-size: 200% 100%;
              background-position: -100%;
              display: inline-block;
              padding: 5px 0;
              position: relative;
          
              -webkit-background-clip: text;
              -webkit-text-fill-color: transparent;
              transition: all 300ms ease-in-out;
            }
          
            a:before {
              content: "";
              background: #54b3d6;
              display: block;
              position: absolute;
              bottom: -3px;
              left: 0;
              width: 0;
              height: 3px;
              transition: all 300ms ease-in-out;
            }
          
            a:hover {
              background-position: 0;
            }
          
            a:hover::before {
              width: 100%;
            }
          
            body {
              display: grid;
              font-size: 27px;
              height: 100vh;
              place-items: center;
            }
          </style>
          
          <a href="">Hover This Link</a>

          彩虹下劃線效果

          • 源碼
          <style>
            a {
              color: black;
              text-decoration: none;
              background: linear-gradient(to right, #64c8c8, #64c8c8),
                linear-gradient(to right, #ff0000, #ff00b4, #0064c8);
              background-size: 100% 3px, 0 3px;
              background-position: 100% 100%, 0 100%;
              background-repeat: no-repeat;
              transition: background-size 400ms;
            }
          
            a:hover {
              background-size: 0 3px, 100% 3px;
            }
          
            body {
              display: grid;
              font-size: 27px;
              font-weight: 700;
              height: 100vh;
              place-items: center;
            }
          </style>
          
          <a href="">Hover This Link</a>

          原文地址:https://css-tricks.com/css-link-hover-effects/


          主站蜘蛛池模板: 99热门精品一区二区三区无码| 一区二区三区观看免费中文视频在线播放 | 亚洲国产一区二区三区 | 人妻视频一区二区三区免费| 91福利一区二区| 成人区精品一区二区不卡亚洲| 亚洲一区二区影视| 精品熟人妻一区二区三区四区不卡 | 国产AV午夜精品一区二区入口 | 中字幕一区二区三区乱码| 韩国美女vip福利一区| 精品无码成人片一区二区98| 中文字幕日韩一区二区不卡| 亚洲变态另类一区二区三区| 色综合视频一区二区三区44| 日韩精品免费一区二区三区| 动漫精品一区二区三区3d| 视频在线一区二区三区| 国产精品亚洲产品一区二区三区| 久久国产精品免费一区| 亚洲AV综合色区无码一区爱AV| 人妻无码一区二区不卡无码av| 亚洲一区在线免费观看| 亚洲av无码一区二区三区人妖| 怡红院美国分院一区二区 | 日韩毛片基地一区二区三区| 欧美日韩国产免费一区二区三区| 天天躁日日躁狠狠躁一区| 国产精品 视频一区 二区三区| 亚洲一区无码中文字幕| 精品人妻码一区二区三区 | 久久综合九九亚洲一区| 2021国产精品视频一区| 全国精品一区二区在线观看| 国产成人无码AV一区二区在线观看 | 天堂va在线高清一区| 国产精品视频一区二区三区经| 无码丰满熟妇浪潮一区二区AV | 色窝窝无码一区二区三区| 国产精品99精品一区二区三区 | 中日韩一区二区三区|