整合營銷服務商

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

          免費咨詢熱線:

          你不知道的CSS濾鏡

          前言

          在日常開發中,對于圖像不同效果的處理,通常需要設計側的專業知識和技能,同時開發側也需要增加額外的圖片資源的請求。為了避免引入多個圖片資源且和增加一些額外的配置項去實現不同效果的處理,我們可以使用CSS的濾鏡屬性直接對元素進行效果處理,而不需要對每個元素的不同效果引入相關的圖片文件,從而能提高更大的靈活性和可維護性。



          2 背景

          在開發過程中我們總會碰到這樣的場景:符合條件時按鈕或圖片高亮展示,不符合條件時按鈕或圖片置灰展示。

          我們可能很自然地就去想這無非就是用兩種樣式:高亮的和非高亮的樣式,兩種樣式對應的按鈕顏色或者圖片路徑不同。那么要是每個按鈕或圖片都不一樣,我們就需要對每一個高亮的場景都去做一個灰色場景的處理,即便是走配置化的數據,那么我們也都需要配置兩份數據去做展示,這樣不僅配置麻煩且工作效率較低。

          如果我們只想要配置一套數據的話,其實可以使用filter濾鏡去進行實現,我們可以利用其grayscale屬性,將配置好高亮圖片轉換為灰度圖像進行實現,參考效果如下圖所示。

          圖1 獎勵領取置灰效果圖

          filter濾鏡就是css3新增的一個神奇功能,它可以對網頁中的圖片進行類似Photoshop圖片處理的效果,但并不需要依賴于任何作圖軟件。同時,filter濾鏡不僅可以對圖片添加濾鏡效果,還可以對網頁元素甚至視頻進行濾鏡處理。



          3 基本概念

          filter屬性通過調整濾鏡函數的參數,可以改變元素的顏色、透明度、亮度、對比度等視覺特性。

          • 作用對象:使用該屬性的元素本身。
          • 使用方式:filter函數 <filter-function> 或使用url添加的svg濾鏡。
          filter: <filter-function> [<filter-function>]* | none
          filter: url(file.svg#filter-element-id)


          3.1 基礎函數

          3.1.1 blur

          blur(radius)函數將高斯模糊應用到圖像。radius 定義了高斯函數的標準偏差值,或者屏幕上有多少像素相互融合,值越大模糊程度越高。若未設置值,默認為 0。

          圖2 blur濾鏡效果對比圖


          3.1.2 brightness

          brightness(amount)函數讓圖像更明亮或更暗淡。值為 0% 將創建全黑圖像,值為 100% 會使輸入保持不變,值大于 100% 提供更明亮的結果。若未設置值,默認為 1。

          圖3 brightness濾鏡效果對比圖

          3.1.3 contrast

          contrast(amount)函數可調整輸入圖像的對比度。值是 0% 圖像會全黑,值為100% 圖像不變,值可以超過 100%,意味著會運用更低的對比。若未設置值,默認是 1。

          圖4 contrast濾鏡效果對比圖


          3.1.4 drop-shadow

          drop-shadow(offset-x offset-y blur-radius color) 可在圖像后方應用投影。陰影可以設置模糊度,以特定顏色畫出的遮罩圖的偏移版本,最終合成在圖像下面。

          圖5 drop-shadow濾鏡效果對比圖


          3.1.5 grayscale

          grayscale(amount)函數可將圖像轉為灰度圖。amount的值定義了轉換的比例,值在 0% 到 100% 之間,值為 0% 圖像無變化,值為 100%則完全轉為灰度圖像。若未設置值,默認是 0。

          圖6 grayscale濾鏡效果對比圖


          3.1.6 hue-rotate

          hue-rotate(angle)函數可在圖像應用色相旋轉,angle的值設定圖像會被調整的色環角度值。值為 0deg,則圖像無變化,超過 360deg相當于又繞一圈。若未設置值,默認為 0deg。

          圖7 hue-rotate濾鏡效果對比圖


          3.1.7 invert

          invert(amount)函數可反轉圖像顏色。amount的值定義轉換的比例,值在 0% 和 100% 之間,值為 0% 則圖像無變化,值為 100% 則圖像完全反轉。若未設置值,則默認為 0。

          圖8 invert濾鏡效果對比圖


          3.1.8 opacity

          opacity(amount) 函數可改變圖像透明度。amount的值定義轉換的比例,值在 0% 和 100% 之間,值為 0% 則是完全透明,值為 100% 則圖像無變化。若未設置值,則默認為 1。該函數與css的opacity 屬性很相似,不同之處在于通過 filter,一些瀏覽器為了提升性能會提供硬件加速。

          圖9 opacity濾鏡效果對比圖


          3.1.9 saturate

          saturate(amount)函數可轉換圖像飽和度。amount的值定義轉換的比例,值為 0% 則是完全不飽和,值為 100% 則圖像無變化,超過 100% 則有更高的飽和度。若未設置值,則默認為 1。

          圖10 saturate濾鏡效果對比圖


          3.1.10 sepia

          sepia(amount) 函數可將圖像轉換為深褐色。amount的值定義轉換的比例,值在 0% 到 100% 之間,值為 0% 圖像無變化,值為 100% 則完全是深褐色的。若未設置值,則默認為 0。

          圖11 sepia濾鏡效果對比圖


          3.2 復合函數

          從filter函數的使用方式可以看出,濾鏡效果是可以進行疊加的,比如,filter: contrast(50%) brightness(50%)。

          圖12 組合濾鏡效果圖

          那么同一元素上定義多個濾鏡的話,濾鏡的先后順序對最后效果有影響嗎?我們調換濾鏡順序換成filter: brightness(50%) contrast(50%)來看看。

          圖13 組合濾鏡順序變換效果圖

          由上圖可以看出,濾鏡的先后順序不同產生的效果也是不一樣的。原因在于濾鏡順序不同,濾鏡的色值處理算法對圖片處理的先后順序也就不一樣,最終產生的效果就不一樣。

          其實CSS濾鏡不僅可以組合使用實現很多視覺效果,也可以通過結合不同的濾鏡效果和CSS動畫,去實現一些奇妙的動畫效果。



          4 動畫效果

          4.1 文字融合動畫

          文字融合動畫就是一種文字從融合到分開的效果,我們可以通過改變letter-spacing和blur的值去進行效果實現。

            <div class="container">
              <div class="text">Hello World</div>
            </div>
          .container {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #000;
            filter: contrast(30);
          }
          
          
          .text {
            color: #fff;
            font-size: 100px;
            animation: show 3s linear forwards;
          }
          
          
          @keyframes show {
            0% {
              opacity: 0;
              letter-spacing: -50px;
              filter: blur(10px);
            }
          
          
            25% {
              opacity: 1;
              filter: blur(8px);
            }
          
          
            50% {
              filter: blur(5px);
            }
          
          
            100% {
              letter-spacing: 10px;
              filter: blur(2px);
            }
          }


          ,時長00:03


          4.2 手機充電動畫

          該動畫其實就是一種模擬安卓手機充電時的動畫效果,主要就是通過contrast濾鏡以及blur濾鏡去實現很好的融合效果。

          <div class="g-container">
            <div class="g-number">90%</div>
            <div class="g-contrast">
              <div class="g-circle"></div>
              <ul class="g-bubbles">
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
              </ul>
            </div>
          </div>
          .g-container {
            position: relative;
            width: 300px;
            height: 400px;
            margin: auto;
          }
          
          
          .g-number {
            position: absolute;
            top: 100px;
            width: 100%;
            color: #fff;
            font-size: 30px;
            text-align: center;
            z-index: 10;
          }
          
          
          .g-contrast {
            width: 100%;
            height: 100%;
            background-color: #000;
            overflow: hidden;
            filter: contrast(10) hue-rotate(0);
            animation: hueRotate 10s infinite linear;
          }
          
          
          .g-circle {
            position: relative;
            width: 300px;
            height: 300px;
            box-sizing: border-box;
            filter: blur(8px);
          }
          
          
          .g-circle::after {
            content: "";
            position: absolute;
            top: 40%;
            left: 50%;
            transform: translate(-50%, -50%) rotate(0);
            width: 200px;
            height: 200px;
            background-color: #00ff6f;
            border-radius: 42% 38% 62% 49%/45%;
            animation: rotate 10s infinite linear;
          }
          
          
          .g-circle::before {
            content: "";
            position: absolute;
            width: 176px;
            height: 176px;
            top: 40%;
            left: 50%;
            transform: translate(-50%, -50%);
            border-radius: 50%;
            background-color: #000;
            z-index: 10;
          }
          
          
          .g-bubbles {
            position: absolute;
            left: 50%;
            bottom: 0;
            width: 100px;
            height: 40px;
            transform: translate(-50%, 0);
            border-radius: 100px 100px 0 0;
            background-color: #00ff6f;
            filter: blur(5px);
          }
          
          
          li {
            position: absolute;
            border-radius: 50%;
            background: #00ff6f;
          }
          
          
          li:nth-child(0) {
            left: 50px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 16px;
            height: 16px;
            animation: move 4s ease-in-out -1.47s infinite;
          }
          
          
          li:nth-child(1) {
            left: 55px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 18px;
            height: 18px;
            animation: move 6s ease-in-out -2.23s infinite;
          }
          
          
          li:nth-child(2) {
            left: 60px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 20px;
            height: 20px;
            animation: move 5s ease-in-out -3.89s infinite;
          }
          
          
          li:nth-child(3) {
            left: 65px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 22px;
            height: 22px;
            animation: move 7s ease-in-out -4.56s infinite;
          }
          
          
          li:nth-child(4) {
            left: 70px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 24px;
            height: 24px;
            animation: move 9s ease-in-out -2.12s infinite;
          }
          
          
          li:nth-child(5) {
            left: 75px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 26px;
            height: 26px;
            animation: move 9s ease-in-out -1.98s infinite;
          }
          
          
          li:nth-child(6) {
            left: 80px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 23px;
            height: 23px;
            animation: move 5s ease-in-out -3.35s infinite;
          }
          
          
          li:nth-child(7) {
            left: 63px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 19px;
            height: 19px;
            animation: move 7s ease-in-out -4.34s infinite;
          }
          
          
          li:nth-child(8) {
            left: 67px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 25px;
            height: 25px;
            animation: move 6s ease-in-out -2.87s infinite;
          }
          
          
          li:nth-child(9) {
            left: 73px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 28px;
            height: 28px;
            animation: move 8s ease-in-out -3.45s infinite;
          }
          
          
          li:nth-child(10) {
            left: 56px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 24px;
            height: 24px;
            animation: move 7s ease-in-out -1.83s infinite;
          }
          
          
          li:nth-child(11) {
            left: 45px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 25px;
            height: 25px;
            animation: move 5s ease-in-out -2.67s infinite;
          }
          
          
          li:nth-child(12) {
            left: 68px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 19px;
            height: 19px;
            animation: move 6s ease-in-out -3.12s infinite;
          }
          
          
          li:nth-child(13) {
            left: 54px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 29px;
            height: 29px;
            animation: move 9s ease-in-out -2.22s infinite;
          }
          
          
          li:nth-child(14) {
            left: 41px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 27px;
            height: 27px;
            animation: move 5s ease-in-out -1.11s infinite;
          }
          
          
          li:nth-child(15) {
            left: 51px;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 24px;
            height: 24px;
            animation: move 7s ease-in-out -3.23s infinite;
          }
          
          
          @keyframes rotate {
            50% {
              border-radius: 45%/42% 38% 58% 49%;
            }
          
          
            100% {
              transform: translate(-50%, -50%) rotate(720deg);
            }
          }
          
          
          @keyframes move {
            90% {
              opacity: 1;
            }
          
          
            100% {
              opacity: 0.1;
              transform: translate(-50%, -180px);
            }
          }
          
          
          @keyframes hueRotate {
            100% {
              filter: contrast(15) hue-rotate(360deg);
            }
          }

          圖14 手機充電動畫效果圖



          4.3 電影謝幕動畫

          電影謝幕動畫其實就是圖片逐漸消失而謝幕文案逐漸模糊顯示的效果,我們可以使用filter屬性中的blur和brightness濾鏡來模擬該效果的實現。

          <div class="main">
            <div class="img"></div>
            <div class="text">Thank you for watching!</div>
          </div>
          .main {
            width: 100vw;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: #000;
          }
          
          
          .img {
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            width: 100%;
            background: url("xxx.png");
            background-size: cover;
            animation: imgHide 3s linear forwards;
          }
          
          
          .text {
            color: #fff;
            font-size: 50px;
            opacity: 0;
            animation: textShow 2s linear forwards;
          }
          
          
          @keyframes imgHide {
            0% {
              filter: brightness(1);
            }
            100% {
              filter: brightness(0);
            }
          }
          @keyframes textShow {
            0% {
              opacity: 0;
              filter: blur(8px) brightness(50%);
            }
            100% {
              opacity: 1;
              filter: blur(0) brightness(100%);
            }
          }


          ,時長00:03


          4.4. 彩虹文字動畫

          彩虹文字動畫其實就是一種動態變化文字顏色的效果。該動畫效果的實現就是通過動態地改變hue-rotate的值,使文字顏色在一定范圍內進行循環變化產生動態顏色。

           <div>MAINTO MEMBER CENTER</div>
          div {
            font-size: 80px;
            background-clip: text;
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-image: linear-gradient(to right, red, orange, yellow, green, cyan, blue, purple);
            animation: huerotate 6s linear infinite;
          }
          
          
          @keyframes huerotate {
            from { filter: hue-rotate(0deg); }
            to { filter: hue-rotate(360deg); }
          }

          效果圖片如下所示:

          圖15 彩虹文字動畫效果圖

          同樣我們也可以通過這種方式去實現一種動態背景顏色變換的效果。

          div {
              background: linear-gradient(45deg, #5fddcc, #ff004d);
              animation: hueRotate 10s infinite alternate;
          }
          
          
          @keyframes hueRotate {
              0 {
                  filter: hue-rotate(0);
              }
              100% {
                  filter: hue-rotate(360deg);
              }
          }


          圖16 動態背景顏色變換效果圖

          這些通過CSS動畫或JavaScript控制去實時改變元素上的濾鏡效果,從而在頁面上產生動態變化的視覺效果又叫做動態濾鏡效果,那與之相對應的不會發生改變或動態變化自然就是靜態濾鏡效果。靜態濾鏡效果在開發中經常被使用,下面我們就來聊聊在日常營銷業務中的一些常見的靜態濾鏡的使用場景。



          5 業務場景

          5.1 網頁置灰效果

          基于一些特殊時期或者特定重大事件的背景下,我們需要把網站頁面變成黑白色或灰色,以表尊敬和紀念。實現網頁的置灰效果并不需要將所有的圖片和文字都手動換成灰色,這種方法十分繁瑣且不現實。它的實現主要是通過filter的grayscale屬性,由于濾鏡filter會直接影響所有的后代元素,所以只需要給html添加一個統一的灰色濾鏡就可以。

          html {
            filter: grayscale(.95);
          }

          圖17 網頁置灰效果圖


          5.2 集卡明暗效果

          我們在集卡活動中經常會看到,未點亮的卡片是暗色顯示,只有獲得了此卡才會高亮顯示。這種明暗效果的實現并不用區分點亮和未點亮的卡片進行顯示,這其實就可以使用filter的brightness屬性進行實現,默認情況下降低亮度,只有點亮了的卡片才恢復亮度。

          .unactive {
            filter:  brightness(0.5);
          }
           .active {
            filter: brightness(1);
          }

          圖18 集卡明暗效果圖


          5.3 圖像陰影效果

          大多數情況下設計提供給我們的圖片都是直接使用,如果需要加上陰影的話會默認在圖片上進行處理。那么如果是配置化的圖片需要統一加上陰影效果呢,開發側能不能進行統一處理?能的話又要怎么處理呢?

          打個比方我們需要給下面的卡券圖片再加個陰影效果:

          圖19 卡券圖片

          設置陰影的方式我們腦子里肯定首先就會想到box-shadow屬性,我們先來看看它的的使用方式。

          box-shadow: offset-x offset-y  blur spread color inset;

          從box-shadow接受的參數可以看出,drop-shadow可接受的參數和box-shadow屬性基本是一樣的,但不包含擴張半徑spread和inset內陰影等關鍵字。那他們實現的陰影效果是不是一樣的呢?我們先用box-shadow來實現看看。

          box-shadow: 2px 4px 3px rgba(50, 50, 0, 0.5);


          圖20 卡券圖片box-shadow效果圖

          如上圖陰影是加了,但是好像哪里不太對,為什么直接給圖片外圍增加了一個陰影,并沒有在卡券本身添加陰影呢?

          這是因為在給透明圖片添加陰影效果時無法穿透元素,只能添加到透明圖片元素的盒模型上,所以最終呈現效果如上圖所示。下面我們來使用filter的drop-shadow屬性看看。

          filter: drop-shadow(2px 4px 3px rgba(50, 50, 0, 0.5));

          圖21 卡券圖片drop-shadow效果圖

          如上圖才是我們期望的效果,陰影效果只作用到卡券本身,這說明drop-shadow的陰影效果是可以穿透透明元素的。除此之外,通過濾鏡一些瀏覽器為了更好的性能會提供硬件加速。但是在使用drop-shadow的投影時,需要注意的是任何非透明的部分都會被打上投影,包括文本(如果背景是透明的)。

          圖22 drop-shadow效果對比圖


          5.4 毛玻璃效果

          毛玻璃效果是一種常見的視覺效果,它模擬了玻璃表面上由于光線折射而產生的模糊和透明感。我們經常需要使用毛玻璃效果處理內容模糊,以此達到一個信息保護的效果,或者進行背景模糊突出主要內容,引導用戶進行操作,在日常開發中其實就是使用了filter的blur屬性進行實現的。比如說我們需要給一些產品卡片設置毛玻璃效果:

          圖23 毛玻璃效果范圍超出對比圖

          使用filter添加模糊后,實際看到的大小會超出我們設置的寬高,這是由于周圍的毛邊效果產生的,我們可以通過外層設置 overflow: hidden進行處理。不過其實使用filter實現的毛玻璃效果并不是唯一且最好的方式,我們也可以用backdrop-filter屬性去實現漂亮的毛玻璃效果,我們來看看他們的實現效果有什么區別。

          圖24 毛玻璃效果對比圖

          從上圖可以看出,filter明顯是對圖片本身進行了一個模糊處理,而dropback-filter卻像是有一個模糊的遮罩層在上面,我們來看看具體的元素結構。

          圖25 毛玻璃效果元素結構對比圖

          由元素結構可以看出,使用backdrop-filter的效果確實比使用filter的效果多了一層置于圖片上層的元素,blur效果也并不是作用于圖片本身,而是作用于圖片的上層元素。

          沒錯,backdrop-filter并不是通過處理圖片本身來實現毛玻璃的效果,而是通過在圖片上面蓋上一個模糊層從而達到毛玻璃的效果,因此要做模糊處理的圖片必須置于使用backdrop-filter元素的下面。

          那么這個backdrop-filter又是什么呢,與filter又有什么關系或者有區別呢?



          6. backdrop-filter

          backdrop-filter可以給元素后面區域添加圖形效果(如模糊或顏色偏移),而filter屬性是將模糊或顏色偏移等圖形效果應用于元素。雖然backdrop-filter使用方式同filter屬性一致,但它適用于元素背后的所有元素,不過為了看到效果,必須使元素或其背景至少部分透明。

          既然backdrop-filter和filter的語法相同,那所支持的濾鏡效果和呈現效果會不會也一樣呢?

          屬性值

          filter

          drop-filter

          說明

          blur

          支持

          支持

          高斯模糊


          brightness

          支持

          支持

          亮度

          contrast

          支持

          支持

          對比度

          drop-shadow

          支持

          支持

          陰影

          grayscale

          支持

          支持

          灰度

          hue-rotate

          支持

          支持

          色相

          invert

          支持

          支持

          反相

          opacity

          支持

          支持

          透明度

          sepia

          支持

          支持

          飽和度

          saturate

          支持

          支持

          褐色

          url

          支持

          支持

          SVG過濾器的URL

          由上可知,filter和backdrop-filter支持的濾鏡是一模一樣的。不過,與filter 不同的就是backdrop-filter是應用于元素后面的內容而不是元素本身,而filter卻是作用于元素本身,所以呈現出來的濾鏡效果當然是有些不同的。為了更好地看出作用元素的區別,我們再舉個簡單的例子,依然是模糊效果。

          <div class="main">
            <div class="child">none</div>
            <div class="child filter">filter</div>
            <div class="child backdrop-filter">backdrop-filter</div>
          </div>
          .main {
            width:100vw;
            height:100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            background: url("xxx.png");
            background-size: cover;
          }
          .child {
            width: 400px;
            height:300px;
            color: #fff;
            font-size: 20px;
            text-align: center;
            line-height: 300px;
            background: rgba(0, 0, 0, .7);
            margin-left: 20px;
          }
          .filter {
            filter: blur(8px);
          }
          .backdrop-filter {
            backdrop-filter: blur(8px);
          }

          圖26 濾鏡作用元素效果對比圖

          由上圖我們可以看到filter屬性確實只將作用元素本身進行了模糊處理,包括元素的背景和文本內容,而backdrop-filter作用的元素本身卻沒有任何效果,但是它背后的背景圖片部分確實被進行了模糊處理,其實在出現backdrop-filter屬性之前,是很難實現給元素背后特定的區域添加濾鏡效果的。

          那既然濾鏡的這兩個屬性都這么厲害為什么還是不怎么常見,難道是因為兼容性不太好嗎?



          7. 兼容性

          圖27 filter兼容性說明圖

          filter屬性在現代瀏覽器中有很好的支持,包括Chrome、Firefox、Safari、Edge等主流瀏覽器,部分版本仍需要添加前綴進行兼容性處理。

          圖28 dropback-filter兼容性說明圖

          dropback-filter屬性的兼容性相對較低,僅在一些較新版本的瀏覽器中得到支持,且安卓移動端支持較弱。

          由上可知,filter屬性在大部分瀏覽器中具有良好的兼容性,但只能調整元素本身的效果;backdrop-filter屬性適用于調整元素后面內容的效果,但兼容性相對較差。所以還是需要根據具體的需求和是否需要廣泛支持的場景,選擇適合的屬性去進行對應濾鏡效果的處理。

          需要注意的是:作用了filter和backdrop-filter的元素會使內部的fixed定位失效,原因是filter值不為none的元素和backdrop-filter值不為none的元素,都會生成新的堆疊上下文。我們都知道css中position: fixed是相對于屏幕視口進行定位的,而作用了filter和backdrop-filter的元素會使得其內部的position: fixed元素不再相對于屏幕視口進行定位,而是相對這個父元素進行定位。



          8. 最后

          CSS濾鏡技術是一個強大而有趣的工具,可以在不依賴圖像編輯軟件的情況下,在網頁設計中應用不同的濾鏡效果,也可以為元素增添生動、豐富的視覺效果。

          在本文中,我們先介紹了各種濾鏡函數的基礎用法和顯示效果,了解了它們如何改變元素的外觀和視覺表現。隨后,我們了解了如何通過靈活地應用不同的濾鏡函數和組合,去創造出更復雜、個性化的濾鏡效果,去實現圖像處理和動畫,為網頁設計增添了更多創意和動感。我們還知道了通過使用filter屬性,可以簡單地應用模糊(blur)、對比度(contrast)和亮度(brightness)調整、顏色調整等效果,讓網頁元素瞬間煥發生機。而backdrop-filter屬性則允許我們對元素背景內容進行處理,為網頁帶來更深度的視覺層次。

          但是,在使用濾鏡效果時我們也要考慮兼容性和性能問題,盡量避免過度使用濾鏡造成頁面加載緩慢。雖然大多數現代瀏覽器都支持CSS濾鏡,但一些高級濾鏡在較舊的瀏覽器或移動設備上可能會有兼容性問題。因此,我們在使用濾鏡時需要進行兼容性測試,并在必要時提供備用方案,以確保在不同平臺和設備上都能展現良好的效果。


          本文作者


          柯琦,來自縵圖互聯網中心前端團隊。

          來源-微信公眾號:縵圖coder

          出處:https://mp.weixin.qq.com/s/x15DGBjOyL8EWtt78xJESg


          度發布是指在黑與白之間,能夠平滑過渡的一種發布方式。AB test就是一種灰度發布方式,讓一部分用戶繼續用A,一部分用戶開始用B,如果用戶對B沒有什么反對意見,那么逐步擴大范圍,把所有用戶都遷移到B上面來。

          灰度發布可以保證整體系統的穩定,在初始灰度的時候就可以發現、調整問題,以保證其影響度。

          灰度發布常見一般有三種方式:

          • Nginx+LUA方式
          • 根據Cookie實現灰度發布
          • 根據來路IP實現灰度發布

          本文主要將講解根據Cookie和來路IP這兩種方式實現簡單的灰度發布,Nginx+LUA這種方式涉及內容太多就不再本文展開了。

          A/B測試流程




          Nginx根據Cookie實現灰度發布

          根據Cookie查詢Cookie鍵為version的值,如果該Cookie值為V1則轉發到hilinux_01,為V2則轉發到hilinux_02。Cookie值都不匹配的情況下默認走hilinux_01所對應的服務器。

          兩臺服務器分別定義為:

          hilinux_01  192.168.1.100:8080
          hilinux_02  192.168.1.200:8080

          用if指令實現

          upstream hilinux_01 {
              server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
          }
          
          upstream hilinux_02 {
              server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
          }
          
          upstream default {
              server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
          }
          
          server {
            listen 80;
            server_name  www.hi-linux.com;
            access_log  logs/www.hi-linux.com.log  main;
          
            #match cookie
            set $group "default";
              if ($http_cookie ~* "version=V1"){
                  set $group hilinux_01;
              }
          
              if ($http_cookie ~* "version=V2"){
                  set $group hilinux_02;
              }
          
            location / {                       
              proxy_pass http://$group;
              proxy_set_header   Host             $host;
              proxy_set_header   X-Real-IP        $remote_addr;
              proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
              index  index.html index.htm;
            }
           }

          用map指令實現

          在Nginx里面配置一個映射,$COOKIE_version可以解析出Cookie里面的version字段。$group是一個變量,{}里面是映射規則。

          如果一個version為V1的用戶來訪問,$group就等于hilinux_01。在server里面使用就會代理到http://hilinux_01上。version為V2的用戶來訪問,$group就等于hilinux_02。在server里面使用就會代理到http://hilinux_02上。Cookie值都不匹配的情況下默認走hilinux_01所對應的服務器。

          upstream hilinux_01 {
              server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
          }
          
          upstream hilinux_02 {
              server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
          }
          
          upstream default {
              server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
          }
          
          map $COOKIE_version $group {
          ~*V1$ hilinux_01;
          ~*V2$ hilinux_02;
          default default;
          }
          
          server {
            listen 80;
            server_name  www.hi-linux.com;
            access_log  logs/www.hi-linux.com.log  main;
          
            location / {                       
              proxy_pass http://$group;
              proxy_set_header   Host             $host;
              proxy_set_header   X-Real-IP        $remote_addr;
              proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
              index  index.html index.htm;
            }
           }

          Nginx根據來路IP實現灰度發布

          如果是內部IP,則反向代理到hilinux_02(預發布環境);如果不是則反向代理到hilinux_01(生產環境)。

          upstream hilinux_01 {
              server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
          }
          
          upstream hilinux_02 {
              server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
          }
          
          upstream default {
              server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
          }
          
          server {
            listen 80;
            server_name  www.hi-linux.com;
            access_log  logs/www.hi-linux.com.log  main;
          
            set $group default;
            if ($remote_addr ~ "211.118.119.11") {
                set $group hilinux_02;
            }
          
          location / {                       
              proxy_pass http://$group;
              proxy_set_header   Host             $host;
              proxy_set_header   X-Real-IP        $remote_addr;
              proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
              index  index.html index.htm;
            }
          }

          如果你只有單臺服務器,可以根據不同的IP設置不同的網站根目錄來達到相同的目的。

          server {
            listen 80;
            server_name  www.hi-linux.com;
            access_log  logs/www.hi-linux.com.log  main;
          
            set $rootdir "/var/www/html";
              if ($remote_addr ~ "211.118.119.11") {
                 set $rootdir "/var/www/test";
              }
          
              location / {
                root $rootdir;
              }
          }

          到此最基本的實現灰度發布方法就講解完了,如果要做更細粒度灰度發布可參考ABTestingGateway項目。

          ABTestingGateway是新浪開源的一個動態路由系統。ABTestingGateway是一個可以動態設置分流策略的灰度發布系統,工作在7層,基于nginx和ngx-lua開發,使用redis作為分流策略數據庫,可以實現動態調度功能。

          ABTestingGateway:https://github.com/CNSRE/ABTestingGateway

          SS是一個很獨特的語言??雌饋矸浅:唵?,但是某種特殊效果看似簡單,實現起來就頗有難度。這篇文章主要是給在學習前端的童鞋分享一些新的CSS技巧,一些在前端教程和培訓課堂中不會講到的知識。第二就是讓還在前端開發這條道路上的童鞋們,重新燃起對前端排版和特效的熱愛和熱情!

          1. 固定底部內容

          這種是一個非常常見的布局方式,但是對于新手來說是比較常見的難題。

          這種布局方式在后臺管理系統中比較常見,當我們內容不足瀏覽器窗口高度時,底部內容需要固定在底部。當內容超出了瀏覽器窗口高度,就會隨著內容往后推。

          在有CSS3之前,實現這個效果是頗有難度的。瀏覽器窗口高度是會根據不同用戶打開瀏覽器的情況,屏幕大小的差異和瀏覽器的縮放比例而變。我們需要借助JavaScript來實時獲取瀏覽器高度進行運算才能實現。雖然說標題是說“固定”底部,但是我們想要的效果不是position: fixed。使用固定定位,在內容高于窗口高度時,就會擋住我們的內容。

          隨著CSS3的來臨,最完美的實現方式是使用Flexbox。實現的關鍵就是使用不太被關注的flex-grow屬性,可以在我們的內容標簽元素(比如div)中使用。在我們下面的例子里使用了main標簽。

          我來講解一下實現原理吧。

          flew-grow是用來控制一個flex元素相對它同等級flex元素的自身可擴充的空間。如果我們使用flex-grow: 0,那這個flex元素就完全不會擴展了。所以我們需要把頭部和底部之間的內容標簽元素設置為flex-grow: 1或者flex-grow: auto,這樣內容部分就會自動填充滿頭部和底部之外的所有空間。

          為了避免底部內容受內容部分擴充空間的影響,我們給footer底部元素flex-shrink: 0屬性。flex-shrink的作用與flex-grow是恰恰相反,用來控制flex元素收縮的空間,這里我們給了flex-shrink: 0就是為了底部footer的大小不受影響。

          我們直接上HTML和CSS代碼看看是怎么實現的。

          • HTML
          <div id="document">
          	<nav>
          		<h1>頭部內容</h1>
          	</nav>
          	<main>
          		<p>可以添加更多內容看看底部的變化哦!</p>
          	</main>
          	<footer>
          		<h1>底部內容</h1>
          	</footer>
          </div>
          • CSS
          #document {
              height: 100vh;
              display: flex;
              flex-direction: column;
              background: #202020;
              font-family: microsoft yahei,wenquanyi micro hei,sans-serif !important;
          }
          
          nav, footer {
              background: #494949;
              display: flex;
              justify-content: center;
          }
          
          main {
              color: #bdbdbd;
              flex: auto;
          }
          
          footer {
              flex-shrink: 0;
          }
          
          * {
              margin: 0;
          }
          
          h1,
          p {
              padding: 15px;
          }
          
          nav > h1 {
              color: #82FCFD;
              text-shadow: 1px 1px 4px #00000080;
          }
          
          footer > h1 {
              color: #82FCFD;
              text-shadow: 1px 1px 4px #00000080;
          }

          知識點總結:

          flex-grow --- 是用來控制一個flex元素相對它同等級flex元素的自身可擴充的空間 flex-shrink --- 作用與flex-grow是恰恰相反,用來控制flex元素收縮的空間

          2. 懸停放大圖片特效

          懸停放大圖片是一個特別吸引眼球的特效,比較常用于可點擊的圖片。當用戶懸停鼠標在圖片上,圖片會稍微的放大。

          其實實現這個特效是非常簡單的。首先我們需要一個div包裹這img標簽,這個包裹層是用來遮擋住圖片,當圖片放大時不會出現圖片超出我們規定的寬高以外。

          首先我們來講講div包裹的屬性,我們需要給它一個固定的width寬和height高。然后我們必須給予這個元素overflow: hidden屬性。讓圖片放大的時候不會超出這個div元素的寬高。有了這個包裹層,我們就可以編寫img的各種效果了。

          我的例子里面用了transform: scale(1,1)作為懸停時的圖片特效,這個transform是用于改變任何元素的屬性的,然后scale是用于放大(整數就會放大)或者縮小(負數就會縮?。┰氐?。

          上代碼讓大家看看:

          • html body中放入
          <div class="img-wrapper">
            <img src="https://img-blog.csdnimg.cn/2020032122230564.png"/>
          </div>
          • CSS
          .img-wrapper {
            width: 400px;
            height: 400px;
            overflow: hidden;
            box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
          }
          
          .img-wrapper img {
            height: 400px;
            -webkit-transition: 0.3s linear;
            transition: 0.3s linear;
          }
          
          .img-wrapper img:hover {
            transform: scale(1.1);
          }
          
          .img-wrapper {
            display: inline-block;
            box-sizing: border-box;
            border: 3px solid #000;
          }

          如果你們想讓圖片更加炫酷可以加上圖片過濾屬性filter,讓圖片變灰或者變深褐色,然后懸停時候出現更加炫酷的顏色變幻?;一膶傩允莊ilter: grayscale(100%);,然后深褐色化的屬性是filter: sepia(100%)。其實圖片還有很多過濾屬性的,大家有興趣也可以去嘗試一下哦!

          加入特殊效果的代碼如下:

          • HTML
          <!-- 灰度過濾 -->
          <div class="img-wrapper">
            <img
              class="grayscale-img"
              src="https://img-blog.csdnimg.cn/2020032211021728.png"
            />
          </div>
          
          <!-- 深褐色過濾 -->
          <div class="img-wrapper">
            <img
              class="sepia-img"
              src="https://img-blog.csdnimg.cn/2020032122230564.png"
            />
          </div>
          • CSS
          /* ============== 
          * 灰度過濾 
          * ==============*/
          .grayscale-img {
            -webkit-filter: grayscale(100%);
            filter: grayscale(100%);
          }
          
          .grayscale-img:hover {
            -webkit-filter: grayscale(0);
            filter: grayscale(0);
          }
          
          /* ============== 
          * 深褐色過濾
          * ==============*/
          .sepia-img {
            -webkit-filter: sepia(100%);
            filter: sepia(100%);
          }
          
          .sepia-img:hover {
            -webkit-filter: sepia(0);
            filter: sepia(0);
          }

          知識總結

          transform --- 用于改變元素 scale --- 對元素進行放大和縮小 filter --- 圖片過濾器 grayscale --- 灰度過濾 sepia --- 深褐色過濾

          3. 瞬間黑暗模式

          最近微信也逃脫不了黑暗時代的到來,網頁也很多都做了黑暗模式的兼容和主題。如果我們在做的一個網站想瞬間實現黑暗模式可以怎么實現呢?

          其實有一個很快的方式,我們可以使用invert和hue-rotate兩個CSS3過濾器來實現。

          filter: invert() — 是從0到1的刻度,1是從白變黑。 filter: hue-rotate() — 用于改變你元素的顏色,同時或多或少保持原本相同的色系。這個屬性的值可以從0deg到360deg。

          在我們頁面的body標簽上添加這兩個屬性,我們就可以快速嘗試把我們的網站變成"黑暗模式"。這里需要注意的是,如果body和html上沒有設置background背景顏色,這個過濾就會不起效了哦。

          CSS的代碼如下:

          html {
            background: #fff;
          }
          
          body {
            background: #fff;
            filter: invert(1) hue-rotate(270deg);
          }

          實現效果

          這里我們會發現圖片的顏色會受影響,并不是很美觀,使用css過濾器是無法完美切換黑暗模式的。不過使用JavaScript輔助就可以完美的切換黑暗模式。

          最近出了一個JavaScript輔助插件叫Darkmode.js。

          Darkmode.js

          其實Darkmode.js運用的也是css里面的一個特性叫mix-blend-mode — “CSS 屬性描述了元素的內容應該與元素的直系父元素的內容和元素的背景如何混合“。加上Javascript的輔助判斷哪些頁面上的元素需要黑化的,哪些是不需要黑化的。就會想我們之前那種做法,導致其他不需要黑化的元素,比如圖片,受到影響導致顏色出現問題。

          使用Darkmode.js非常簡單,只要在腳本里面添加以下代碼就可以馬上加入一個插件,

          <script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.5/lib/darkmode-js.min.js"></script>
          <script>
            // 這些是這個插件的可配置項:
            var options = {
              bottom: "32px", // 定位底部距離 - 默認: '32px'
              right: "32px", // 定位右邊距離 - 默認: '32px'
              left: "unset", // 定位左邊距離 - 默認: 'unset'
              time: "0.5s", // 默認動畫時間: '0.3s'
              mixColor: "#fff", // 需要改變的顏色 - 默認: '#fff'
              backgroundColor: "#fff", // 背景顏色 - 默認: '#fff'
              buttonColorDark: "#262728", // 黑暗模式下按鈕顏色 - 默認: '#100f2c'
              buttonColorLight: "#fff", // 日間模式下按鈕顏色 - 默認: '#fff'
              saveInCookies: true, // 是否在cookie保存當前模式 - 默認: true,
              label: "", // 切換模式按鈕圖標 - 默認: ''
              autoMatchOsTheme: true // 是否自動根據系統適應模式 - 默認: true
            };
          
            let darkmode = new Darkmode(options);
            darkmode.showWidget();
          </script>

          如果你不希望用這個插件的默認按鈕,你可以在你的JavaScript代碼中自主控制。我們可以通過.toggle()方法來切換模式,同時可以使用.isActivated()來檢測是否已經進入黑暗模式。

          const darkmode =  new Darkmode();
          darkmode.toggle();
          console.log(darkmode.isActivated()) // 如果已經進入黑暗模式會返回 true

          知識總結

          filter: invert() — 可以把頁面從白變黑,也可以從黑變白。 filter: hue-rotate() — 用于改變你元素的顏色,同時或多或少保持原本相同的色系。 Darkmode.js — 瞬間實現黑暗模式。

          4. 自定義列表符號

          ul,li的無序列表有默認的符號·,但是在很多情況下我們希望可以給這個符號加入自己的樣式和顏色,甚至是換成自定義的符號。默認的符號我們是無法做任何的樣式處理,而且默認的符號在CSS屬性里面只有幾個選擇可以使用,很多情況下都是無法滿足我們的設計。

          其實自定義無序列表符號不難,我們只需要使用偽類::before加content屬性就可以實現。

          在我這個例子里面我做了兩個任務列表,一個是待處理任務,一個是已完成任務,各自給了不一樣的列表符號和顏色。

          實現原理

          一、首先我們禁用了ul的默認符號樣式list-style: none

          二、在li的:before偽類上給予content內容值,待處理任務使用,已完成任務li.completed:before使用?

          三、為了展示效果更加好看我分別給了li和li .completed兩個不同的顏色

          上代碼看看是怎么實現的吧:

          HTML

          <div>
            <h2>待處理</h2>
            <ul>
              <li>待辦任務1</li>
              <li>待辦任務2</li>
              <li>待辦任務3</li>
              <li>待辦任務4</li>
              <li>待辦任務5</li>
            </ul>
          </div>
          <div>
            <h2>已完成</h2>
            <ul>
              <li class="completed">完成任務1</li>
              <li class="completed">完成任務2</li>
              <li class="completed">完成任務3</li>
            </ul>
          </div>

          CSS

          ul {
            list-style: none;
            color: #fff;
            font-size: 20px;
            border: 3px solid #000;
            padding: 1rem 2rem;
            min-height: 200px;
            margin: 15px 2rem 0 0;
            background: #323232;
            box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
            border-radius: 8px;
          }
          
          li {
            padding: 0.3rem 0;
          }
          
          li::before {
            content: " ";
            color: aqua;
          }
          
          li.completed::before {
            content: "? ";
            text-decoration: none;
            color: greenyellow;
          }
          
          li.completed {
            text-decoration: line-through;
            color: #bdbdbd;
          }

          ::before和::after偽類加content屬性可以用來做很多特殊的效果,也是當代前端排版比較常用的“魔法”。說到偽類的使用,我再給大家說一個比較常用的使用場景。

          在管理后臺或者是文章展示中,我們經??梢砸姷降摹懊姘紝Ш健币彩怯脗晤悂聿迦朊總€目錄中間的符號的。

          實現邏輯

          一、這個導航含有3個a標簽,首先給每個a標簽加入一個偽類::after,然后在content屬性插入/符號。

          二、然后使用a:first-child,這個偽類會選擇到第一個a標簽,然后使用content屬性加入?符號。

          三、因為我們第一步在每個a標簽的后面插入了/符號, 所以我們需要在最后一個a標簽清除掉。這里我們使用:last-child選擇到最后一個a標簽,然后用content: " "屬性把偽類的內容清楚掉。

          HTML

          <div class="breadcrumb">
            <a>三鉆</a>
            <a>前端</a>
            <a>教程</a>
          </div>

          CSS

          .breadcrumb {
            font-size: 1.6rem;
            color: #fff;
          }
          .breadcrumb a:first-child {
            color: #82fcfd;
          }
          .breadcrumb a:first-child::before {
            content: " ? ";
          }
          .breadcrumb a::after {
            content: " /";
            color: #ef6eae;
          }
          .breadcrumb a:last-child::after {
            content: "";
          }

          知識總結

          ::before | ::after — 偽類用于向某些選擇器添加特殊的效果。 content — CSS 屬性用于在元素的 ::before 和 ::after 偽元素中插入內容。使用content 屬性插入的內容都是匿名的可替換元素。 :first-child — CSS偽類表示在一組兄弟元素中的第一個元素。 :last-child — CSS偽類代表父元素的最后一個子元素。

          5. 圖片視差效果

          這個超級炫酷的效果在官網中非常的受歡迎,這種效果可以給用戶帶來視覺沖擊,也給我們的網站帶來了活力。普通的網頁圖片會跟隨著網頁一起滑動,但是視覺差效果圖就會固定在底部,只有圖片所在的窗口上的元素會移動。

          僅使用CSS

          對你沒有看錯,這個效果只需要用到CSS就能輕易的實現!我們只要使用一個CSS背景圖的屬性background-attachment: fixed,這個特性會把背景相對于視口固定。即使一個元素擁有滾動機制,背景也不會隨著元素的內容滾動。

          實現理論:

          一、在含有圖片的元素中加入background: url()和background-size: cover(第二個屬性適用于定義圖片為封面,可以讓圖片大小自動適應,在很大的屏幕也會顯示完整的圖片)

          二、然后附加固定背景圖的屬性background-attachment: fixed

          三、最后給這個元素加入一個高度height: 100%或者任意的高度height: 400px

          就那么簡單哦!不用懷疑,馬上上代碼,大家都可以自己去試試哦!

          HTML

          <div class="wrapper">
             <div class="parallax-img"></img>
             <p>這里填寫一堆文字就可以了,盡量多一點哦</p>
          </div>

          CSS

          .wrapper {
            height: 100wh;
          }
          .parallax-img {
            background-attachment: fixed;
            background-position: center;
            background-repeat: no-repeat;
            background-size: cover;
            height: 100%;
            background-image: url("http://ppe.oss-cn-shenzhen.aliyuncs.com/collections/182/7/thumb.jpg");
          }
          p {
            font-size: 20px;
            padding: 1.5rem 3rem;
            min-height: 1000px; // 當你的文字內容不夠,也能撐出足夠的高度來看到效果,當然如果你文字足夠多,就不需要了
          }

          如果想做到我動圖里面一樣的效果,或者想看是怎么實現的,可以查看下面總結里面的“預覽實際效果”或者看“GitHub源碼”。

          知識總結

          background-attachment: fixed — 把背景相對于視口固定。即使一個元素擁有滾動機制,背景也不會隨著元素的內容滾動。 background-size: cover — 可以讓圖片大小自動適應,在很大的屏幕也會顯示完整的圖片。


          使用CSS + JavaScript

          有些童鞋可能沒有被這個震撼到或者還是覺得不夠刺激。那我們再來一個高級例子,上面的例子在滑動的時候圖片是固定死的。如果我們加上JavaScript的助力,我們可以讓窗口的圖片緩慢的跟隨這個頁面滑動,使得效果更有動力和更有沖擊感。

          實現理論 首先講一下排版,因為我們需要在我們滑動頁面的時候使用JavaScript偏移圖片,所以我們需要給圖片一個CSS屬性讓我們可以讓圖片可以根據一個速度來往上或者往下移動。這個例子里面我們讓所有圖片包裹在一個div里面,class名為block。這個div給予相對定位屬性position: relative,這個時候我們就可以在里面加入圖片,然后讓圖片絕對定位position: absolute在這個div盒子里面。

          但是圖片是可能很大的,我們需要把圖片不超出我們定義個盒子,所以我們的div同時也給予了overflow: hidden和一個高度height: 100%。這樣圖片超出div盒子就會被隱藏。

          布局代碼如下:

          <div class="block">
            <img
              src="https://unsplash.it/1920/1920/?image=1005"
              data-speed="-1"
              class="img-parallax"
            />
            <h2>視差速度 -1</h2>
          </div>
          <div class="block">
            <img
              src="https://unsplash.it/1920/1920/?image=1067"
              data-speed="1"
              class="img-parallax"
            />
            <h2>視差速度 1</h2>
          </div>
          html, body{
            margin: 0;
            padding: 0;
            height: 100%;
            width: 100%;
            font-family: 'Amatic SC', cursive;
          }
          .block{
            width: 100%;
            height: 100%;
            position: relative;
            overflow: hidden;
            font-size: 16px;
          }
          .block h2{
            position: relative;
            display: block;
            text-align: center;
            margin: 0;
            top: 50%;
            transform: translateY(-50%);
            font-size: 10vw;
            color: white;
            font-weight: 400;
          }
          .img-parallax {
            width: 100vmax;
            z-index: -1;
            position: absolute;
            top: 0;
            left: 50%;
            transform: translate(-50%,0);
            pointer-events: none
          }

          實現這個布局,在你滑動的時候,圖片是不會移動的。因為最后一步就是加入JavaScript的輔助,讓圖片活起來。

          <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
          <script>
          // 循環獲取每一個圖片元素
          $(".img-parallax").each(function () {
            var img = $(this);
            var imgParent = $(this).parent();
            function parallaxImg() {
              var speed = img.data("speed"); // 獲取每張圖片設置了的偏移速度
              var imgY = imgParent.offset().top; // 獲取圖片盒子所在的Y位置
              var winY = $(this).scrollTop(); // 獲取當前滑動到的位置
              var winH = $(this).height(); // 獲取瀏覽器窗口高度
              var parentH = imgParent.innerHeight(); // 獲取圖片盒子的內高度
          
              // 瀏覽器窗口底部的所在位置
              var winBottom = winY + winH; 
          
              // 當前圖片是否進入瀏覽器窗口
              if (winBottom > imgY && winY < imgY + parentH) {
                // 運算圖片需要開始移動的位置
                var imgBottom = (winBottom - imgY) * speed;
                // 運算出圖片需要停止移動的位置
                var imgTop = winH + parentH;
                // 獲取從開始移動到結束移動的%(根據開始與結束像素 + 移動速度)
                var imgPercent = (imgBottom / imgTop) * 100 + (50 - speed * 50);
              }
              img.css({
                top: imgPercent + "%",
                transform: "translate(-50%, -" + imgPercent + "%)",
              });
            }
            $(document).on({
              scroll: function () {
                parallaxImg();
              },
              ready: function () {
                parallaxImg();
              },
            });
          });
          </script>

          知識總結

          position: relative — 相對定位。 position: absolute — 絕對定位。 overflow: hidden — 如果需要,內容將被剪裁以適合填充框。 不提供滾動條。

          6. 裁剪圖像的動畫

          在有CSS3之前裁剪圖片實現也是頗有難度的?,F在我們有了兩個非常方便簡單的CSS3屬性可以實現裁剪,那就是object-fit和object-position, 這兩個屬性可以讓我們改變圖片的大小,但是不影響圖片的長寬比。

          當然我們可以使用圖片處理工具或者使用JavaScript等插件來實現圖片裁剪功能。但是因為有了CSS3的屬性,我們不只可以裁剪,我們還可以用裁剪的屬性來做圖片的動態效果。

          為了讓我們的例子更加簡單,我們這里使用了<input type="checkbox">復選框元素,這樣我們就可以使用:checked的偽類來觸發啟動效果。所以在例子里面我們完全不需要JavaScript的協助。

          實現原理:

          一、首先給予圖片一個寬高height: 1080px,width: 1920px。

          二、然后用CSS選擇器,鎖定當input被選中后img標簽的樣式變化。當被選中時,給圖片設定一個新的寬高,這里我們給寬高各自500像素:width: 500px,height: 500px。

          三、然后我們加上了過渡效果和時間讓圖片改變寬高時有動畫過渡效果:transition: width 2s, height 4s;。

          四、最后加上object-fit: cover和object-position: left-top這兩個屬性來保持圖片的寬高比例,這樣就大功告成了!

          我們來看看完成的代碼:

          勾選裁剪圖片 <input type="checkbox" />
          <br />
          <img
            src="https://img-blog.csdnimg.cn/2020032122230564.png"
            alt="Random"
          />
          input {
            transform: scale(1.5); /* 只是用來放大復選框大小 */
            margin: 10px 5px;
            color: #fff;
          }
          
          img {
            width: 1920px;
            height: 1080px;
            transition: 0s;
          }
          
          /* css選擇器鎖定復選框被選中時的狀態 */
          input:checked + br + img {
            width: 500px;
            height: 500px;
            object-fit: cover;
            object-position: left-top;
            transition: width 2s, height 4s;
          }

          知識總結

          object-fit — CSS 屬性指定可替換元素的內容應該如何適應到其使用的高度和寬度確定的框。 object-position — 用來切換被替換元素的內容對象在元素框內的對齊方式。 transition — 過渡可以為一個元素在不同狀態之間切換的時候定義不同的過渡效果。

          7. 混合模式(Blend)

          如果有使用過Photoshop的同學對blend混合模式應該是非常熟悉了,我們都知道混合模式是非常強大,也是p圖時非常常用的一個功能。但是你們有沒有想象過可以在瀏覽器的CSS中直接使用呢?對我們不需要設計師給我們做圖,我們前端也可以實現混合模式了。

          在CSS中我們不只可以對background背景加入混合模式,我們可以對任何一個元素的自帶背景加入混合模式,讓你可以做出很多之前沒有想過的效果和排版。

          往一個元素加入混合模式,我們只需要使用到一個CSS屬性mix-blend-mode即可。

          簡單實現原理:

          首先我們只需要加一個h1標題標簽

          <h1>混合模式:顏色減淡</h1>

          然后我們給h1標簽加入mix-blend-mode中的顏色減弱模式color-dodge,但是要注意的是我們需要給body和html加入背景顏色background: white,要不你會發現這個效果會無效。因為h1我們沒有給顏色,會自動往上級繼承,并且混合模式是針對背景顏色的過濾,所以body和html需要有背景顏色才行。

          h1 {
             mix-blend-mode: color-dodge;
             font-family: yahei;
             font-size: 5rem;
             text-align: center;
             margin: 0; 
             padding: 20vh 200px;
             color: #D1956C;
           }
          
           html,
           body {
             margin: 0;
             background-color: white;
           }
          
           body {
          
             background-image: url(https://images.unsplash.com/photo-1505567745926-ba89000d255a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3302&q=80);
             background-repeat: no-repeat;
             background-size: cover;
             min-height: 100vh;
             overflow: hidden;
           }

          換換背景圖和h1標簽的字體顏色就可以弄出各種不同的特效了。

          知識總結

          mix-blend-mode — CSS 屬性描述了元素的內容應該與元素的直系父元素的內容和元素的背景如何混合。

          8. 瀑布流布局

          CSS Grid和Flexbox讓我們可以更簡便,更容易和更快的實現各式各樣的響應布局,并且讓我們快捷方便的在布局中實現橫向劇中和豎向劇中。但是回想一下以前是頗為困難的。

          雖然這些新出的布局方式可以讓我們解決很多以前的布局難題,但是像瀑布流布局這種,就無法用它們簡單來實現了。因為瀑布流一般來說都是寬度一致,但是高度是根據圖片自適應的。并且圖片的位置也是根據在上方圖片的位置而定的。

          其實最好實現瀑布流布局的辦法就是用CSS的列屬性套件,這套屬性大多數都是用于排版雜志中的文本列。但是用于布局瀑布流也是特別實用哦。因為以前需要實現瀑布流,就必須有JavaScript的輔助來計算圖片高度然后決定每張圖片的定位和位置,所以現在有了列屬性就可以使用純CSS實現了。

          實現原理:

          實現這個布局,首選我們需要把所有的內容先包裹在一個div元素里面,然后給這個元素column-width和column-gap屬性。

          然后,為了防止任何元素被分割到兩個列之間,將column-break-inside: avoid添加到各個元素中。

          神奇的效果就完美實現了,零JavaScript。

          我們來看看代碼:

          <div class="columns">
            <figure>
              <img src="https://source.unsplash.com/random?city" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?night" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?developer" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?building" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?water" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?coding" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?stars" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?forest" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?girls" alt="" />
            </figure>
            <figure>
              <img src="https://source.unsplash.com/random?working" alt="" />
            </figure>
          </div>
          .columns {
            column-width: 320px;
            column-gap: 15px;
            width: 90%;
            max-width: 1100px;
            margin: 50px auto;
          }
          .columns figure {
            display: inline-block;
            box-shadow: 0 1px 2px rgba(34, 25, 25, 0.4);
            column-break-inside: avoid;
            border-radius: 8px;
          }
          .columns figure img {
            width: 100%;
            height: auto;
            margin-bottom: 15px;
            border-radius: 8px;
          }

          知識總結

          column-width — CSS屬性建議一個最佳列寬。 列寬是在添加另一列之前列將成為最大寬度。 column-width — 該 CSS 屬性用來設置元素列之間的間隔 (gutter) 大小。 column-break-inside — 設置或檢索對象內部是否斷。

          總結

          我希望這8個前端小技巧和特效對大家有幫助,或多或少有吸收一點新的前端知識。這篇文章提到的內容,其實很多都是值得深挖和學習的。有一些例子我做的比較簡單,但是其實是有無限的可能性。喜歡前端的童鞋們,讓我們繼續在前端領域中一起深挖,讓我們的熱愛無限的燃燒起來吧!



          在最后我想給大家講一下我對前端的熱愛和態度。

          回想前端這幾年,發展真的是突飛猛進,從前端排版,HTML5+CSS3做H5頁面,到前端組件化,各種UI框架滿天飛。

          一開始我隨著熱潮用起了UI框架,起初覺得特別方便,來一個新的項目就直接上一個UI框架,研發速度也非常快。但是久而久之就覺得前端開發變成了處理數據,對接接口,實現交互。

          某天在閱覽國外的一些前端設計和框架的時候,我突然發現國內多數的前端開發者都不再怎么使用CSS3做出一些很好玩的布局和特效了。現在市面上的系統和頁面都是千篇一律,普遍都是用一些知名的UI框架搭建系統和APP,基本自己動手去排版已經少之又少。前端已不再是以前的前端,缺少了靈魂。

          但是我們回想一下,我們剛剛開始學習前端的時候,讓我們最有成就感,覺得前端特別有意思的那種感覺。就是那種讓我們覺得神乎奇跡,不可思議的布局,特效和交互。那種感覺自己成功實現了很優美,很炫酷的頁面和特效的感覺,讓我們越做越來勁,越做越是興奮。

          但是在某些公司,研發部都是要求快速開發,UI設計部門也是受到時間的控制和限制,所以逐步走進了UI框架的限制之中。都是圍繞這一些UI框架來設計和開發系統和應用。

          作為一名熱愛前端的開發者,我還是堅持在絕大多數的項目中,自己排版和實現頁面交互特效。然后使用UI框架作為輔助,主要是用來減輕一些小組件和常用組建的快速實現。(可以說我是比較追求完美和外貌協會的程序員 )


          作者:三鉆
          鏈接:https://juejin.im/post/5e8fc7826fb9a03c677e68d9
          來源:掘金
          著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


          主站蜘蛛池模板: 国产a久久精品一区二区三区| 国产福利酱国产一区二区| 亚洲丶国产丶欧美一区二区三区| 日产亚洲一区二区三区| 国产福利电影一区二区三区久久老子无码午夜伦不 | 韩国理伦片一区二区三区在线播放| 麻豆天美国产一区在线播放| 亚洲AV无码一区二区二三区入口| 日韩一区精品视频一区二区| 无码日韩人妻av一区免费| 精彩视频一区二区三区| 狠狠色成人一区二区三区| 精品国产乱码一区二区三区| 美女AV一区二区三区| 色老头在线一区二区三区| 怡红院AV一区二区三区| 中文字幕在线观看一区| 97se色综合一区二区二区| 日韩熟女精品一区二区三区| 久久国产视频一区| 日本在线视频一区二区三区| 97久久精品午夜一区二区 | 69久久精品无码一区二区| 国产成人一区二区三区高清| 免费av一区二区三区| 日韩av片无码一区二区不卡电影 | 狠狠色成人一区二区三区| 中文字幕乱码亚洲精品一区 | 国产精品高清一区二区三区不卡| 国产精品一区二区资源| 无码免费一区二区三区免费播放 | 中文字幕一区二区在线播放| 麻豆国产一区二区在线观看| 国产免费播放一区二区| 亚洲精品色播一区二区| 国产成人无码一区二区三区| 国产一区在线播放| 无码少妇A片一区二区三区| 国产在线一区二区三区| 欧洲精品码一区二区三区| 日产一区日产2区|