Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲国产资源,国产免费人视频在线观看免费,毛片在线视频观看

          整合營銷服務商

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

          免費咨詢熱線:

          JavaScript的變量提升

          JavaScript的變量提升

          果是第一次學習JavaScript,或許你會對此感到疑惑:在JavaScript中,變量只有全局變量和局部變量兩種,而不像C語言和Java語言,還有塊變量。

          其實,只要你知道了JavaScript的變量提升,就理解了變量的作用域。

          1、有點不可思議的變量未定義

          下面是一個包含JavaScript的完整HTML文檔:

          <!DOCTYPE html>
          <html>
          <head>
          <title>var001</title>
          <meta charset="utf-8" />
          <script>
          var theMesage="value of global";
          function showMessage(){
          alert(theMessage);
          var theMessage="value of local";
          alert(theMessage);
          }
          </script>
          </head>
          
          <body>
          <button onclick="showMessage();" >顯示信息</button>
          </body>
          </html>

          當使用瀏覽器打開該文檔后,界面展示如下:

          當點擊按鈕后,先顯示下面的警告框:

          點擊告警框的“確定”按鈕后,再顯示下面的警告框:

          讓人不可思議的是,第一次彈出的警告框,theMessage變量的值竟然是undefined!

          2、變量未定義的原因

          初一看JavaScript代碼,我們會認為第一次警告框顯示的信息應該是“value of global”,因為theMessage變量的值就是“value of global”。

          其實在瀏覽器內部,showMessage函數中的語句:

          var theMessage="value of local";

          經歷了兩次變換,第一次變換,將這條語句變為兩條語句:

          var theMessage;
          theMessage="value of local";

          這兩條語句,一條是變量聲明語句,用于生成變量;第二條是賦值語句,用于為變量賦值。

          第二次變換,就是將變量聲明語句上浮到函數體的頂部,因此,最終執行之前的showMessage函數,是這個樣子:

          function showMessage(){
          var theMessage;
          alert(theMessage);
          theMessage="value of local";
          alert(theMessage);
          }

          看到showMessage函數的最終形式,你會立即明白:theMessae變量沒有被賦值就使用了,當然是undefined。原來如此!

          3、語句塊內定義的變量,外部竟然可以使用

          下面也是一個包含JavaScript的完整HTML文檔:

          <!DOCTYPE html>
          <html>
          <head>
          <title>var002</title>
          <meta charset="utf-8" />
          <script>
          function showMessage(){
          var theMessage="";
          for (var i=1; i<5; i++)
          {
          theMessage=theMessage + " " + i;
          }
          theMessage=theMessage + " " + i*100;
          alert(theMessage);
          }
          </script>
          </head>
          
          <body>
          <button onclick="showMessage();" >顯示信息</button>
          </body>
          </html>

          看到這樣的HTML文件,這樣的JavaScript函數,有經驗的C程序員或者Java程序員,會立即喊出來:“程序錯了,在for塊之外,i不能被使用!”,實際上,HTML文件被瀏覽器打開后,展示如下:

          點擊“顯示信息”按鈕,出現下面的警告框:

          程序竟然正常運行了!

          4、程序正常運行的原因

          上面的程序正常運行的原因,也是變量提升,下面的語句:

          var i=1;

          也是經過兩次變換,最終,showMessage函數在運行前,被變換成這樣了:

          function showMessage(){
          var theMessage;
          var i;
          theMessage="";
          for (i=1; i<5; i++)
          {
          theMessage=theMessage + " " + i;
          }
          theMessage=theMessage + " " + i*100;
          alert(theMessage);
          }

          這樣的代碼,肯定可以正常運行了。

          5、變量提升知識點的總結

          在JavaScript中,上面的變換方式,被稱為變量提升。其實,變量提升,就是變量聲明上浮,一直上浮到全局或者函數體的頂部。

          在前面:

          本文將和各位老鐵一起探索如何使用CSS變量來降低復雜布局和交互的代碼編寫難度,并使其更易于維護。這里即將分享兩篇該系列的文章,本篇是分享css變量的探索應用的各種用例。

          進入文章前,我們先看下圖,一張網站常用的響應式信息圖表布局圖,當然實現的方式很多,如果我告訴您一個CSS聲明會在以下圖像中對寬屏情況(左測)和第二個(右測)之間產生差異,用一個CSS聲明實現在寬屏幕的情況下對奇數項和偶數項進行區分,從而來實現下面效果,你會不會覺得有點驚喜?

          或者僅僅一個CSS聲明就能區別下面的壓縮和擴展的情況?

          有點意思吧,接下來,我們就一起探索CSS變量在復雜布局和交互的一些小運用。關于CSS變量是什么以及如何開始使用它們的文章已經很多了,所以我們不會在這里深入討論。我們將直接深入了解CSS變量為什么對實現這些情況和其他情況有用,然后我們將進一步詳細解釋如何實現各種情況。我們將從頭編寫一個實際示例,一步一步地編寫,最后,您將通過使用相同技術的更多演示獲得一些引人注目的東西。所以讓我們開始吧!(ps:本文樣式都是scss編寫)

          為什么CSS變量很有用

          對我而言,CSS變量的最大優點是它們以邏輯,數學和輕松的方式為事物的樣式打開了大門。看下面這個陰陽圖,其實是使用loader元素的兩個偽元素創建兩個半部分

          旋轉?符號,兩個半的大小逐漸增大和減小。我們使用相同的 background , border-color , transform-origin 和 animation-delay 值兩半。這些值都取決于 --i 最初設置為 0 兩半(偽元素)的開關變量,但隨后我們將其更改 1 為后半部分( :after 偽元素),從而動態修改所有這些屬性的計算值。

          如果沒有CSS變量,我們將不得不再次在:after偽元素上設置所有這些屬性(border-color、transform-origin、background、anima -delay),并可能出現一些錯誤,甚至忘記設置其中一些屬性。

          一般情況下切換的工作原理

          一、在零和非零值之間切換

          在陰陽加載器的特定情況下,我們在兩半(偽元素)之間改變的所有屬性對于開關的一個狀態變為零值而對于另一個狀態變為非零值。

          如果我們希望當開關關閉( --i: 0 )時我們的值為零,而當開關打開()時我們的值為非零 --i:1,那么我們將它與開關值( var(--i) )相乘。這樣,如果我們的非零值應該是 30deg ,我們有一個角度值,我們有:

          • 當開關 關閉
          • ( --i: 0 )時, calc(var(--i)*30deg) 計算到 0*30deg=0deg
          • 當開關 打開
          • ( --i: 1 )時, calc(var(--i)*30deg) 計算到 1*30deg=30deg

          您可以看到以下所示的概念:

          在零和非零值之間切換(現場演示,由于 calc() 不處理角度值而沒有Edge支持)

          對于裝載機的特定情況下,我們使用HSL值 border-color 和 background-color 。HSL代表色調,飽和度,亮度,并且可以借助于雙錐體(其由粘合在一起的基部的兩個錐體組成)在視覺上最佳地表示。

          色調圍繞著雙色調, 0° 相當于 360° 在兩種情況下都給我們一個紅色

          飽和度從 0% 雙錐的垂直軸到 100% 雙錐面上。當飽和度 0% (在雙錐的垂直軸上)時,色調不再重要;對于同一水平面上的所有色調,我們得到完全相同的灰色。“相同水平面”是指具有相同的亮度,其沿垂直軸雙錐增加,從去 0% 在黑色雙圓錐體的頂點,以 100% 在白色雙圓錐體的頂點。當亮度是 0% 或者 100% ,色調和飽和度都不再重要時 - 我們總是得到黑色亮度值 0% 和白色亮度值 100% 。因為我們只需要黑色和白色我們的?符號,色調和飽和度是不相關的,所以我們清除它們,然后之間進行切換黑色,并白色通過切換之間的亮度 0% 和 100% 。

          .yin-yang {
           &:before, &:after {
           --i: 0;
           /* lightness of border-color when 
           * --i: 0 is (1 - 0)*100%=1*100%=100% (white)
           * --i: 1 is (1 - 1)*100%=0*100%=0% (black) */
           border: solid $d/6 hsl(0, 0%, calc((1 - var(--i))*100%));
           /* x coordinate of transform-origin when 
           * --i: 0 is 0*100%=0% (left) 
           * --i: 1 is 1*100%=100% (right) */
           transform-origin: calc(var(--i)*100%) 50%;
           /* lightness of background-color when 
           * --i: 0 is 0*100%=0% (black) 
           * --i: 1 is 1*100%=100% (white) */
           background: hsl(0, 0%, calc(var(--i)*100%));
           /* animation-delay when
           * --i: 0 is 0*-$t=0s 
           * --i: 1 is 1*-$t=-$t */
           animation: s $t ease-in-out calc(var(--i)*#{-$t}) infinite alternate;
           }
           &:after { --i: 1 }
          }
          
          

          但是,如果我們想要在開關關閉( --i: 0 )時具有非零值而在開關打開時具有另一個不同的非零值( --i: 1 )呢?

          一、在兩個非零值之間切換

          假設我們希望一個元素在開關關閉時具有灰色 background ( #ccc ),在開關打開時 --i: 0

          具有橙色 background ( #f90 )( --i: 1 )。我們要做的第一件事是從十六進制切換到更易于管理的格式,如 rgb() 或 hsl() 。我們可以通過使用諸如Lea Verou的CSS Colors之類的工具或通過DevTools手動完成此操作。如果我們 background 在元素上有一個集合,我們可以通過 Shift 按住鍵來循環瀏覽格式,同時單擊DevTools中值前面的正方形(或圓圈)。這適用于Chrome和Firefox,但它似乎不適用于Edge。

          更妙的是,如果我們使用無禮的話,我們可以提取成分 red() / green() / blue()hue() /

          saturation() / lightness() 函數。雖然 rgb() 可能是更為人所知的格式,但我更傾向于 hsl()因為我發現它更直觀,而且通過查看代碼,我更容易了解視覺效果。因此,我們使用以下函數提取

          hsl() 兩個值的等價物的三個組成部分( $c0: #ccc 當開關關閉 $c1: #f90 時和開關打開時):

          $c0: #ccc;
          $c1: #f90;
          $h0: round(hue($c0)/1deg);
          $s0: round(saturation($c0));
          $l0: round(lightness($c0));
          $h1: round(hue($c1)/1deg);
          $s1: round(saturation($c1));
          $l1: round(lightness($c1))
          
          

          請注意,我們已經四舍五入的結果hue(),saturation()并lightness()作為他們可能返回大量的小數,我們要保持我們生成的代碼干凈。我們還將hue()函數的結果除以1deg,因為在這種情況下返回值是度值,而Edge僅支持CSS hsl()函數內的無單位值。通常,在使用Sass時,我們可以使用度數值,而不僅僅是hsl()函數內部hue的單位值,因為Sass將其視為Sass hsl()函數,它被編譯為hsl()具有無單位色調的CSS 函數。但是在這里,我們內部有一個動態CSS變量,因此Sass將此函數視為CSShsl() 沒有編譯成其他任何東西的函數,因此,如果hue有一個單元,則不會從生成的CSS中刪除它。

          現在我們有:

          • 如果開關關閉(--i: 0),我們background是 hsl($h0, $s0, $l0)
          • 如果開關打開(--i: 1),我們background是 hsl($h1, $s1, $l1)

          我們可以將我們的兩個背景寫成:

          • 如果開關關閉( --i: 0 ), hsl(1*$h0 + 0*$h1, 1*$s0 + 0*$s1, 1*$l0 + 1*$l1)
          • 如果開關打開( --i: 1 ), hsl(0*$h0 + 1*$h1, 0*$s0 + 1*$s1, 0*$l0 + 1*$l1)

          在這里,我們記--j的互補值--i(當--i是0,--j是1,當--i是1,--j是0)。

          上述公式適用于在任意兩個HSL值之間切換。但是,在這種特殊情況下,我們可以簡化它,因為當開關關閉時我們有一個純灰色(--i: 0)。

          考慮到RGB模型,純灰度值具有相等的紅色,綠色和藍色值。 當考慮HSL模型時,色調是無關緊要的(我們的灰色看起來對于所有色調都是相同的),飽和度總是0%只有亮度很重要,決定了我們的灰色是多么亮或暗。 在這種情況下,我們可以始終保持非灰色值的色調(我們對“on”情況所具有的色調$h1)。

          由于任何灰度值(我們對“關閉”情況所具有的)的飽和度 $s0始終是0%,將其乘以0或者1總是給出我們0%。因此,考慮到var(--j)*#{$s0}我們的公式中的術語總是如此0%,我們可以放棄它,我們的飽和公式減少到“on”情況$s1和switch變量飽和之間的乘積--i。 這使得輕盈成為我們仍然需要應用完整配方的唯一組成部分

          --j: calc(1 - var(--i));
          background: hsl($h1, 
           calc(var(--i)*#{$s1}), 
           calc(var(--j)*#{$l0} + var(--i)*#{d1l}))
          
          

          以上內容可在此演示中進行測試。 類似地,假設我們想要font-size一些文本2rem在我們的開關關閉(--i: 0)和10vw開關打開(--i: 1)時。應用相同的方法,我們有:

          font-size: calc((1 - var(--i))*2rem + var(--i)*10vw)
          
          

          觸發切換

          一、基于元素的切換

          這意味著某些元件和其他元件的開關關閉。例如,這可以通過奇偶校驗來確定。假設我們希望所有偶數元素都旋轉并且具有橙色background而不是初始灰色元素

          .box {
           --i: 0;
           --j: calc(1 - var(--i));
           transform: rotate(calc(var(--i)*30deg));
           background: hsl($h1, 
           calc(var(--i)*#{$s1}), 
           calc(var(--j)*#{$l0} + var(--i)*#{$l1}));
           
           &:nth-child(2n) { --i: 1 }
          }
          
          

          由項目奇偶校驗觸發的切換(實時演示,由于calc()不適用于角度值而在Edge中不能完全正常工作)

          在奇偶校驗的情況下,我們為每隔一個項目(:nth-child(2n))打開開關,但我們也可以為前七個項目(:nth-child(7n)),前兩個項目(:nth-child(-n + 2)),為除了第一個和最后兩個(:nth-child(n + 3):nth-last-child(n + 3))之外的所有項目打開它。我們也可以僅針對標題或僅針對具有特定屬性的元素進行翻轉。

          二、狀態切換

          這意味著當元素本身(或父元素或其先前的兄弟元素之一)處于一種狀態時關閉開關,而當它是另一種狀態時關閉。在上一節的交互式示例中,在檢查或取消選中元素之前的復選框時,交換機被翻轉。我們還可以使用白色鏈接,在聚焦或懸停時可以放大并變成橙色:

          $c: #f90;
          $h: round(hue($c)/1deg);
          $s: round(saturation($c));
          $l: round(lightness($c));
          a {
           --i: 0;
           transform: scale(calc(1 + var(--i)*.25));
           color: hsl($h, $s, calc(var(--i)*#{$l} + (1 - var(--i))*100%)); 
           &:focus, &:hover { --i: 1 }
          }
          
          

          因為white任何hsl()具有亮度100%(色調和飽和度都無關緊要)的值,我們可以通過始終保持:focus/ :hover狀態的色調和飽和度并且僅改變亮度來簡化事物。

          由狀態變化觸發的切換(現場演示,由于功能calc()內部不支持的值,Edge中功能不全scale())

          三、基于媒體查詢的切換

          另一種可能性是切換由媒體查詢觸發,例如,當方向改變時或從一個視口范圍轉到另一個視口范圍時。 比方說,我們有white一個標題font-size的1rem最高320px,但隨后變為橙色($c)和font-size變5vw,并開始與視縮放width。

          h5 {
           --i: 0;
           color: hsl($h, $s, calc(var(--i)*#{$l} + (1 - var(--i))*100%));
           font-size: calc(var(--i)*5vw + (1 - var(--i))*1rem);
           @media (min-width: 320px) { --i: 1 }
          }
          
          

          從頭開始編寫一個更復雜的例子-搜索

          我們在這里剖析的例子是本文開頭展示的擴展搜索

          ps:從可用性的角度來看,在網站上設置這樣的搜索框可能不是最好的主意,因為人們通常期望搜索框后面的按鈕觸發搜索,而不是關閉搜索欄,但它仍然是一個有趣的編碼練習,這就是為什么我選擇在這里剖析它。

          首先,我的想法是僅使用表單元素來完成它。

          因此,HTML結構如下所示:

          <input id='search-btn' type='checkbox'/>
          <label for='search-btn'>Show search bar</label>
          <input id='search-bar' type='text' placeholder='Search...'/>
          
          

          我們在這里做的最初是隱藏文本input,然后在選中復選框之前將其顯示出來 - 讓我們深入了解它是如何工作的! 首先,我們使用基本重置并flex在我們input和label元素的容器上設置布局。在我們的例子中,這個容器是body,但也可能是另一個元素。我們也絕對定位復選框并將其移出視線(視口外)。

          *, :before, :after {
           box-sizing: border-box;
           margin: 0;
           padding: 0;
           font: inherit
          }
          html { overflow-x: hidden }
          body {
           display: flex;
           align-items: center;
           justify-content: center;
           margin: 0 auto;
           min-width: 400px;
           min-height: 100vh;
           background: #252525
          }
          [id='search-btn'] {
           position: absolute;
           left: -100vh
          }
          
          

          我們把復選框label變成一個大的綠色圓形按鈕,并使用一個大的負數值移動它的文本內容的視線text-indent和overflow: hidden。

          $btn-d: 5em; /* 同上 */[for='search-btn'] {
           overflow: hidden;
           width: $btn-d;
           height: $btn-d;
           border-radius: 50%;
           box-shadow: 0 0 1.5em rgba(#000, .4);
           background: #d9eb52;
           text-indent: -100vw;
           cursor: pointer;
          }
          
          

          接下來,我們通過以下方式修改實際搜索欄:

          • 給它明確的維度
          • 提供 background 正常狀態
          • background 為其聚焦狀態定義不同的光暈
          • 使用 border-radius 相當于其一半的左側角落 height
          • 清理占位符一點
          $btn-d: 5em;
          $bar-w: 4*$btn-d;
          $bar-h: .65*$btn-d;
          $bar-r: .5*$bar-h;
          $bar-c: #ffeacc;/* 同上 */
          [id='search-bar'] {
           border: none;
           padding: 0 1em;
           width: $bar-w;
           height: $bar-h;
           border-radius: $bar-r 0 0 $bar-r;
           background: #3f324d;
           color: #fff;
           font: 1em century gothic, verdana, arial, sans-serif;
           &::placeholder {
           opacity: .5;
           color: inherit;
           font-size: .875em;
           letter-spacing: 1px;
           text-shadow: 0 0 1px, 0 0 2px
           }	
           &:focus {
           outline: none;
           box-shadow: 0 0 1.5em $bar-c, 0 1.25em 1.5em rgba(#000, .2);
           background: $bar-c;
           color: #000;
           }
          }
          復制代碼
          

          此時,搜索欄的右邊緣與按鈕的左邊緣重合。但是,我們想要一些重疊 - 假設重疊使得搜索欄的右邊緣與按鈕的垂直中線重合。鑒于我們align-items: center在容器上有一個flexbox布局(body在我們的例子中),由我們的兩個項目組成的組件(條和按鈕)保持水平中間對齊,即使我們設置margin一個或另一個或在這兩個項目之間。(在最左邊的項目的左側或最右邊的項目的右側是一個不同的故事,但我們現在不會進入那個。)

          這是.5*$btn-d半個按鈕直徑的重疊,相當于按鈕的半徑。我們margin-right在欄上將其設為負數。我們還調整padding條形圖的右側,以便我們補償重疊:

          $btn-d: 5em;
          $btn-r: .5*$btn-d;
          /* 同上 */
          [id='search-bar'] {
           /* 同上 */
           margin-right: -$btn-r;
           padding: 0 calc(#{$btn-r} + 1em) 0 1em;
          }
          
          

          除了條形按照DOM順序中的按鈕,所以它放在它的頂部,當我們真正想要按鈕在頂部。

          幸運的是,這有一個簡單的解決方案(至少現在 - 以后還不夠,但讓我們一次處理一個問題)。

          [for='search-btn'] {
           /* 同上 */
           position: relative;
          }
          

          在這種狀態下,條形和按鈕組件的總寬度是條形寬度$bar-w加上按鈕的半徑$btn-r(按鈕直徑的一半$btn-d),因為按鈕的一半重疊。在折疊狀態下,組件的總寬度就是按鈕直徑$btn-d。

          由于我們希望在從展開狀態到折疊狀態時保持相同的中心軸,我們需要將按鈕向左移動擴展狀態(.5*($bar-w + $btn-r))減去按鈕半徑($btn-r)的組件寬度的一半。 我們稱之為這種轉變$x,我們在按鈕上使用減號(因為我們將按鈕向左移動,左邊是x軸的負方向)。由于我們希望條形圖折疊到按鈕中,我們$x在它上面設置相同的偏移,但是在正方向上(因為我們將條形圖移動到右邊的 x軸)。 當未選中復選框時,我們處于折疊狀態,而當未選中復選框時,我們處于展開狀態。這意味著transform當沒有選中復選框時,我們的欄和按鈕會被CSS移動,并且我們當前將它們置于其中(沒有transform)。 為了做到這一點,我們--i在復選框后面的元素上設置了一個變量- 按鈕(使用label復選框創建)和搜索欄。此變量0處于折疊狀態(當兩個元素都移位且未選中復選框時)并1處于展開狀態(當我們的條和按鈕位于它們當前占據的位置時,沒有移位,并且復選框被選中)

          $x: .5*($bar-w + $btn-r) - $btn-r;
          [id='search-btn'] {
           position: absolute;
           left: -100vw;	
           ~ * {
           --i: 0;
           --j: calc(1 - var(--i)) /* 1 when --i is 0, 0 when --i is 1 */
           }
           &:checked ~ * { --i: 1 }
          }
          [for='search-btn'] {
           /*同之前 */
           transform: translate(calc(var(--j)*#{-$x}));
          }
          [id='search-bar'] {
           /*同之前 */
           transform: translate(calc(var(--j)*#{$x}));
          }
          
          

          我們現在有互動的東西!

          單擊該按鈕可切換復選框狀態(因為該按鈕已使用 label 復選框創建)。

          除了現在按鈕有點難以點擊,因為它再次位于文本輸入下(因為我們在條上設置了 transform.

          并建立了堆疊上下文)。修復非常簡單 - 我們需要 z-index 在按鈕上添加一個按鈕,然后將其移動到條形圖上方。

          但是我們還有另一個更大的問題:我們可以看到右側按鈕下方的欄桿。為了解決這個問題,我們在欄上設置clip-path了一個inset()值。這指定了一個剪切矩形,借助于元素頂部,右側,底部和左側邊緣的距離border-box。剪切矩形之外的所有內容都會被剪切掉,只顯示內部的內容

          在上圖中,每個距離都從邊框的邊緣向內移動。在這種情況下,他們是積極的。但它們也可以向外移動,在這種情況下它們是負的,并且剪切矩形的相應邊緣在元素之外border-box。 起初,您可能認為我們沒有理由這樣做,但在我們的特定情況下,我們會這樣做! 我們希望從top(dt),bottom(db)和left(dl)的距離是負的,并且足夠大以包含在該狀態中box-shadow的元素外部延伸的border-box距離,:focus因為我們不希望它被剪切掉。所以解決方案是創建一個剪切矩形,邊緣在元素之外border-box在這三個方向。 與右邊的距離(dr)是折疊情況下的整個條寬$bar-w減去按鈕半徑$btn-r(未選中復選框--i: 0),并且0在展開的情況下(選中復選框--i: 1)。

          $out-d: -3em;
          [id='search-bar'] {
           /* 同之前 */
           clip-path: inset($out-d calc(var(--j)*#{$bar-w - $btn-r}) $out-d $out-d);
          }
          
          

          我們現在有一個搜索欄和按鈕組件,在單擊按鈕時會展開和折疊。

          由于我們不希望兩個便之間發生突然變化,我們使用 transition :

          [id='search-btn'] {
           /* 同之前 */
           ~ * {
           /* same as before */
           transition: .65s;
           }
          }
          
          

          我們還希望我們的按鈕background在折疊的情況下為綠色(未選中復選框--i: 0),在展開的情況下為粉紅色(選中復選框--i: 1)。為此,我們使用與以前相同的技術:

          [for='search-btn'] {
           /* 同之前 */
           $c0: #d9eb52; // green for collapsed state
           $c1: #dd1d6a; // pink for expanded state
           $h0: round(hue($c0)/1deg);
           $s0: round(saturation($c0));
           $l0: round(lightness($c0));
           $h1: round(hue($c1)/1deg);
           $s1: round(saturation($c1));
           $l1: round(lightness($c1));
           background: hsl(calc(var(--j)*#{$h0} + var(--i)*#{$h1}), 
           calc(var(--j)*#{$s0} + var(--i)*#{$s1}), 
           calc(var(--j)*#{$l0} + var(--i)*#{$l1}));
          }
          
          

          看看效果

          我們仍然需要做的是創建一個圖標,該圖標在折疊狀態的放大鏡和展開狀態的“x”之間變形,以指示關閉動作。我們使用:before和:after偽元素執行此操作。我們首先確定放大鏡的直徑以及圖標線寬度所代表的直徑。

          $ico-d: .5*$bar-h;
          $ico-f: .125;
          $ico-w: $ico-f*$ico-d;
          
          

          我們絕對將偽元素放在按鈕中間,并考慮其尺寸。然后我們把它們變成inherit父母的transition。我們給:beforea background,因為這將是我們的放大鏡的把手,使它成為:after圓形border-radius并給它一個插圖box-shadow。

          [for='search-btn'] {
           /* 同之前 */	
           &:before, &:after {
           position: absolute;
           top: 50%; left: 50%;
           margin: -.5*$ico-d;
           width: $ico-d;
           height: $ico-d;
           transition: inherit;
           content: ''
           }
          	
           &:before {
           margin-top: -.4*$ico-w;
           height: $ico-w;
           background: currentColor
           }
           &:after {
           border-radius: 50%;
           box-shadow: 0 0 0 $ico-w currentColor
           } 
          }
          
          

          我們現在可以在按鈕上看到放大鏡組件,為了使我們的圖標看起來更像放大鏡,我們的translate兩個組件都向外放大了放大鏡直徑的四分之一。這意味著所述手柄平移向右,在正方向X通過軸.25*$ico-d與所述主要部分的左側,在負方向X以相同的軸線.25*$ico-d。 我們還scale手柄(該:before偽元素)水平至其一半width相對于其右邊緣(這意味著一個transform-origin的100%沿X軸)。 我們只希望在折疊狀態下發生這種情況(復選框未選中,--i是0,因此--j是1),因此我們將轉換量乘以--j并用于--j調整比例因子:

          [for='search-btn'] {
           /* 同之前 */
           &:before {
           /* 同之前 */
           height: $ico-w;
           transform: 
           translate(calc(var(--j)*#{.25*$ico-d})) 
           scalex(calc(1 - var(--j)*.5))
           }
           &:after {
           /* same as before */
           transform: translate(calc(var(--j)*#{-.25*$ico-d}))
           } 
          }
          
          

          我們現在處于折疊狀態的放大鏡圖標:

          由于我們希望旋轉兩個圖標組件45deg,我們在按鈕本身上添加此旋轉:

          [for='search-btn'] {
           /* 同之前 */
           transform: translate(calc(var(--j)*#{-$x})) rotate(45deg);
          }
          
          

          這仍然會離開擴展狀態,我們需要將圓形:after偽元素轉換為一條線。我們通過縮放它順著這樣做X軸,將其border-radius從50%到0%。我們使用的縮放系數是$ico-w我們想要獲得的線寬和$ico-d它在折疊狀態下形成的圓的直徑之間的比率。我們稱這個比例$ico-f。 因為我們只希望做這在擴展狀態下,當復選框被選中,并--i是1,我們使這兩個比例因子和border-radius依賴于--i和--j:

          $ico-d: .5*$bar-h;
          $ico-f: .125;
          $ico-w: $ico-f*$ico-d;
          [for='search-btn'] {
           /* 同之前 */	
           &:after{
           /* 同之前 */
           border-radius: calc(var(--j)*50%);
           transform: 
           translate(calc(var(--j)*#{-.25*$ico-d})) 
           scalex(calc(1 - var(--j)*.5))
           }
          }
          
          

          嗯,差不多,但并不完全。縮放也縮水了插圖box-shadow沿X軸,所以我們進行了修復與第二插圖影子,我們(當復選框被選中,并在擴展狀態下只能得到--i是1),因此,它的傳播和α取決于--i:

          $ico-d: .5*$bar-h;
          $ico-f: .125;
          $ico-w: $ico-f*$ico-d;
          [for='search-btn'] {
           /* 同之前 */
           --hsl: 0, 0%, 0%;
           color: HSL(var(--hsl));	
           &:after{
           /* 同之前 */
           box-shadow: 
           inset 0 0 0 $ico-w currentcolor, 
           /* collapsed: not checked, --i is 0, --j is 1
           * spread radius is 0*.5*$ico-d=0
           * alpha is 0
           * expanded: checked, --i is 1, --j is 0
           * spread radius is 1*.5*$ico-d=.5*$ico-d
           * alpha is 1 */
           inset 0 0 0 calc(var(--i)*#{.5*$ico-d}) HSLA(var(--hsl), var(--i))
           }
          }
          
          

          這給了我們最終的結果! 【本例完整源碼】

          實用案例

          以下是一些使用相同技術的演示。我們不會從頭開始構建這些 - 我們只會介紹它們背后的基本思想

          一、響應橫條

          在這種情況下,我們的實際元素是前面較小的矩形,而后面的數字正方形和較大的矩形分別使用:before和:after偽元素創建。 數字方塊的背景是單獨的,并使用--slist對于每個項目不同的停止列表變量進行設置。

          <p style='--slist: #51a9ad, #438c92'><!-- 1st paragraph text --></p>
          <p style='--slist: #ebb134, #c2912a'><!-- 2nd paragraph text --></p>
          <p style='--slist: #db4453, #a8343f'><!-- 3rd paragraph text --></p>
          <p style='--slist: #7eb138, #6d982d'><!-- 4th paragraph text --></p>
          
          

          影響橫幅樣式的因素是平價,以及我們是處于廣泛,正常還是狹窄的情況。這些給我們的開關變量

          html {
           --narr: 0;
           --comp: calc(1 - var(--narr));
           --wide: 1;	
           @media (max-width: 36em) { --wide: 0 }
           @media (max-width: 20em) { --narr: 1 }
          }
          p {
           --parity: 0; 
           &:nth-child(2n) { --parity: 1 }
          }
          
          

          數字方塊絕對定位,它們的位置取決于奇偶校驗。如果--parity開關關閉(0),則它們在左側。如果它在(1)上,那么它們就在右邊。 一個值left: 0%沿著其父元素的左邊緣與數字方塊的左邊緣left: 100%對齊,而一個值沿著父元素的右邊緣對齊其左邊緣。 為了使數字方塊的右邊緣與其父邊緣的右邊緣對齊,我們需要從前一個100%值中減去自己的寬度。(請記住,%偏移量的值是相對于父級的尺寸。)

          left: calc(var(--parity)*(100% - #{$num-d}))
          
          

          ... $num-d編號方塊的大小在哪里。 在寬屏幕的情況下,我們還向外推送編號1em- 這意味著減去1em我們迄今為止對于奇數項目(--parity關閉開關)1em的偏移量,并添加到目前為止偶數項目的偏移量(--parity開啟時) )。 現在問題是......我們如何切換標志?最簡單的方法是使用的權力-1。遺憾的是,我們在CSS中沒有冪函數(或冪函數運算符),即使它在這種情況下非常有用:

          pow(-1, var(--parity))復制代碼
          

          這意味著我們必須使它與我們所擁有的(加法,減法,乘法和除法)一起工作,這導致了一個奇怪的小公式......但是,嘿,它有效!

          --sign: calc(1 - 2*var(--parity))
          
          left: calc(var(--parity)*(100% - #{$num-d}) - var(--wide)*var(--sign)*1em)
          
          

          我們還width使用這些變量來控制段落,并且max-width我們希望它具有上限并且僅在窄case(--narr: 1)中水平地完全覆蓋其父級:

          width: calc(var(--comp)*80% + var(--narr)*100%);
          max-width: 35em;
          
          

          這font-size也取決于我們是否處于狹窄的情況(--narr: 1)或不是(--narr: 0):

          calc(.5rem + var(--comp)*.5rem + var(--narr)*2vw)
          
          

          ......對于:after偽元素(后面較大的矩形)的水平偏移也是如此,因為它們0在窄情況(--narr: 1)中,而非零偏移,$off-x否則(--narr: 0)

          right: calc(var(--comp)*#{$off-x}); 
          left: calc(var(--comp)*#{$off-x});
          
          

          二、懸停并注重效果

          這個效果是通過一個鏈接元素和它的兩個偽元素在對角:hover和:focus狀態上對角滑動創建的。鏈接的尺寸是固定的,其偽元素也是固定的,設置為它們的父對角線$btn-d(在寬度和高度形成的直角三角形中斜邊計算)水平和父height垂直。

          該:before定位使得它的左下角恰逢其父,而:after被定位為使得其右上角與其父一致。由于兩者都應與height其父級相同,因此通過設置top: 0和解決垂直位置bottom: 0。水平放置的處理方式與前一個示例完全相同,使用--i切換變量來更改兩個偽元素之間的值,并使用--j其互補(calc(1 - var(--i))):

          left: calc(var(--j)*(100% - #{$btn-d}))
          
          

          我們設定transform-origin的:before到它的左下角(0% 100%)和:after其右上角的(100% 0%),再次,與交換機的幫助--i和補充--j

          transform-origin: calc(var(--j)*100%) calc(var(--i)*100%)
          
          

          我們將兩個偽元素旋轉到對角線和水平線之間的角度 $btn-a(也是由高度和寬度形成的三角形計算出來的,作為兩者之間比率的反正切)。通過這種旋轉,水平邊緣沿著對角線相交。 然后我們按照自己的寬度向外移動它們。這意味著我們將為兩者中的每一個使用不同的符號,同樣取決于在:before和之間改變值的switch變量,:after就像前面的橫幅示例一樣:

          transform: rotate($btn-a) translate(calc((1 - 2*var(--i))*100%))
          
          

          在:hover和:focus,這個切換必須回去0。這意味著我們通過互補乘以上面的平移量--q的開關變量--p這是0在正常狀態下和1在:hover或:focus狀態:

          transform: rotate($btn-a) translate(calc(var(--q)*(1 - 2*var(--i))*100%))
          
          

          為了使偽元素在鼠標移出或失焦時以相反的方式滑出(不回溯它們進入的方式),我們將switch變量設置--i為--pfor :before的值,并將值設置--q為for :after,反轉轉換的符號,確保只轉換transform屬性

          三、響應信息

          在這種情況下,我們為每個項目(article元素)都有一個三行,兩列網格,第三行在寬屏幕場景中折疊,第二列在窄屏幕場景中折疊。在寬屏幕場景中,列的寬度取決于奇偶校驗。在窄屏場景中,第一列跨越元素的整個內容框,第二列具有寬度0。我們在列之間也存在差距,但僅限于寬屏場景。

          $col-1-wide: calc(var(--q)*#{$col-a-wide} + var(--p)*#{$col-b-wide});
          $col-2-wide: calc(var(--q)*#{$col-b-wide} + var(--p)*#{$col-a-wide});
          $row-1: calc(var(--i)*#{$row-1-wide} + var(--j)*#{$row-1-norm});
          $row-2: calc(var(--i)*#{$row-2-wide} + var(--j)*#{$row-2-norm});
          $row-3: minmax(0, auto);
          $col-1: calc(var(--i)*#{$col-1-wide} + var(--j)*#{$col-1-norm});
          $col-2: calc(var(--i)*#{$col-2-wide});
          $art-g: calc(var(--i)*#{$art-g-wide});
          html {
           --i: var(--wide, 1); 
           --j: calc(1 - var(--i));
           @media (max-width: $art-w-wide + 2rem) { --wide: 0 }
          }
          article {
           --p: var(--parity, 0);
           --q: calc(1 - var(--p));
           --s: calc(1 - 2*var(--p));
           display: grid;
           grid-template: #{$row-1} #{$row-2} #{$row-3}/ #{$col-1} #{$col-2};
           grid-gap: 0 $art-g;
           grid-auto-flow: column dense;
           &:nth-child(2n) { --parity: 1 }
          }
          
          

          既然我們已經設置了grid-auto-flow: column dense,我們可以在寬屏幕情況下只設置第一級標題來覆蓋整個列(第二個用于奇數項,第一個用于偶數項),并讓第二個級別標題和段落文本填寫第一個可用單元格。

          grid-column: calc(1 + var(--i)*var(--q));
          grid-row: 1/ span calc(1 + 2*var(--i));
          
          

          對于每個項目,一些其他屬性取決于我們是否處于寬屏幕方案中。 在寬屏幕情況下,垂直margin,垂直和水平padding值,box-shadow偏移和模糊都更大:

          $art-mv: calc(var(--i)*#{$art-mv-wide} + var(--j)*#{$art-mv-norm});
          $art-pv: calc(var(--i)*#{$art-pv-wide} + var(--j)*#{$art-p-norm});
          $art-ph: calc(var(--i)*#{$art-ph-wide} + var(--j)*#{$art-p-norm});
          $art-sh: calc(var(--i)*#{$art-sh-wide} + var(--j)*#{$art-sh-norm});
          article {
           margin: $art-mv auto;
           padding: $art-pv $art-ph;
           box-shadow: $art-sh $art-sh calc(3*#{$art-sh}) rgba(#000, .5);
          }
          
          

          我們有一個非零border-width和border-radius寬屏幕的情況

          $art-b: calc(var(--i)*#{$art-b-wide});
          $art-r: calc(var(--i)*#{$art-r-wide});
          article {
           border: solid $art-b transparent;
           border-radius: $art-r;
          }
          
          

          在寬屏幕場景中,我們限制項目width,但100%不管怎樣。

          $art-w: calc(var(--i)*#{$art-w-wide} + var(--j)*#{$art-w-norm});
          article {
           width: $art-w;
          }
          
          

          padding-box 漸變的方向也隨奇偶校驗而變化:

          background: 
           linear-gradient(calc(var(--s)*90deg), #e6e6e6, #ececec) padding-box, 
           linear-gradient(to right bottom, #fff, #c8c8c8) border-box;
          
          

          以類似的方式,margin,border-width,padding,width,border-radius,background梯度方向,font-size或line-height對標題和段落文本還取決于我們是否是在寬屏場景(在第一級標題的情況下border-radius或background梯度方向,也在奇偶校驗)。

          看效果:

          最后

          本篇文章主要介紹了使用CSS變量來驅動布局和交互的切換的策略,其中值得注意的是:只適用于數值 - 長度,百分比,角度,持續時間,頻率,無單位數值等.

          SS也能寫變量了???

          其實早在2015年,層疊變量的自定義屬性(Custom Properties for Cascading Variables)就已經問世了,給CSS引進了變量的概念。允許我們聲明一個變量,然后在樣式表的其他地方引用這個值。到目前為止,各大瀏覽器廠商基本支持了這個新特性。


          css variables


          肯定有小伙伴想,一些css預處理器也支持變量啊,比如less,sass等。css變量和預處理器里面的變量有著本質的區別,css變量是瀏覽器支持的特性,而預處理器的變量近在css的處理過程中支持,處理完成后這些變量會代替為具體的值。

          定義一個css變量

          :root {
          	--main-font: sans-sarif;
          }

          上面的代碼定義了一個名為--main-font的變量。變量名前必須有兩個連字符(--)。

          變量必須在一個聲明塊內聲明。這里使用了:root選擇器,因此這個變量可以在整個網頁使用。這里可以推斷出,css變量是有作用域的概念的,如果是定義在別的選擇器里面的話,只能在應用了這個選擇器元素的子元素所用的類中去引用這個變量。文字有點繞,我們看個具體的例子。


          css variable示例


          :root、page-content選擇器中定義了分別定義了--main-color、--content-color兩個顏色變量。在類page-content中可以引用--main-color,在類page-content-spec中可以引用--content-color,而在類page-title中無法引用--content-color變量。

          動態改變css variables

          不要將css variables理解為一個全局的常量,定義在:root中,在子選擇器中引用;應該被看作一個選擇器的入參,輸入不同的參數,有不同的表現。簡單來說,可以定義一個變量為黑色,然后在某個容器中重新將其定義為白色。那么基于該變量的任何樣式,在容器外部都會動態解析為黑色,而在容器內部會動態解析為白色。

          我們還可以使用JavaScript在瀏覽器中實時訪問和修改自定義屬性。例如:

          var rootElement=document.documentElement;
          rootElement.style.setProperty('--main-color', 'red')

          總結

          利用這種技術,是不是可以方便的提取網頁主題等特性,實時切換網站主題?

          雖然大部分瀏覽器廠商都支持了css variable特性,但是某些廠商和版本依然不支持,所以我們在使用這個特性的時候,應該準備一個回退方案,類似下面的例子(相當于設置了一個默認值):

          color: black;
          color: var(--main-color)

          好了,今天的內容就講到這里了,小伙伴們覺得怎么樣?歡迎大家在評論區留言和我一起探討!


          主站蜘蛛池模板: 亚洲一区在线视频| 国产产一区二区三区久久毛片国语| 91精品国产一区二区三区左线 | 久久免费区一区二区三波多野| 精品国产高清自在线一区二区三区 | 国产亚洲一区二区三区在线| 国产婷婷色一区二区三区深爱网 | 天堂Aⅴ无码一区二区三区| 中文字幕日韩欧美一区二区三区 | 国产高清在线精品一区二区三区 | 国产成人高清亚洲一区久久| 亚洲日韩AV一区二区三区中文| 亚洲福利一区二区三区| 蜜臀Av午夜一区二区三区| 人妻av无码一区二区三区| 日韩免费无码视频一区二区三区| 中文字幕精品一区| 国产在线无码视频一区二区三区 | 日产一区日产2区| 在线观看免费视频一区| 中文字幕一区二区三区永久| 久久精品国产一区二区三区不卡 | 日韩精品一区二区亚洲AV观看| 亚洲乱码日产一区三区| 国产一区二区电影| 日韩免费无码一区二区三区| 亚洲一区二区三区不卡在线播放 | 一区二区三区四区无限乱码| 一区二区免费在线观看| 一区二区三区www| 久久影院亚洲一区| 午夜福利一区二区三区在线观看 | 无码国产精品一区二区免费式直播 | 丝袜美腿高跟呻吟高潮一区| 成人精品一区二区三区中文字幕 | 亚洲日韩一区二区一无码| 韩国精品一区视频在线播放| 精品一区二区三区中文| 伊人色综合一区二区三区| 一区二区三区视频在线| 午夜视频一区二区三区|