1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        好家伙,這些寫 CSS 的新姿勢(shì)你還不知道?

        共 10941字,需瀏覽 22分鐘

         ·

        2021-09-03 09:12

        現(xiàn)在大部分搞前端的應(yīng)該還是這樣寫 CSS 的:
        .mock {
            margin: auto;
            font-size: 16px;
            // ...
        }
        <div class='mock'>mock</div>

        以上代碼就是舉個(gè)例子,大部分情況應(yīng)該都是寫一個(gè)類,然后整一堆樣式進(jìn)去。

        但是這種方式寫多了以后,你應(yīng)該會(huì)感受到一些痛點(diǎn),比如說(shuō):

        • 取名困難,節(jié)點(diǎn)結(jié)構(gòu)一多,取名真的是個(gè)難事。當(dāng)然了,我們可以用一些規(guī)范或者選擇器的方式去規(guī)避一些取名問(wèn)題。
        • 需要用 JS 控制樣式的時(shí)候又得多寫一個(gè)類,尤其交互多的場(chǎng)景。
        • 組件復(fù)用大家都懂,但是樣式復(fù)用少之又少,這樣就造成了冗余代碼變多。
        • 全局污染,這個(gè)其實(shí)現(xiàn)在挺多工具都能幫我們自動(dòng)解決了。
        • 死代碼問(wèn)題。JS 我們通過(guò) tree shaking 的方式去除用不到的代碼減少文件體積,但是 CSS 該怎么去除?尤其當(dāng)項(xiàng)目變大以后,無(wú)用 CSS 代碼總會(huì)出現(xiàn)。
        • 樣式表的插入順序影響了 CSS 到底是如何生效的。
        • 等等,不一一說(shuō)明了。其實(shí)對(duì)于筆者而言,第一二塊在開(kāi)發(fā)中是最難受的兩個(gè)點(diǎn),尤其是剛寫前端,需要做活動(dòng) / 產(chǎn)品頁(yè)的時(shí)候。

        當(dāng)下,社區(qū)里有一些 CSS 方案,能夠解決以上一些痛點(diǎn):

        • Atom CSS
        • CSS-in-JS
        • 上述兩者的結(jié)合體

        本文就來(lái)聊聊以上三種方案的優(yōu)缺點(diǎn)以及各自方案的代表作。

        Atom CSS

        首先來(lái)聊聊啥叫做 Atom CSS:意思是一個(gè)類只干一件事,比如說(shuō):

        .m-8 {
            margin8px;
        }

        想象一下你按照這樣的思想搞出一大堆類似的類名,就能整出一個(gè)踐行 Atom CSS 方案的三方庫(kù)了,tailwindcss 就是這個(gè)方案里的佼佼者。其實(shí) Atom CSS 很多人應(yīng)該早都用過(guò)了,柵格系統(tǒng)上就有它的身影,無(wú)非不清楚原來(lái)它就是 Atom CSS 罷了。

        我們先來(lái)看看如果用 tailwindcss 的話,寫好樣式的 HTML 大概長(zhǎng)啥樣:

        上圖是人家官網(wǎng)上的,在這之前還有一段挺炫的動(dòng)畫??雌饋?lái)好像挺方便的,寫上一堆類名就能出左邊好看的樣式了,省了很多寫樣式的時(shí)間,但是讀者們可以來(lái)想想這種方式它會(huì)有啥好處及弊端?

        在說(shuō)優(yōu)缺點(diǎn)之前,我們先來(lái)聊聊 Atom CSS 的歷史。其實(shí)它并不是一個(gè)新興產(chǎn)物,這玩意你往前推個(gè)十年就能看到它的討論。正所謂天道好輪回,蒼天饒過(guò)誰(shuí)。Atom CSS 以前火過(guò),而且是被噴火的,沉寂了幾年之后這幾年又被拿出來(lái)說(shuō)了。

        接下來(lái)我們以 tailwindcss 為例來(lái)聊聊 Atom CSS 方案的優(yōu)劣點(diǎn)。

        優(yōu)劣點(diǎn)

        如果你想在團(tuán)隊(duì)內(nèi)部推廣這個(gè)產(chǎn)品,學(xué)習(xí)成本會(huì)是一個(gè)問(wèn)題,畢竟需要大家都看得懂你這坨東西到底是啥意思,這算一個(gè)很明顯的缺陷。但是對(duì)于語(yǔ)法問(wèn)題你還真的不用怎么擔(dān)心,tailwindcss 是有語(yǔ)法補(bǔ)全的工具鏈的,Webstorm 已經(jīng)內(nèi)置了,VSCode 需要大家自行裝個(gè)插件,所以噴寫 tailwindcss 語(yǔ)法麻煩的可以歇一歇。

        樣式復(fù)用,就像寫組件一樣,這次我們是把樣式一個(gè)個(gè)抽離了出來(lái),這樣帶來(lái)的一大好處是減少了 CSS 代碼文件體積。

        原本傳統(tǒng)的寫法是定義一個(gè)類,然后寫上需要的樣式:

        .class1 {
            font-size18px;
            margin10px;
        }
        .class2 {
            font-size16px;
            color: red;
            margin10px;
        }

        這種寫法是存在一部分樣式重復(fù)的,換成 Atom CSS 就能減少一部分代碼的冗余。

        把 CSS 當(dāng)成組件來(lái)寫。大家乍一看 tailwindcss 官網(wǎng)肯定會(huì)覺(jué)得我在 HTML 里寫個(gè)樣式要敲那么多類是有病吧?

        <figure class="md:flex bg-gray-100 rounded-xl p-8 md:p-0">
          <img class="w-32 h-32 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">
          <div class="pt-6 md:p-8 text-center md:text-left space-y-4">
            <blockquote>
              <p class="text-lg font-semibold">
                “Tailwind CSS is the only framework that I've seen scale
                on large teams. It’s easy to customize, adapts to any design,
                and the build size is tiny.”
              </p>
            </blockquote>
            <figcaption class="font-medium">
              <div class="text-cyan-600">
                Sarah Dayan
              </div>
              <div class="text-gray-500">
                Staff Engineer, Algolia
              </div>
            </figcaption>
          </div>
        </figure>

        其實(shí)我們是可以利用 Atom CSS 一次只干一件事的特性,將這些類隨意組裝成我們想要的類,這樣就可以提供出來(lái)一個(gè)更上層的通用樣式來(lái)復(fù)用。

        比如說(shuō)項(xiàng)目中的按鈕都是存在通用的圓角、內(nèi)邊距、字體等,這樣我們就可以封裝出這樣一個(gè)類:

        .btn {
            @apply p-8 rounded-xl font-semibold
        }

        效率工具。tailwindcss 用的好肯定是能提高寫布局的效率的,尤其對(duì)于需要做響應(yīng)式的頁(yè)面而言。當(dāng)然這東西其實(shí)也算是甲之蜜糖乙之砒霜,評(píng)價(jià)兩極分化很嚴(yán)重,有人認(rèn)為提高了效率,也有人認(rèn)為反而是增加了成本,或者說(shuō)是脫褲子放屁。

        提供了一整套規(guī)范化的設(shè)計(jì)模式,直接點(diǎn)說(shuō)就是 tailwindcss 給你內(nèi)置好一套優(yōu)秀的設(shè)計(jì)主題了。但是這玩意對(duì)于規(guī)范的視覺(jué)團(tuán)隊(duì)來(lái)說(shuō)是個(gè)不小的福音,不規(guī)范的話就可能是火葬場(chǎng)了。下面我給大家舉個(gè)例子:

        // tailwind.config.js
        const colors = require('tailwindcss/colors')

        module.exports = {
          theme: {
            screens: {
              sm'480px',
              md'768px',
              lg'976px',
              xl'1440px',
            },
            colors: {
              gray: colors.coolGray,
              blue: colors.lightBlue,
              red: colors.rose,
              pink: colors.fuchsia,
            },
            fontFamily: {
              sans: ['Graphik''sans-serif'],
              serif: ['Merriweather''serif'],
            },
            extend: {
              spacing: {
                '128''32rem',
                '144''36rem',
              },
              borderRadius: {
                '4xl''2rem',
              }
            }
          }
        }

        以上是 tailwindcss 的主題配置文件,大家可以按照視覺(jué)的要求來(lái)做調(diào)整。比如說(shuō)今天視覺(jué)覺(jué)得屏幕的 lg 尺寸應(yīng)該是 976px,過(guò)段時(shí)間又覺(jué)得需要改成 1000px。對(duì)于開(kāi)發(fā)者而言我們只需要修改一行代碼就能全局生效了,很舒服。

        但是假如說(shuō)視覺(jué)原本定義的邊距規(guī)則如下:

        // tailwind.config.js
        module.exports = {
          theme: {
            spacing: {
              px'1px',
              0'0',
              0.5'0.125rem',
              1'0.25rem',
              1.5'0.375rem',
              2'0.5rem',
              2.5'0.625rem',
              3'0.75rem',
              3.5'0.875rem',
              4'1rem',
              5'1.25rem',
              6'1.5rem',
              7'1.75rem',
              8'2rem',
              // ...
            },
          }
        }

        現(xiàn)在需要我們把 6 換成 1.6rem,但是這個(gè)規(guī)則只需要作用在某些組件上,此時(shí)我們需要如何修改樣式?新增一個(gè) spacing 然后一個(gè)個(gè)去替換需要的地方么?

        上述場(chǎng)景筆者認(rèn)為還是不少見(jiàn)的,最起碼在我們公司內(nèi)部是存在這樣的問(wèn)題。已經(jīng)定義了視覺(jué)規(guī)范并體現(xiàn)在內(nèi)部的組件庫(kù)上,但是在業(yè)務(wù)中還是有不少視覺(jué)會(huì)去動(dòng)組件的基本樣式,這里改個(gè)邊距,那里改個(gè)顏色等等。原本組件庫(kù)是為了幫助開(kāi)發(fā)者提效的,但是在這種場(chǎng)景下開(kāi)發(fā)者反而會(huì)抱怨改動(dòng)樣式極大提高了他們的成本,并且大部分情況下還不得不這樣做。

        再說(shuō)回傳統(tǒng) CSS 的問(wèn)題,其實(shí) tailwindcss 也解決了一部分,但是仍舊存在沒(méi)解決的點(diǎn),比如說(shuō):

        • 死代碼問(wèn)題沒(méi)解決
        • 樣式表的插入順序依舊有影響

        以上說(shuō)了那么多,其實(shí)對(duì)于我們使用 tailwindcss 而言,有利也有弊。它肯定是存在很好用的場(chǎng)景的,比如說(shuō)寫個(gè)人的產(chǎn)品頁(yè),或者說(shuō)業(yè)務(wù)中樣式變化不頻繁的場(chǎng)景中,但是如果說(shuō)需要業(yè)務(wù)中全量切換到 tailwindcss 的話,筆者肯定是持保留態(tài)度的。

        對(duì)于 Atom CSS 來(lái)說(shuō),大家應(yīng)該是不能否認(rèn)它的優(yōu)點(diǎn)的,但是我們是否有辦法在盡可能避免它的缺點(diǎn)的情況下又獲得它的優(yōu)點(diǎn)呢?答案是有的,但是在講答案之前我想先來(lái)聊聊 CSS-in-JS。

        CSS-in-JS

        CSS-in-JS(下文以 CIJ 縮寫表示)核心就是在用 JS 寫 CSS,這同樣也是一個(gè)頗具爭(zhēng)議的技術(shù)方案。

        在這個(gè)領(lǐng)域下有兩個(gè)庫(kù)比較流行,分別為:styled-components(下文以 sc 縮寫表示) 以及 Emotion。筆者目前已經(jīng)用了一年多的 sc 了,來(lái)粗略談?wù)勊膬?yōu)缺點(diǎn)。

        我們先來(lái)了解下 sc 是怎么使用的。首先說(shuō)下 sc 和 Emotion 的語(yǔ)法是趨于一致的,應(yīng)該是為了 API 層面的統(tǒng)一吧,甚至前者還依賴了后者的一些包,以下是 sc 的常用寫法:

        const Button = styled.a`
          display: inline-block;

          ${props => props.primary && css`
            backgroundwhite;
            colorblack;
          `
        }

        `

        render(
          <div>
            <Button
              href="https://github.com/styled-components/styled-components"
              target="_blank"
              rel="noopener"
              primary
            >

              GitHub
            </Button>

            <Button as={Link} href="/docs">
              Documentation
            </Button>
          </div>

        )

        用法我們不多展開(kāi),有興趣的可以去官方看看,基本沒(méi)有學(xué)習(xí)成本的,主要是一些樣式組件上的使用。

        另外 sc 并不是最終生成了內(nèi)聯(lián)樣式,而是幫我們插入了 style 標(biāo)簽。

        優(yōu)劣點(diǎn)

        筆者用了一年多的 sc,感覺(jué)這種方案對(duì)于 React 來(lái)說(shuō)是很香的。并且解決了我很討厭的傳統(tǒng)寫 CSS 的一些點(diǎn),所以關(guān)于優(yōu)劣點(diǎn)這段的講述會(huì)有點(diǎn)主觀。

        首先 CSS-in-JS 這種方案不僅能讓我們完整使用到 CSS 的功能,而且還擴(kuò)充了一些用法。比如說(shuō)選擇器這塊,在 sc 中我們能通過(guò)選擇組件的方式來(lái)編寫樣式,如下代碼:

        const Button = styled.a`
          ${Icon} {
            color: green;
          }
        `

        另外既然我們通過(guò) JS 來(lái)管理 CSS 了,那么我們就可以充分享受 JS 帶來(lái)的工具鏈好處了。一旦項(xiàng)目中出現(xiàn)沒(méi)有使用到的樣式組件,那么 ESLint 就可以幫助我們找到那些死代碼并清除,這個(gè)功能對(duì)于大型項(xiàng)目來(lái)說(shuō)還是能減少一部分代碼體積的。

        除此之外,樣式污染、取名問(wèn)題、自動(dòng)添加前綴這些問(wèn)題也很好的解決了。

        除了以上這些,再來(lái)聊兩點(diǎn)不容易注意到的。

        首先是動(dòng)態(tài)切換主題。因?yàn)槲覀兪峭ㄟ^(guò) JS 來(lái)寫 CSS 了,那么我們就可以動(dòng)態(tài)地控制樣式。如果你的項(xiàng)目有切換主題這種類似的大量動(dòng)態(tài) CSS 的需求,那么這個(gè)方案會(huì)是一個(gè)不錯(cuò)的選擇。

        還有個(gè)點(diǎn)是按需加載。因?yàn)槲覀兪峭ㄟ^(guò) JS 寫的 CSS,現(xiàn)階段打包基本都走的 code split,那么就可以實(shí)現(xiàn) CSS 文件的按需加載,而不是傳統(tǒng)方式的一次性全部加載進(jìn)來(lái)(當(dāng)然也是可以優(yōu)化的,只是沒(méi)那么方便)。

        聊完了優(yōu)點(diǎn)我們?cè)賮?lái)說(shuō)說(shuō)缺點(diǎn)。

        第一個(gè)缺點(diǎn)很明顯,有學(xué)習(xí)成本,當(dāng)然筆者覺(jué)得這個(gè)學(xué)習(xí)曲線還是平緩的。

        運(yùn)行時(shí)成本,sc 本身就有文件體積,加上還需要?jiǎng)討B(tài)生成 CSS,那么這其中必定有性能上的損耗。項(xiàng)目越大影響的也會(huì)越大,如果你的項(xiàng)目對(duì)于性能有很高的要求,那么需要謹(jǐn)慎考慮使用。另外因?yàn)?CSS 動(dòng)態(tài)生成,所以不能像傳統(tǒng) CSS 一樣緩存 CSS 文件了。

        代碼復(fù)用性和傳統(tǒng)寫 CSS 的方式?jīng)]啥兩樣。

        最后點(diǎn)是代碼耦合問(wèn)題。會(huì)有人覺(jué)得在大型項(xiàng)目中將 CSS 及 JS 寫在一起會(huì)增加維護(hù)成本,并且也不符合 CSS 需要分離開(kāi)來(lái)想法。

        Atom CSS 加上 CSS-in-JS 的縫合怪

        看了上文,如果你覺(jué)得兩種方案都挺好的話,可以了解下 twin.macro,這個(gè)庫(kù)(還有別的競(jìng)品)把這兩種方案融合了起來(lái)。

        import 'twin.macro'

        const Input = () => <input tw="border hover:border-black" />
        const Input = tw.input`border hover:border-black`

        這種方案之上其實(shí)還有更好玩的方式,能幫助我們盡量取其精華而去其糟粕。

        自動(dòng)生成 Atom CSS 的 CSS-in-JS 方案

        假如說(shuō)我不僅想用 CSS-in-JS,還想把 Atom CSS 也給整上,但是又不想記 / 寫一大堆類名,我這個(gè)想法能實(shí)現(xiàn)么?

        答案是有的。利用運(yùn)行時(shí)的方式把單個(gè)樣式抽離出來(lái),最后實(shí)現(xiàn)雖然我們寫的是 CSS-in-JS,但是最終呈現(xiàn)的是 Atom CSS 的樣子。

        以 styletron 舉個(gè)例子,開(kāi)發(fā)時(shí)候的代碼長(zhǎng)這樣:

        import { styled } from "styletron-react";

        export default () => {
          // Create a styled component by passing
          // an element name and a style object
          const Anchor = styled("a", {
            fontSize"20px",
            color"red"
          });
          return <Anchor href="/getting-started">Start!</Anchor>;
        };

        實(shí)際編譯出來(lái)的時(shí)候長(zhǎng)這樣:

        <html>
          <head>
            <style>
              .foo {
                font-size20px;
              }
              .bar {
                color: red;
              }
            
        </style>
          </head>

          <body>
            <a href="/getting-started" class="foo bar">Start!</a>
          </body>

        </html>

        這樣的方式就能很好地享受到兩種方案帶來(lái)的好處了。但是這類方案筆者找了些競(jìng)品,覺(jué)得還沒(méi)有前兩者方案來(lái)的流行,大家了解一下即可。另外這種方式帶來(lái)的運(yùn)行時(shí)成本應(yīng)該會(huì)更大,也許可以配套打包工具在本地先做一次預(yù)編譯(一個(gè)不成熟的想法,說(shuō)錯(cuò)勿噴)?

        總結(jié)

        說(shuō)了那么多方案,可能讀者會(huì)有疑問(wèn),那么我到底該用啥?這里筆者說(shuō)下自己的想法。

        首先對(duì)于 sc 來(lái)說(shuō),筆者覺(jué)得很香,在項(xiàng)目中大范圍用起來(lái)未嘗不可,當(dāng)然我們還可以搭配著 Atom CSS 一起來(lái)寫通用樣式。

        對(duì)于 Atom CSS,筆者個(gè)人認(rèn)為不適合項(xiàng)目中大規(guī)模使用,起碼在我們公司內(nèi)部不會(huì)是一個(gè)好方案,畢竟視覺(jué)真的會(huì)來(lái)動(dòng)某些通用樣式。

        大家也可以來(lái)說(shuō)說(shuō)各自的看法。

        瀏覽 33
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            山村精品乱肉合集乱 | 亚洲综合成人视频 | 久久爽久久爽久久免费观看 | 宋佳双乳高耸呻吟不止 | 做爱视频无码免费网站 | 欧美老熟妇在线视频 | 黄色家庭乱伦视频 | 182午夜福利 | 亚洲九九九九 | 国精产品久久久久久九九九九 |