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 99亚洲精品,国产精品网站在线观看,久久99在线

          整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          CSS的革命:從基礎(chǔ)到前沿的全面演變

          離 HTML

          大家都知道 CSS 在 HTML 里面的幾種寫法,先稍微回顧一下:

          • 行內(nèi)樣式:style 屬性
          <element style="style-name: style-value;" />

          內(nèi)聯(lián)樣式:<style> 標簽內(nèi)部編寫 CSS

          <style>
          element {
              style-name: style-value;
          }
          .class-name {
              style-name: style-value;
          }
          #element-1 {
              style-name: style-value;
          }
          </style>
          
          <element id="element-1" class="class-name" />

          導入樣式:<style> 標簽內(nèi)部使用 @import 引入外部 CSS 文件

          <style>
          @import url("style-1.css");
          @import "style-2.css";
          </style>
          
          <element id="element-1" class="class-name" />

          外部樣式:<meta> 標簽內(nèi)部使用 <link> 標簽引入外部 CSS 文件

          <header>
              <meta>
                  <link type="text/css" rel="stylesheet" href="css-herf">
              </meta>
          </header>
          
          <body>
              <element id="element-1" class="class-name" />
          </body>

          在直接編寫 HTML 的時候,我們幾乎不會用行內(nèi)樣式與導入樣式。行內(nèi)樣式可復用性、可維護性、性能都很差,而導入樣式看起來雖然挺好的,但是有著致命缺點,我們一般不會使用:會影響瀏覽器 并發(fā) 請求資源的效率,因為它們的加載時機不確定或會被其他資源阻塞。 具體表現(xiàn)如下:

          執(zhí)行順序

          內(nèi)聯(lián) @import

          外部 @import

          標簽

          內(nèi)聯(lián) @import

          并行

          外部 @import阻塞

          并行,部分情況阻塞(IE)

          外部 @import

          /

          并行

          @import 阻塞

          標簽

          /

          /

          并行

          可以發(fā)現(xiàn)其優(yōu)先級在大部分情況下低于標簽,最好的情況也只是并行渲染,這導致:

          • 可能會延遲頁面樣式的渲染,可能會造成頁面閃爍的現(xiàn)象;
          • 可能會延遲頁面樣式的應(yīng)用,可能會和頁面中的 javascript 腳本產(chǎn)生沖突,導致 js 修改的樣式被后加載的外部樣式表覆蓋;

          在最開始的時候,我們在努力讓 CSS 與 HTML 分離,形成獨立的兩個文件,這樣有利于內(nèi)容與表現(xiàn)的分離。

          組織 CSS 代碼

          在實際開發(fā)中我們發(fā)現(xiàn),使用 class 選擇器比使用其他選擇器優(yōu)勢更大,因為class選擇器是最初的模塊化思想。但是隨著項目規(guī)模的增大,CSS 的一個缺點逐漸浮現(xiàn)出來:全局作用域,這導致我們不得不將這些 class 的命名區(qū)別開來。為了解決 CSS 全局作用域和命名沖突的問題,很多大佬、組織提出了一些規(guī)范和指南。

          如何組織 CSS 代碼?這些方法有些是基于面向?qū)ο笏枷氲模行┦腔诮M件化思想的,有些是基于樣式規(guī)則分類的,有些是基于樣式規(guī)則分層的,還有些是基于最小化樣式規(guī)則的。不同的方法論有不同的特點和適用場景。

          當然,我們現(xiàn)在已經(jīng)不會去直接使用這些方法了,但了解這些方法也有助于我們一窺大佬們的思想。

          下面我們來具體的看一下每種方法。

          OOCSS - Object Oriented CSS

          OOP 的主要要素:類(方法、變量的集合)、對象(類的一個實例) 類與類的關(guān)系有繼承(父子關(guān)系)、實現(xiàn)(類型-定義關(guān)系)、依賴(平等關(guān)系)、關(guān)聯(lián)(平等關(guān)系)、聚合(弱部分-整體關(guān)系)、組合(強部分-整體關(guān)系)

          我們肯定都聽說過 OOP(Object-oriented programming - 面對對象編程),那么 OOCSS 同理,是一種面對對象的 CSS 命名方式,它于 2008 年由 Nicole Sullivan 提出。

          CSS 本身是聲明式的編程語言,不具備任何的面對對象能力,我們需要構(gòu)建出自己的一套“約定”。在 OOCSS 中,“對象”指 HTML 元素或相關(guān)內(nèi)容(如 CSS 類或 JavaScript 方法)。比如,側(cè)邊欄小部件對象可復制用于不同目的(通訊注冊、廣告塊、最近文章等)。CSS “對象”是一種重復的視覺模式,可以抽象為獨立的代碼片段。 OOCSS 主要有以下兩個原則:

          結(jié)構(gòu)和皮膚分離

          • 結(jié)構(gòu)是指應(yīng)用于元素(寬度、高度、邊距、填充)的不可見樣式,而皮膚是可見樣式(顏色、字體、陰影)。
          • 用可重復的類來定義獨特的樣式(例如浮動,clearfix,獨特的字體堆棧)。
          // non-OOCSS
          .button {
             width: 100px;
             height: 50px;
             background: #000;
             color: #fff;
          }
          
          
          .button-2 {
             width: 100px;
             height: 50px;
             background: #fff;
             color: #333;
          }


          // OOCSS
          .button {
             background: #000;
             color: #fff;
          }
          
          .button-2 {
             background: #fff;
             color: #333;
          }
          
          .btn-structure {
             width: 100px;
             height: 50px;
          }

          容器和內(nèi)容分離

          • 內(nèi)容指的是圖片、段落、div等元素,它們被嵌套在作為容器的其他元素中。
          • 避免使用子選擇器和 ID 選擇器,用于內(nèi)容元素的樣式應(yīng)該是獨立于容器類的,這樣它就可以在其任何地方不受限制地使用。
          // non-OOCSS
          #sidebar {
              padding: 2px;
              left: 0;
              margin: 3px;
              position: absolute;
              width: 140px;
          }
          
          #sidebar .list {
              margin: 3px;
          }
          
          #sidebar .list .list-header {
              font-size: 16px;
              color: red;
          }
          
          #sidebar .list .list-body {
              font-size: 12px;
              color: #FFF;
              background-color: red;
          }


          // OOCSS
          .sidebar {
              padding: 2px;
              left: 0;
              margin: 3px;
              position: absolute;
              width: 140px;
          }
          
          .list {
              margin: 3px;
          }
          
          .list-header {
              font-size: 16px;
              color: red
          }
          
          .list-body {
              font-size: 12px;
              color: #FFF;
              background-color: red;
          }

          許多開發(fā)者認為,OOCSS 易于分享和維護。相比之下,SMACSS 等模塊化方法對 CSS 對象有更嚴格的分類規(guī)則。

          SMACSS - Scalable and Modular Architecture for CSS

          SMACSS(Scalable and Modular Architecture for CSS)即可伸縮及模塊化的 CSS 結(jié)構(gòu),由 Jonathan Snook 在 2011 年雅虎時提出。與 OOCSS 不同的是,SMACSS 的關(guān)注點在于網(wǎng)絡(luò)元素的所屬功能。

          SMACSS 將網(wǎng)頁的 CSS 分為以下幾個組件大類:

          Base(基礎(chǔ))

          顧名思義,基本規(guī)則需要應(yīng)用于網(wǎng)頁的基本元素。下面的示例可以被認為是 SMACSS 中的一部分基本規(guī)則:

          body { 
              margin-left : 20px; 
          }
          
          p {
              font-family: xyz;
          }

          我們將基本規(guī)則應(yīng)用于在整個網(wǎng)頁中保持一致的元素。在上面的 SMACSS 示例中,我們希望內(nèi)容距離左邊 20px 顯示,段落元素應(yīng)該有一種特定的字體。

          除了直接元素外,Base 類型的 CSS 還可以使用后代選擇器、子選擇器和偽類。但是,在創(chuàng)建基本規(guī)則時,我們不能使用任何 !important。這可能是因為當我們的樣式從不同的部分或特異性問題(稍后討論)開始覆蓋時,會顯示出不希望的行為。

          你可能會想到使用 CSS-resets 來代替這些樣式,但是這會增加從服務(wù)器發(fā)送到客戶端的代碼量。因此,如果你想要創(chuàng)建任何默認設(shè)置的 CSS,Base 是一個很好的地方來記下它們。

          Layout(布局)

          第二條規(guī)則講的是如何設(shè)計網(wǎng)頁應(yīng)用的布局的 CSS。網(wǎng)頁的主要部分都屬于布局的范疇。為它們設(shè)計CSS通常會遇到很多挑戰(zhàn),因為涉及到很多元素,而且用多個 ID 來定義每個布局會讓事情變得更復雜。

          一個簡單的不太成熟的 CSS 設(shè)計如下:

          #header, #features, #sidebar {
              //樣式
          }

          但是,當我們需要根據(jù)不同的偏好來設(shè)計多種布局時,上面的不太成熟的CSS設(shè)計就會失效。在這種情況下,可以用前綴“l(fā)”來表示這個類選擇器是基于一個布局元素的。

          #header {
              //樣式
          }
          
          #sidebar {
              //樣式
          }
          
          .l-mobile #sidebar {
              //移動端特定的樣式,比如寬度
          }

          在上面的示例中,l-mobile 類表示它是為了改變與移動端相關(guān)的元素的“布局”而構(gòu)建的。因此,“l(fā)”這個名稱在 SMACSS 的布局規(guī)則中并不是必須使用的。但是,SMACSS 作者建議使用它作為一個標準,以便更好地閱讀。

          題外話:我不同意 SMACSS 的這種在 layout 類型里面用 ID 選擇器的行為,我們應(yīng)該從始至終使用 class 選擇器。如下示例

          .l-header {
              //樣式
          }
          
          .l-sidebar {
              //樣式
          }
          
          .l-mobile-sidebar {
              //移動端特定的樣式,比如寬度
          }

          Module(模塊)

          模塊是布局元素的較小部分,例如導航、小部件、對話框等。將模塊視為布局的一部分會增加不必要的復雜性,因為模塊在多個地方使用比大型布局更多,可以把布局看作是主要的布局,模塊看作是次要的布局

          模塊的命名很符合我們的直覺:

          .heading {}
          
          .heading-email {}
          
          .heading-news {}

          State(狀態(tài))

          在我們精心制定了布局和模塊規(guī)則之后,我們還需要考慮元素狀態(tài)的設(shè)計。當一個元素有多個狀態(tài)時,就需要應(yīng)用狀態(tài)規(guī)則。例如,一個模塊可以處于錯誤狀態(tài)(取決于收到的錯誤)或成功狀態(tài)。對于這兩種狀態(tài),模塊都需要渲染不同的樣式,這就是狀態(tài)規(guī)則的作用。

          .is-error {
              //樣式
          }
          
          .is-success {
              //樣式
          }

          Theme(主題)

          主題規(guī)則是為 Web 應(yīng)用程序的主題定義的。例如,每個網(wǎng)站都有一個反映業(yè)務(wù)或基于其他策略的主題。但很多網(wǎng)站可能不需要更換主題的功能,因此這個規(guī)則是可選的。

          .button-large {
              width: 60px;
              height: 60px;
          }

          這種規(guī)則看起來和默認規(guī)則很像,但基本規(guī)則只針對默認的外觀,而且往往是類似于重設(shè)為默認的瀏覽器設(shè)置;而主題規(guī)則則更像是一種風格設(shè)計,它給出了最終的外觀,對于這個特定的色彩方案是獨一無二的。

          BEM - Block Element Modifier


          BEM(Block Element Modifier)是一種典型的 CSS 命名方法論,由 Yandex 團隊在 2009 年前提出。BEM 和上面兩種方法非常的不一樣,他是通過全局統(tǒng)一的格式來命名出獨一無二的 class,每一個 class 都由以下部分組成:

          Block

          獨立的實體,其本身就有著明確意義。比如header, container, menu, checkbox, input等。

          Element

          一個區(qū)塊的一部分,沒有獨立的意義,在語義上與它的區(qū)塊相聯(lián)系。就是說 Element 不能脫離 Block 存在。比如menu-item, list-item, checkbox-caption, header-title等。如果 Element 里面還有 Element,使用 - 分割。

          Modifier

          塊或元素上的一個標志。用它們來改變外觀或行為,類似于 SMACSS 的 State + Theme。比如disabled, highlighted, checked, fixed, size-big, color-yellow 等。

          BEM 的規(guī)則非常清晰易懂,而且可以使用 SCSS 等預處理器來完成,在 2020 年的 CSS 調(diào)查里面位居榜首。

          // 配合 SCSS 語法
          .card {
            &__head {}
            &__menu {
              &-item {
                &--active {}
                &--disable {}
              }
            }
            &__body {}
            &__foot {}
          }

          ITCSS - Inverted Triangle CSS

          作為原子化 CSS 的思路來源,ITCSS 是一種比較新的 CSS 代碼組織方法。他 CSS 命名無關(guān),可以與 BEM、SMACSS 或 OOCSS 等方法一起使用。ITCSS 把 CSS 代碼的特征分成了三個維度,再根據(jù)這三個維度進行分層:

          1. Reach - 范圍:CSS 代碼所能影響的范圍
          2. Specificity - 特異性:CSS 代碼的普適程度
          3. Explicitness - 明確性:CSS 代碼的名稱確定性

          根據(jù)以上特征的不同,ITCSS 將 CSS 代碼分為以下幾層:

          • Settings 設(shè)置 -- 與預處理器一起使用,包含字體、顏色定義等。
          • Tools 工具 -- 全局使用的混合元素和函數(shù)。重要的是不要在前兩層輸出任何CSS。
          • Generic 通用 -- 重置和/或規(guī)范化樣式,盒狀大小的定義,等等。這是產(chǎn)生實際CSS的第一層。
          • Elements 元素 -- 裸露的HTML元素的樣式(如H1、A等)。這些元素帶有瀏覽器的默認樣式,所以我們可以在這里重新定義它們。
          • Objects 對象 -- 基于類的選擇器,它定義了非裝飾的設(shè)計模式,例如OOCSS中的媒體對象。
          • Components 組件 -- 特定的UI組件。這是我們大部分工作發(fā)生的地方。我們經(jīng)常將UI組件由Objects和Components組成。
          • Utilities 實用工具 -- 實用工具和輔助類,能夠覆蓋三角形中的任何東西,例如,隱藏輔助類。

          可以看到,ITCSS 的分層較多,每層的樣式都可以覆蓋前面一層的樣式。將 ITCSS 層組織到子文件夾中,并使用 Sass 或其他預處理器編譯新添加的文件:

          // ITCSS + SCSS
          @import 'settings/*';
          @import 'tools/*';
          @import 'generic/*';
          @import 'elements/*';
          @import 'vendor/*';
          @import 'objects/*';
          @import 'components/*';
          @import 'utilities/*';


          // BEMIT
          .s-name
          .t-name
          .g-name
          .e-name
          .v-name
          .o-name
          .c-name
          .u-name

          ITCSS 只是一種組織結(jié)構(gòu),這種組織結(jié)構(gòu)清晰易懂,我們可以快速組織并分享我們的 CSS 代碼。ITCSS 和 BEM 一起使用的時候,有一個獨特的名稱:BEMIT,使用的時候無需去思考 CSS 代碼存放的位置,只需要在 BEM 前面加上 ITCSS 的前綴即可。

          pre-processor


          上面我們提到了“預處理器”,可能你會疑問,預處理器是什么東西?

          CSS 預處理器是一種程序,可讓您從預處理器自己的獨特語法生成 CSS。簡單來說,預處理器就是一個編譯器,有了這個編譯器,我們就可以用很多原生 CSS 不具有的特性,例如 mixin、嵌套選擇器、繼承選擇器等。這些特性使 CSS 結(jié)構(gòu)更具可讀性和更易于維護。

          每個 CSS 預處理器都有自己的語法,它們編譯成常規(guī) CSS,以便瀏覽器可以在客戶端呈現(xiàn)它。CSS 預處理器以或多或少不同的方式做類似的事情,并且每個都有自己的語法和生態(tài)系統(tǒng)(工具、框架、庫)。現(xiàn)在流行的 CSS 預處理器大概有以下三個:

          Sass & SCSS: Syntactically Awesome Style Sheets

          Sass 是最流行和最古老的 CSS 預處理器,最初發(fā)布于2006年。它的創(chuàng)造者 Natalie Weizenbaum 和 Hampton Catlin 受到 Haml模板語言的啟發(fā),該語言為 HTML 增加了動態(tài)功能。他們的目標是在 CSS 中也實現(xiàn)類似的動態(tài)功能。因此,他們想出了一個 CSS 預處理器,并將其命名為 Syntactically Awesome Style Sheets。

          Sass 預處理器允許我們使用變量、if/else 語句、for/while/each 循環(huán)、繼承、運算符、插值、混合器和其他動態(tài)功能,然后將代碼編譯成網(wǎng)絡(luò)瀏覽器可以解釋的普通CSS。

          Sass 有兩種語法。

          • .sass 文件擴展名使用基于縮進的舊語法。
          • SCSS 是 Sass 3 引入新的語法,是 Sassy CSS 的簡寫,是更新和更廣泛使用的語法,使用 .scss 文件擴展名。

          下面我們來看個例子,可以看到 SCSS 語法更類似 CSS 語法,沒有什么上手難度:

          /* Sass */
          $primary-color: seashell $primary-bg: darkslategrey  body
              color: $primary-color     background: $primary-bg
              


          /* SCSS */ $primary-color: seashell; $primary-bg: darkslategrey;  body {     color: $primary-color;     background: $primary-bg; }

          Sass 提供了一些很方便我們編寫 CSS 的機制,比如 mixin 函數(shù):

          @mixin card($width, $height, $bg, $border) {       width: $width;       height: $height;       background: $bg;       border: $border; }
          
          .card-1 {
              @include card(300px, 200px, yellow, red 2px solid);
          }
          .card-2 {
              @include card(400px, 300px, lightblue, black 1px dotted);
          }

          其他機制包括:

          • 變量作用域機制
          $global-variable: global value;
          
          .content {
              $local-variable: local value;
              global: $global-variable;
              local: $local-variable;
          }
          
          .sidebar {
              global: $global-variable; 
              // This would fail, because $local-variable isn't in scope:
              // local: $local-variable;
          }
          

          @extend -- CSS class 繼承

          .error {
              border: 1px #f00;
              background-color: #fdd;
              &--serious {
                  @extend .error;
                  border-width: 3px;
              }
          }
          
          // equal to
          .error, .error--serious {
              border: 1px #f00;
              background-color: #fdd;
          }
          .error--serious {
              border-width: 3px;
          }
          • 嵌套語法
          • @if @else @for @while 等條件循環(huán)控制語句
          $base-color: #036;
          @for $i from 1 through 3 {
              ul:nth-child(3n + #{$i}) {
                  background-color: lighten($base-color, $i * 5%);
              }
          }
          • @import 模塊化

          還有其他很多詳細的語法,大家可以去官方文檔了解閱讀,這里不多贅述。

          LESS: "Leaner Style Sheets"

          LESS 由 Alexis Sellier 在 Sass 之后的 2009 年發(fā)布,LESS 受 Sass 影響很多,但其本身也影響了 SCSS。之后 Bootstrap 決定從 LESS 轉(zhuǎn)移到 Sass,這對 LESS 的普及是一個巨大的打擊,導致目前來說 SCSS 的普及率高過 LESS 非常多。

          LESS 的語法非常像 SCSS,但其邏輯處理能力較弱,有興趣的小伙伴可以去官網(wǎng)文檔了解。

          Stylus: Expressive, dynamic, and robust CSS

          Stylus 的第一個版本是在 LESS 一年后推出的,由前 Node.js 開發(fā)者 TJ Holowaychuk 在2010年推出。Stylus 結(jié)合了Sass 強大的邏輯能力和 LESS 簡單明了的設(shè)置,讓他在預處理器的市場份額有著一席之地。

          當然雖然 Stylus 語法靈活,支持兩種不同的語法,但是這也帶來了容易導致混亂的缺點,而且大部分人都選擇用 Sass,導致目前遠不如 Sass 的影響力。


          我們可以很清晰的看到,在SCSS 推出 + node-sass 在重構(gòu)為 dart-sass 之后,爆發(fā)式增長,LESS 和 stylus 都沒有什么抵抗的力量。如果目前需要選擇一個預處理器,這里推薦使用 Sass 的 SCSS 語法。

          不過不管這些 CSS 預處理器流行度怎么樣,他們都是能幫助我們快速組織編寫 CSS 代碼的工具,因地制宜即可。甚至后面我們就知道了,我們也不是非要用他們不可。

          PostCSS


          好了經(jīng)過上面的部分,我猜你對 Less、Sass 和 Stylus 等預處理程序已經(jīng)很熟悉。這些工具是當今網(wǎng)絡(luò)開發(fā)生態(tài)系統(tǒng)的重要組成部分。但是,傳統(tǒng)的預處理器有幾個問題:

          • 它們不遵循 CSS 標準。每個預處理器都已經(jīng)有了自己的標準。遺憾的是,它們不以與 W3C 標準兼容為目標,這意味著它們不能把它們的功能作為 polyfills,用于早期測試較新的 W3C 標準。
          • 它們是不可擴展的。無論你選擇哪種預處理器,你都被限制在它所提供的功能集上。如果你需要在此基礎(chǔ)上的任何功能,你需要在構(gòu)建過程中單獨添加。如果你想寫你的擴展,你就得靠自己了。

          可以看到,盡管傳統(tǒng)的預處理器帶來了許多很優(yōu)秀的特性,但他們嚴格限制了我們的 CSS 編寫思路。這就給了 PostCSS 用武之地。

          上面這幅圖是 PostCSS 的原理,很簡單地,你可以把 PostCSS 理解成 Babel 一樣的代碼轉(zhuǎn)換工具,將我們編寫的 CSS 轉(zhuǎn)成可以瀏覽器可以直接識別的 CSS,而預處理器相當于 Typescript。PostCSS 接收一個 CSS 文件并提供了一個 API 來分析、修改它的規(guī)則(通過把 CSS 規(guī)則轉(zhuǎn)換成一個 抽象語法樹 的方式)。在這之后,這個 API 便可被許多 插件 利用來做有用的事情,比如尋錯或自動添加 CSS vendor 前綴。


          可以看到,PostCSS 的下載次數(shù)遠超預處理器之和,這是因為很多很多三方庫都基于 PostCSS 的能力來構(gòu)建。同時 PostCSS 擁有眾多插件,比如:Autoprefixer(前綴添加)、lost(基于 calc 的柵格系統(tǒng))、Stylelint(CSS 格式檢查)、CSSNext(使用瀏覽器未支持的 CSS語法) 等,這些優(yōu)秀的插件都基于 PostCSS 的能力。

          了解完這些之后,我們就會明白,我們其實沒有必要糾結(jié)使用哪些預處理器了,只需要在 PostCSS 里面安裝我們想要的預處理器語法插件就行。

          高級模塊化

          其實上面我們介紹的組織 CSS 代碼都是具有模塊化思想的,但是這些模塊化思想都是非自動化的,說白了就是,我們需要時時刻刻記住這些約定,這對于我們的開發(fā)效率來說影響甚大。隨著 React 框架的火熱,前端代碼模塊不再遵循“關(guān)注點分離”原則,而是一個 HTML+CSS+JS 構(gòu)成的組件為核心。但是 React 并沒有像 Vue 一樣提供了 scope 等內(nèi)置機制,因為 React 本身的設(shè)計原則決定了其不會提供原生的 CSS 封裝方案。舊的代碼模塊化約定已經(jīng)不能適應(yīng)新的開發(fā)方式的需求,模塊化的兩種最強形式呼之欲出。

          CSS Modules

          首先是對我們代碼編寫方式影響較小的 CSS Modules。其實 CSS Modules 在本質(zhì)上也是 CSS-in-JS 的一種,但其功能比較簡單,也類似于關(guān)注點分離的寫法,所以其從 CSS-in-JS 中獨立出來并成為一種獨立的思想。

          CSS Modules 的核心很簡單,就是只管理好 CSS 代碼的作用域,讓我們可以通過類似 ESM 的方式來組織 CSS 代碼。他以 CSS 文件模塊為單元,將模塊內(nèi)的選擇器附上特殊的哈希字符串,以實現(xiàn)樣式的局部作用域。對于大多數(shù) React 項目來說,這種方案已經(jīng)足夠用了。


          CSS Modules 有以下幾個重要特性:

          • 局部作用域:構(gòu)建時會將類名style.title編譯成一個哈希字符串。可以在對應(yīng)的插件配置中定制哈希類名。
          // before
          .title {
              color: red;
          }
          
          // equal to
          :local(.title) {
              color: red;
          }
          
          // after
          ._3zyde4l1yATCOkgn-DBWEL {
              color: red;
          }
          • 全局作用域
            • :global(.className),使用這種語法的類名不會被編譯成哈希字符串。
          • 類名組合機制:一個選擇器可以繼承另一個選擇器的規(guī)則
            • 編譯前:
          .className {
              background-color: blue;
          }
          
          .title {
              composes: className;
              color: red;
          }


          <h1 className={style.title}>

          編譯后:

          ._2DHwuiHWMnKTOYG45T0x34 {
              color: red;
          }
          
          ._10B-buq6_BEOTOl9urIjf8 {
              background-color: blue;
          }


          <h1 class="_2DHwuiHWMnKTOYG45T0x34 _10B-buq6_BEOTOl9urIjf8">

          使用 CSS Modules 之后,我們不需要使用任何類似 BEM 的命名約定了,因為我們的 CSS 代碼的作用域已經(jīng)被分隔開了,不要命名一個項目唯一的 CSS 類名。同時我們可以在項目的組件文件夾中直接編寫 CSS 文件,這對于我們的開發(fā)體驗來說是一個質(zhì)的飛躍。

          CSS Modules 可以配合 PostCSS 一起使用,這樣我們也可以用各種額外特性,例如 CSS 變量或者預處理器語法等。

          CSS-in-JS

          CSS-in-JS 在 2014 年由 Facebook 的員工 Vjeux 在 NationJS 會議上提出:可以借用 JS 解決許多 CSS 本身的一些“缺陷”,比如全局作用域、死代碼移除、生效順序依賴于樣式加載順序、常量共享等等問題。


          很明顯,CSS-in-JS 是一種沒有標準規(guī)范的思想,他的主要要義就是在 JS 里面寫 CSS。這就導致其實現(xiàn)非常非常多,目前有六十多種 CSS-in-JS 的實現(xiàn)。每隔一段時間,都會有新的語法方案或?qū)崿F(xiàn),嘗試補充、增強或是修復已有實現(xiàn)。


          CSS-in-JS 雖然解決了一些直接編寫 CSS 代碼的問題,但他也帶來了一些問題:

          • 使用 CIJ 可能是一種不必要的需求。如果開發(fā)者能夠充分理解 CSS 的基本概念,比如特異性、級聯(lián)、繼承等,同時運用一些預處理或后處理工具(例如 scss/postcss)和規(guī)范化的命名方法(例如 BEM),那么純 CSS 就可以滿足開發(fā)需求,無需引入額外的復雜度。
          • CIJ 的方案和工具琳瑯滿目,但是缺乏統(tǒng)一的標準和規(guī)范,許多還處于試驗性或不穩(wěn)定的階段,使用起來存在較大的風險和不確定性。一旦選擇了某個方案,就可能面臨這個方案被廢棄或不兼容的問題,導致代碼難以維護或遷移。
          • CIJ 會增加運行時的性能開銷,因為它需要在瀏覽器中動態(tài)生成和注入 CSS,這會消耗更多的內(nèi)存和 CPU 資源,影響頁面的加載速度和用戶體驗。

          下面我們來看看幾種 CIJ 的具體實現(xiàn)。

          styled-components


          styled-components 是一種 CSS-in-JS 的實現(xiàn)方式,它可以讓你在 React 組件中直接寫 CSS 代碼,從而實現(xiàn)組件和樣式的一一對應(yīng)。這樣,你就不需要再為每個組件定義一個單獨的 CSS 文件或者使用類名來管理樣式了,而是可以將樣式和組件的邏輯和結(jié)構(gòu)緊密地結(jié)合在一起。

          styled-components 的原理是利用了 JavaScript 的標簽模板字符串(tagged template literals)功能,將 CSS 代碼作為一個函數(shù)的參數(shù)傳遞,然后在運行時動態(tài)生成和注入樣式表。例如,你可以這樣定義一個按鈕組件:

          import styled from 'styled-components';
          
          const Button = styled.button`
            background: palevioletred;
            color: white;
            border-radius: 4px;
          `;

          這里,styled.button 是一個函數(shù),它接收一個模板字符串作為參數(shù),并返回一個 React 組件。這個組件會渲染一個帶有指定樣式的按鈕元素。你可以像使用任何其他 React 組件一樣使用這個 Button 組件:

          <Button>Click me</Button>

          styled-components 有以下幾個優(yōu)勢:

          • 可以避免 CSS 類名的沖突和全局污染,因為它會自動生成唯一的類名。這樣,你就不需要擔心命名沖突或者覆蓋了其他組件的樣式了。
          • 可以利用 JavaScript 的變量和邏輯來動態(tài)地控制樣式。例如,你可以根據(jù) props 或者主題來改變組件的顏色、大小、邊距等屬性。
          • 可以支持主題和樣式繼承等功能,方便實現(xiàn) UI 的一致性。例如,你可以使用 ThemeProvider 組件來提供一個全局的主題對象,然后在任何組件中通過 props.theme 來訪問它。

          styled-components 也有以下幾個劣勢:

          • 可能會增加代碼的復雜度和可讀性,因為需要在 JavaScript 中混合寫 CSS 代碼。這樣,你就不能利用一些專門針對 CSS 的工具或者編輯器功能了,而且也可能降低代碼的可維護性和可測試性。
          • 可能會影響運行時的性能,因為需要在瀏覽器中解析和注入樣式表。這樣,你就不能利用一些針對 CSS 的優(yōu)化技術(shù)了,比如 CSS 提取、壓縮、緩存等。
          • 可能會導致樣式的重復或冗余,因為每個組件都會生成一個獨立的樣式表。這樣,你就不能利用 CSS 的繼承和級聯(lián)機制了,而且也可能增加最終打包后的文件大小。
          • 可能會與一些第三方庫或工具不兼容,比如 CSS 模塊、CSS 提取、CSS Lint 等。這樣,你就不能使用這些庫或工具來提高你的開發(fā)效率和代碼質(zhì)量了。

          總之,styled-components 可以讓你在 React 組件中直接寫 CSS 代碼,從而實現(xiàn)組件和樣式的一一對應(yīng)。如果你想使用 styled-components 來開發(fā)你的 React 應(yīng)用,你需要根據(jù)你的具體需求和場景來權(quán)衡它的利弊,選擇適合你的方案。

          Emotion

          Emotion 是另外一個流行的 CSS-in-JS 庫,由于這兩個庫比較類似,我們主要就針對這兩個庫做一些對比:

          • styled-components 和 emotion 都使用了模板字符串(template literals)來創(chuàng)建樣式化的組件,這樣可以保持CSS的語法和高亮,同時也可以使用JavaScript的變量和表達式。
          • styled-components 和 emotion 都支持主題(themes),即一組全局的樣式變量,可以在不同的組件中共享和使用。它們也都支持媒體查詢(media queries),即根據(jù)不同的設(shè)備或屏幕尺寸來調(diào)整樣式。
          • styled-components和emotion的主要區(qū)別在于:
            • emotion支持更多的API,例如css prop,@emotion/core,@emotion/styled等,而styled-components只支持styled API。可以說這點是差距最大的一點。
            • emotion提供了更好的開發(fā)者體驗,例如支持自動標簽(auto-labels),即在開發(fā)者工具中顯示組件的名稱,以及支持源映射(source maps),即在開發(fā)者工具中顯示樣式的來源文件和行數(shù)。
            • emotion具有更高的渲染速度,即在瀏覽器中將樣式應(yīng)用到組件上所需的時間。根據(jù)測試結(jié)果,emotion比styled-components 快了約10%。

          最終我們還是需要根據(jù)自己的項目需求和偏好來選擇合適的庫。如果項目需要更多的靈活性和性能,可以選擇 emotion。如果項目需要更簡單和一致的API,可以選擇 styled-components。

          Stitches & vanilla-extract

          下面介紹的是兩個比較新且評價較好的的 CSS-in-JS 庫。


          Stitches **是一個 TypeScript 友好的 CSS-in-JS 庫,具有接近零運行時,服務(wù)器端渲染,多變量支持和一流的開發(fā)人員體驗。vanilla-extract 是一個 Stitches 的競爭對手,稱自己為“CSS Modules-in-TypeScript”,vanilla-extract 是真正的零運行時(Stitches 6 kB gzipped)。

          類似 styled-components 的 CSS-in-JS 庫由于需要在運行時動態(tài)注入 CSS,性能較差,而新的 CSS-in-JS 庫基本都拋棄了運行時的思路,轉(zhuǎn)而在編譯階段生成固定的 CSS 代碼。這樣有兩個好處:

          可以減小 JS 文件的體積 可以完美支持 SSR 加快客戶端運行速度

          具體到他們的區(qū)別,可以看看這篇文章:Vanilla-Extract & Stitches: A Comparison,總之,vanilla-extract 是最為先進、迅猛的 CSS-in-JS 庫,因為他是真正的零運行時庫,FCP 可能稍大,但 TTL 很小,用戶體驗很棒,適合開發(fā)大型應(yīng)用。 我們來簡單看個 vanilla-extract 的 demo:

          import { style } from '@vanilla-extract/css';
          
          export const parentClass = style({
              background: 'red',
              ':hover': {
                  background: 'blue',
              },
          });
          
          export const childClass = style({
              selectors: {
                  '&:nth-child(2n)': {
                      background: '#fafafa',
                  },
                  [`${parentClass} &`]: {
                      color: 'pink',
                  },
              },
          });


          import { childClass, parentClass } from './index.styles.css';
          const Demo = () => (
              <div className={parentClass}>
                  <div className={childClass}>DEMO1</div>
                  <div className={childClass}>DEMO2</div>
                  <div className={childClass}>DEMO3</div>
              </div>
          );
          
          export default Demo;

          Atomic CSS

          原子 CSS 就像是實用工具優(yōu)先(utility-first)CSS 的一個極端版本: 所有 CSS 類都有一個唯一的 CSS 規(guī)則。原子 CSS 最初是由 Thierry Koblentz (Yahoo!)在 2013 年挑戰(zhàn) CSS 最佳實踐時使用的。在前端構(gòu)建工具沒有成熟的時候,這種思想基本很難實現(xiàn),但是現(xiàn)在借助 PostCSS 的力量,有一些原子化 CSS 庫例如 Tailwind CSS 開始被廣泛使用。

          .m-0 {
              margin: 0;
          }
          
          .text-red {  
              color: red;
          }

          下面這個在組件數(shù)量膨脹的情況下,使用原子化和不使用原子化的性能圖。可以看到不使用原子化 CSS 的時候是線性增長,而使用之后是對數(shù)增長。因為原子化 CSS 的上限是固定的,而普通 class 的上限是不確定的,隨著組件數(shù)量的增加,使用的原子化 CSS class 數(shù)量趨于穩(wěn)定,而普通 class 數(shù)量依舊在一路狂奔。


          Tailwind CSS 這里就不多介紹了,其流行程度完全超過了流行程度最高的組件庫 MUI(人們都喜歡自己造輪子)。而 Tailwind CSS 的最新競對 UnoCSS,由 Vite 核心團隊打造,不使用 PostCSS,性能比 Tailwind CSS 快 100 倍。具體快的來龍去脈可以參考這篇文章:重新構(gòu)想原子化 CSS。

          當然原子化 CSS 也有缺點:

          • 不易維護。如果要修改常用的原子類,如 m20(表示 margin 20px ),要么改變它的定義(違背它的命名),要么批量替換它的引用(費時費力)。如果只要修改部分引用,就更麻煩了。
          • 學習成本。影響開發(fā)效率,解決方案安裝對應(yīng)的vscode插件,語法提示能夠幫助我們,但是仍然無法完全避免去翻官方文檔。

          總結(jié)

          希望你能通過以上,了解 CSS 的發(fā)展脈絡(luò),在開發(fā)過程選擇合適的 CSS 技術(shù)提高我們的開發(fā)效率。隨著前端的發(fā)展,CSS 技術(shù)仍然在不斷進化,我們也要時刻保持學習的心態(tài),去接觸最前沿的知識。

          數(shù)字化辦公的海洋里,PDF文檔如同一座座島嶼,而我們的目標則是將這些島嶼轉(zhuǎn)化為能在互聯(lián)網(wǎng)上自由航行的船只——HTML網(wǎng)頁文件。那么,有沒有一把神奇的鑰匙能夠輕松打開這扇轉(zhuǎn)換之門呢?當然有!那就是我們的“首助編輯高手”軟件。它不僅是一個好用的PDF編輯器,更是一個PDF轉(zhuǎn)換大師,能夠一鍵將PDF文檔批量轉(zhuǎn)換為HTML網(wǎng)頁文件,并且還能將新文件保存在原文件相同的位置,讓你的辦公之旅更加順暢無阻!

          1.軟件的PDF編輯工具不僅具備傳統(tǒng)的PDF新建和修改功能,更在格式轉(zhuǎn)換方面表現(xiàn)出色。

          2.用戶只需在軟件的批量轉(zhuǎn)換格式中選擇PDF轉(zhuǎn)HTML模式,即可輕松實現(xiàn)PDF到HTML的轉(zhuǎn)換。這一功能極大地提高了工作效率,讓用戶在處理大量PDF文檔時事半功倍。

          3.在實際操作中,我體驗到了軟件的便捷與高效。通過簡單的添加文件或添加文件夾中的文件操作,我成功導入了多個PDF文檔。

          4.在設(shè)置新文件保存位置時,我選擇了與原文件相同的位置,這樣便于后續(xù)管理和查找。

          5.點擊開始轉(zhuǎn)換按鈕后,軟件迅速完成了轉(zhuǎn)換工作,生成了對應(yīng)的HTML網(wǎng)頁文件。

          6.查看轉(zhuǎn)換后的HTML文件時,我發(fā)現(xiàn)文檔的格式和排版都得到了很好的保留。

          7.與未轉(zhuǎn)換前的PDF文檔相比,HTML文件在網(wǎng)頁上的展示效果更加友好,同時也方便進行進一步的編輯和修改。

          首助編輯高手軟件就像是一位掌握了魔法技能的辦公助手,無論我們面對的是一座座PDF文檔的孤島,還是一片茫茫的HTML海洋,它都能輕松駕馭,幫助我們實現(xiàn)文檔的完美轉(zhuǎn)換。它的批量轉(zhuǎn)換功能不僅提高了我們的工作效率,更讓我們的辦公體驗變得更加輕松愉快。如果你還在為PDF和HTML之間的轉(zhuǎn)換而煩惱,那么不妨試試軟件吧!相信它一定會成為你辦公桌上不可或缺的好幫手。



          將網(wǎng)頁轉(zhuǎn)換為圖片,您可以使用一些庫和工具來實現(xiàn)。在前端開發(fā)中,常用的庫包括html2canvas和dom-to-image。這些庫允許您將HTML元素轉(zhuǎn)換為圖像。

          下面是使用html2canvas庫將網(wǎng)頁轉(zhuǎn)換為圖像的示例代碼:

          <!DOCTYPE html>  
          <html>  
          <head>  
            <title>Convert Webpage to Image</title>  
            <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.2/html2canvas.min.js"></script>  
          </head>  
          <body>  
            <div id="capture">  
              <!-- 在這里放置您想要轉(zhuǎn)換為圖像的HTML內(nèi)容 -->  
              <h1>Hello, World!</h1>  
              <p>This is an example of converting a webpage to an image.</p>  
            </div>  
            
            <button onclick="convertToImage()">Convert to Image</button>  
            
            <script>  
              function convertToImage() {  
                html2canvas(document.getElementById("capture")).then(canvas => {  
                  var img = canvas.toDataURL("image/png");  
                  var link = document.createElement("a");  
                  link.href = img;  
                  link.download = "webpage.png";  
                  link.click();  
                });  
              }  
            </script>  
          </body>  
          </html>

          上述代碼使用html2canvas庫來將id為"capture"的div元素轉(zhuǎn)換為圖像。當用戶點擊"Convert to Image"按鈕時,convertToImage()函數(shù)會被調(diào)用。該函數(shù)使用html2canvas對指定的HTML元素進行截圖,并將結(jié)果轉(zhuǎn)換為一個包含圖像數(shù)據(jù)的URL。然后,創(chuàng)建一個隱藏的鏈接元素,將圖像數(shù)據(jù)URL設(shè)置為鏈接的href屬性,并模擬點擊該鏈接以下載圖像。最后,圖像將以PNG格式下載到用戶的設(shè)備上。

          請注意,html2canvas庫有一些限制和局限性,例如跨域圖像的限制、CSS樣式的復雜性等。確保在使用這些庫時仔細測試和驗證您的代碼,并查閱相關(guān)文檔以了解更多細節(jié)和選項。


          主站蜘蛛池模板: 97久久精品无码一区二区天美 | 亚洲av无码片vr一区二区三区| 国产伦精品一区二区三区视频猫咪| 亚洲人成人一区二区三区| 亚洲一区二区三区久久| 久久亚洲色一区二区三区| 成人h动漫精品一区二区无码| 亚洲韩国精品无码一区二区三区| 国产一区二区三区播放| 日韩一区二区免费视频| 亚洲av无码一区二区三区在线播放| 精品久久国产一区二区三区香蕉| 国产乱码精品一区二区三区| 日韩一区二区视频| 中文字幕一区二区三区在线观看 | 国产成人精品无码一区二区| 国产主播一区二区三区在线观看| 麻豆一区二区免费播放网站| 久久久久人妻一区二区三区vr| 国产免费无码一区二区| 果冻传媒董小宛一区二区| 中文字幕一区视频一线| 制服中文字幕一区二区 | 国产91精品一区二区麻豆网站| 国产在线一区二区三区| 国产视频一区二区在线播放| 久久精品国产一区二区| 激情综合一区二区三区| 免费一区二区三区| 日韩人妻无码一区二区三区99 | 亚洲啪啪综合AV一区| 日韩精品无码一区二区三区免费 | 日韩国产免费一区二区三区| 色婷婷一区二区三区四区成人网| 亚洲一区二区三区久久| 亚洲av无一区二区三区| 麻豆视传媒一区二区三区| 香蕉免费看一区二区三区| 风间由美性色一区二区三区| 中文字幕一区二区三区人妻少妇| 国产精品无码一区二区三区毛片|