人人都用 Bootstrap 的年代過去了,如今我很難向開發者們推薦 Bootstrap 5

語言: CN / TW / HK

Bootstrap 5 和 Tailwind 相比簡直就是噩夢

我最近開始為開發人員編寫小教程。我的目標是向初級開發人員展示高級開發人員在編寫代碼時是如何思考的。例如,高級開發人員如何開始理解他們原先不瞭解的文檔或新框架,以及他們在出錯時(也就是著名的“代碼壞味道”)如何解決問題。

我在 Frontend Mentor 網站上找到了一些示例項目,並寫了各種各樣的代碼。例如,第一個項目是一個產品卡片組件,我決定使用普通的 CSS 和 Tailwind 以及 Bootstrap 來編寫解決方案。

這不僅對讀者來説很有趣,對我來説也很有趣。我想看看 Tailwind 和 Bootstrap 在過去幾年裏發展得怎樣。我知道 Tailwind 的開發者體驗會很棒,但我並不知道原來使用 Bootstrap 5 會如此痛苦。它很糟糕,所以我寫了這篇文章。

在本文中,你將看到歷史(主要是關於 Bootstrap)、想法(關於開發體驗)和代碼片段。讓我們先從歷史部分講起吧!

人人都用 Bootstrap 的年代

多年前,Bootstrap 無處不在。在 2016 年,你幾乎找不到一個沒有使用 Bootstrap 的網站。CSS Flexbox 已經有了,但 CSS Grid 還不為人所知,也沒有得到很好的支持。我記得在 2016 年中,我曾與一位開發人員談起 CSS Grid,我向他講述了它的強大功能,但他的回答令人感到震驚——他還以為我説的是 HTML 表格元素,可見他對 CSS Grid 一無所知。那時,所有人都依賴 Bootstrap 3,他們都還在使用 jQuery。

除了 Bootstrap,還有其他 CSS 框架。第二個最著名框架的是 Foundation。除了電子郵件模板,我使用 Foundation 的機會並不多。也許它比 Bootstrap 更好或更差或不同或相同,事實上,我真的不知道。

他們聲稱(現在在他們的 GitHub 頁面上仍然如此)自己是“世界上最先進的響應式前端框架”。但從他們的官方文檔和 GitHub 代碼庫來看,我覺得它已經死了。我不想在歷史方面花太多時間,只是想在繼續其他話題之前補充一些東西。

bonnegueule.fr——2016 年使用 Bootstrap 編寫的一個法國網站(來源:waybackmachine.com)

首先,Bootstrap 是由 Twitter 的工程師開發的,他們做得很好。Twitter 仍然在使用 Bootstrap,還有許多網站也是。大多數時候,即使你不是一個經驗豐富的開發人員,也可以很容易地判斷一個網站是否使用了 Bootstrap。但在我看來,這並不總是好事情,因為它會讓所有網站看起來都一個樣。

對於一些網站來説,這可能是一個優勢,因為用户不需要重新熟悉網站。例如,他們知道鏈接或提交按鈕是什麼樣子的。但是,在某些時候,你的網站失去了個性,依賴它就變成了一個劣勢。它的第二個優點是核心開發團隊決定在 Bootstrap 5 中移除 jQuery。我不知道這個決定是好是壞。今天,jQuery 沒有其他前端框架那麼受歡迎,開發人員也越來越少使用它,所以在某種程度上,這麼做是有意義的。

然而,移除 jQuery 增加了核心開發團隊的工作量,並且失去了對舊瀏覽器的一些兼容性。

最後要説聲“感謝”。Bootstrap 核心開發團隊在網頁可訪問性方面做得非常出色,尤其是 Bootstrap 4。他們引入了許多與 aria 屬性相關的概念,並提供了人們可以使用的具體示例和代碼示例。在我看來,Bootstrap 4 很棒!遺憾的是,Bootstrap 5 不是。

Tailwind 重塑編寫 CSS 的方式

與許多人一樣,我也是因為 Tailwind 才知道“實用優先 CSS(Utility-first CSS)”這個詞。在此之前,我一直在嘗試使用 BEM。我不知道你是怎麼想的,但我一直對 BEM 有種迷惘的感覺。我瞭解修飾符的概念,但是當我需要使用塊或元素時,會感到有點困惑。

理論上,按照這種方式構建 CSS 似乎是一個合理的想法。然而,它往往會污染 HTML 的可讀性。這裏有一篇文章( https://medium.com/@jescalan/bem-is-terrible-f421495d093a )介紹了這些概念。

讓我們回到 Tailwind 上來。為什麼説在開發“實用優先”CSS 框架時 Tailwind 向前邁出了一大步?如果你讀過前面我分享的那個文章資源,那麼你應該已經知道答案了。Tailwind 不像 Bootstrap 那樣依賴組件且一次應用多種樣式,相反,它添加只做一件事的類。換句話説,你編寫的類可以進行任意組合——一個類用於填充,另一個類用於控制字體大小,等等。

我們來舉個例子。

下面是使用 Bootstrap 編寫的卡片組件。

<div class="card" style="width: 18rem;">  <img src="..." class="card-img-top" alt="...">  <div class="card-body">    <h5 class="card-title">Card title</h5>    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>    <a href="#" class="btn btn-primary">Go somewhere</a>  </div></div>

複製代碼

結果看起來像這樣:

下面是使用 Tailwind 編寫的卡片組件。

<figure class="md:flex bg-slate-100 rounded-xl p-8 md:p-0 dark:bg-slate-800">  <img class="w-24 h-24 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-medium">        “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-sky-500 dark:text-sky-400">        Sarah Dayan      </div>      <div class="text-slate-700 dark:text-slate-500">        Staff Engineer, Algolia      </div>    </figcaption>  </div></figure>

複製代碼

結果看起來像這樣。

這兩張卡片看起來不一樣,但我希望你們看看代碼。在使用 Bootstrap 時,卡片組件可以在大小和顏色方面有所不同,但最終,它們或多或少看起來是一樣的。還記得我在本文開頭説的“即使你不是一個經驗豐富的開發人員,也可以很容易地判斷一個網站是否使用了 Bootstrap”嗎?

在使用 Tailwind 時,你幾乎可以把自定義樣式添加到任何東西上。你可能會問,這重要嗎?首先,因為它允許你按照你想要的方式設計網站,這就非常棒了,尤其是對設計師來説!其次,它可以幫助開發人員儘可能接近你想要的模型,並且不會破壞 HTML 標記和 CSS 之間的任何責任關係。

有了 Tailwind,你就不再需要依賴 BEM 了。對我來説,這真是個好消息!

開發者體驗和文檔

Tailwind——設置和使用都方便

那是我第一次使用 Tailwind。我的意思是,我之前就知道這個項目,並且已經閲讀了文檔,但還沒有機會使用它。對於這個項目,我決定不使用 CLI 或 PostCSS。

我決定使用 CDN。通過閲讀文檔得知,生產環境的網站不適合這麼做,但如果是出於試驗的目的是可以的。不過我還是驚訝地發現,即使使用了 CDN,仍然可以很簡單地添加自定義顏色和字體。

相比之下,Bootstrap API 則是一團糟。它的文檔和示例代碼都不容易看懂,尤其是如果你還不知道有版本 5。

我是這樣在項目中設置 Tailwind 的:

<script src="https://cdn.tailwindcss.com"></script>  <script>    tailwind.config = {      theme: {        extend: {          colors: {            viridian: 'hsl(158, 36%, 37%)',            dawnPink: 'hsl(30, 38%, 92%)',            white: 'hsl(0, 0%, 100%)',            ebonyClay: 'hsl(212, 21%, 14%)',            stormGray: 'hsl(228, 12%, 48%)'          },          fontFamily: {            montserrat: ['Montserrat', 'sans-serif'],            fraunces: ['Fraunces', 'serif']          }        }      }    }  </script>

複製代碼

在上面的代碼示例中,我在 tailwind.config 對象中添加了新的顏色和新的字體。

然後,我在代碼中使用它:

<p class="font-montserrat font-medium text-xs tracking-[.5em] uppercasetext-stormGray mb-3">  Perfume</p><h1 class="font-fraunces text-3xl font-bold text-ebonyClay mb-4">  Gabrielle Essence Eau de Parfum</h1><p class="font-montserrat font-medium text-sm text-stormGray mb-6">  A floral, solar and voluptuous interpretation composed by Olivier Polge,  Perfumer-Creator for the House of CHANEL.</p>

複製代碼

看,這很容易!我不需要寫自定義 CSS 或 Sass 代碼,我只需要調用正確的類就可以了。它真的非常簡單,但卻很強大!

Tailwind——多麼好的文檔

這就引出了 Tailwind 的第二個優勢——文檔。我是一名開發人員(我想你也是),大多數時候,當我們忙於一個項目時,根本沒有時間閲讀整個文檔。我們需要可以直接使用或重用的簡單但具體的示例。

我們想看看 Tailwind 是否是一個對的工具,我們想很快得出結論。在過去的幾年裏,我對開發者體驗(簡稱 DX)越來越感興趣。以下是我在網上找到的一個有關 DX 的定義:

開發者體驗是指與 API 或開發工具相關的每一次交互。

—— 來源: https://everydeveloper.com/developer-experience/

關於交互,不要只考慮代碼註釋、變量名或遵循約定,我們還要考慮文檔,以及使用庫或框架的容易程度。

例如,我認為 Symfony 和 Angular 的開發者體驗就很棒。它們提供了教程、優秀的文檔和代碼示例。但還有更多的東西!當你開始使用它們時,你也會學到其他概念。例如,Symfony 文檔解釋了實體和存儲庫模式的概念。Angular 告訴我們什麼是 Promise 和 Observable。

相反,React 的文檔就算不上出色。它們都沒有解釋如何編寫有效的測試,甚至關於 Hook 都沒有提供足夠的信息。大多數時候,當我與開發人員談及 React Hook 時,他們並不瞭解它們的工作原理。所以説,DX 很重要,比你想象的更重要。它可以讓一個項目成功,也可以讓它失敗。有了 Tailwind,我一個下午就能完成這個項目。文檔應該易於閲讀和使用,框架也是。那麼,Bootstrap 5 怎麼樣?

Bootstrap——組件和 Utility 的混合

當我在寫這篇文章時,我不確定我是想先討論 Utility API 還是組件和 Utility 之間的模糊邊界。

退一步來看,我認為這兩個問題是相關的,從組件和 Utility 開始討論可能會更有意義。

Bootstrap 從一開始都是關於組件,有表單組件、輪播組件(即使你不應該使用它)、麪包屑組件、模態組件,等等。這些是(還是曾經是?)Bootstrap 最大的優勢。

如果我想要一個標題呢?我在“Content”部分的“Typography”頁面可以找到關於 heading、display 和 lead 類的信息。

這太棒了!但是“Utilities”部分的“Text”頁面呢,尤其是“Font size”部分呢?這是另一種改變字體大小的方式。那麼我應該用哪一種呢?我可以把它們結合起來使用嗎?框架想讓我怎麼做?這些都是我在編寫代碼時問自己的問題。

Bootstrap 給我的印象是它位於兩把椅子之間,不知道該坐哪一邊。一方面,他們希望你堅持使用 Bootstrap 及其組件庫,因為核心開發團隊投入了大量時間和精力。另一方面,他們引入了 Utility 及其 API,但文檔裏又沒有給出很多示例。

Bootstrap Utility API——理解它需要一些時間

幾天前,我正在為產品組件編寫 Bootstrap 解決方案,並創建了不使用 Bootstrap Utility 的類。

我想給一個元素添加 90%的寬度。我查看了文檔,在“Utilities”部分找到了“Sizing”頁面。默認寬度為 25%、50%、75%和 100%。我先創建了一個叫作 w-90 的自定義寬度,表示 90%,但我知道有些地方出錯了。

這又是代碼的壞味道!我快速查看了 Utility API 頁面,並認為已經理解了。我必須在項目中安裝 Sass 和 Bootstrap 才能使用這個 API。

我安裝好了,然後跳到“Customize”部分的“Sass”頁面,發現我可以做出一個選擇——要麼導入 Bootstrap 所有的東西,但不能修改 Utility,要麼手動導入你需要的東西。

// Custom.scss// Option B: Include parts of Bootstrap

// 1. Include functions first (so you can manipulate colors, SVGs, calc, etc)@import "../node_modules/bootstrap/scss/functions";

// 2. Include any default variable overrides here

// 3. Include remainder of required Bootstrap stylesheets@import "../node_modules/bootstrap/scss/variables";

// 4. Include any default map overrides here

// 5. Include remainder of required parts@import "../node_modules/bootstrap/scss/maps";@import "../node_modules/bootstrap/scss/mixins";@import "../node_modules/bootstrap/scss/root";

// 6. Optionally include any other parts as needed@import "../node_modules/bootstrap/scss/utilities";@import "../node_modules/bootstrap/scss/reboot";@import "../node_modules/bootstrap/scss/type";@import "../node_modules/bootstrap/scss/images";@import "../node_modules/bootstrap/scss/containers";@import "../node_modules/bootstrap/scss/grid";@import "../node_modules/bootstrap/scss/helpers";

// 7. Optionally include utilities API last to generate classes based on the Sass map in `_utilities.scss`@import "../node_modules/bootstrap/scss/utilities/api";

// 8. Add additional custom code here

複製代碼

然後我修改了 Utility(下面將向你展示是如何修改的),並將 Sass 編譯為 CSS。乍一看似乎沒問題,但我很快發現按鈕沒有了樣式。原來我忘記導入一些東西了,看看第 19 行到 26 行就知道了。

註釋寫着“根據需要導入其他部分”,但我是從 Bootstrap 5 開始的,我不知道哪些是需要的,哪些是不需要的。還記得我講的 DX 嗎?對我來説,這就是糟糕的 DX!因為即使是簡單的複製和粘貼,你也找不到一個能用的例子。這很令人沮喪,也不會給人留下什麼好印象。

下面是我修改的東西。

// Include any default variable overrides here (though functions won't be available)// Custom variables$viridian: hsl(158, 36%, 37%);$dawn-pink: hsl(30, 38%, 92%);$white: hsl(0, 0%, 100%);$ebony-clay: hsl(212, 21%, 14%);$storm-gray: hsl(228, 12%, 48%);

$font-montserrat: 'Montserrat', sans-serif;$font-fraunces: 'Fraunces', serif;

// Configuration@import "../node_modules/bootstrap/scss/functions";



// 2. Include any default variable overrides here$body-bg: $dawn-pink;$font-weight-normal: 500;



@import "../node_modules/bootstrap/scss/variables";

// 4. Include any default map overrides here$custom-colors: ( "viridian": $viridian, "dawn-pink": $dawn-pink, "white": $white, "ebony-clay": $ebony-clay, "storm-gray": $storm-gray);

// Merge the maps$theme-colors: map-merge($theme-colors, $custom-colors);



@import "../node_modules/bootstrap/scss/maps";@import "../node_modules/bootstrap/scss/mixins";@import "../node_modules/bootstrap/scss/utilities";

// Layout & components@import "../node_modules/bootstrap/scss/root";@import "../node_modules/bootstrap/scss/reboot";@import "../node_modules/bootstrap/scss/type";@import "../node_modules/bootstrap/scss/images";@import "../node_modules/bootstrap/scss/containers";@import "../node_modules/bootstrap/scss/grid";@import "../node_modules/bootstrap/scss/buttons";



// Import we don't need@import "../node_modules/bootstrap/scss/tables";@import "../node_modules/bootstrap/scss/forms";@import "../node_modules/bootstrap/scss/transitions";@import "../node_modules/bootstrap/scss/dropdown";@import "../node_modules/bootstrap/scss/button-group";@import "../node_modules/bootstrap/scss/nav";@import "../node_modules/bootstrap/scss/navbar";@import "../node_modules/bootstrap/scss/card";@import "../node_modules/bootstrap/scss/accordion";@import "../node_modules/bootstrap/scss/breadcrumb";@import "../node_modules/bootstrap/scss/pagination";@import "../node_modules/bootstrap/scss/badge";@import "../node_modules/bootstrap/scss/alert";@import "../node_modules/bootstrap/scss/progress";@import "../node_modules/bootstrap/scss/list-group";@import "../node_modules/bootstrap/scss/close";@import "../node_modules/bootstrap/scss/toasts";@import "../node_modules/bootstrap/scss/modal";@import "../node_modules/bootstrap/scss/tooltip";@import "../node_modules/bootstrap/scss/popover";@import "../node_modules/bootstrap/scss/carousel";@import "../node_modules/bootstrap/scss/spinners";@import "../node_modules/bootstrap/scss/offcanvas";@import "../node_modules/bootstrap/scss/placeholders";

// Helpers@import "../node_modules/bootstrap/scss/helpers";



$utilities: map-merge( $utilities, ( "width": map-merge( map-get($utilities, "width"), ( values: map-merge( map-get(map-get($utilities, "width"), "values"), (90: 90%), ), ), ), "max-width": map-merge( map-get($utilities, "max-width"), ( values: map-merge( map-get(map-get($utilities, "max-width"), "values"), (600: 680px), ), ), ), "font-family": map-merge( map-get($utilities, "font-family"), ( values: map-merge( map-get(map-get($utilities, "font-family"), "values"), ( montserrat: $font-montserrat, fraunces: $font-fraunces ), ), ), ), "letter-spacing": ( property: letter-spacing, class: lt, responsive: true, values: ( 0: 0px, 5: 5px, 10: 10px ) ) ));

// Utilities@import "../node_modules/bootstrap/scss/utilities/api";

.max-w { max-width: 300px;}

複製代碼

我導入了所有東西,甚至是我(還)不需要的部分,然後我加了一個註釋告訴自己(未來的自己)我不需要它們。

我多麼希望能有一個具體的例子。最後,我終於能夠添加新的 Utility 了。是的,這確實有點乏味。在下面的兩個小節中,你將看到幾個例子,關於如何在 Bootstrap 和 Tailwind 中導入和使用自定義字體以及如何添加新的寬度。我想有些人很希望能夠看到具體的例子!

如何導入自定義字體

Tailwind

首先,導入字體。我使用的是谷歌字體。

<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,[email protected],700&family=Montserrat:wght@500;700&display=swap"rel="stylesheet">

複製代碼

然後,從 CDN 導入 Tailwind 並更新 tailwind.config 對象。我添加了備用字體和新的顏色。

  <script src="https://cdn.tailwindcss.com"></script>  <script>    tailwind.config = {      theme: {        extend: {          colors: {            viridian: 'hsl(158, 36%, 37%)',            dawnPink: 'hsl(30, 38%, 92%)',            white: 'hsl(0, 0%, 100%)',            ebonyClay: 'hsl(212, 21%, 14%)',            stormGray: 'hsl(228, 12%, 48%)'          },          fontFamily: {            montserrat: ['Montserrat', 'sans-serif'],            fraunces: ['Fraunces', 'serif']          }        }      }    }  </script>

複製代碼

最後,使用它!

<span class="text-white font-montserrat font-bold text-sm">  Add to Cart</span>

複製代碼

很簡單,對吧?

Bootstrap

通過 npm 安裝 Saas。

{  "dependencies": {    "bootstrap": "^5.2.0",    "sass": "^1.53.0"  },  "scripts": {    "sass": "node_modules/.bin/sass scss/main.scss css/main.css --watch"  }}

複製代碼

通過 Sass 添加 Bootstrap 並導入 Bootstrap 所有的東西。

然後,你就可以去掉你不想要的部分。

在第 9 行和第 10 行之間,我定義了 Sass 變量。我在第 102 行和第 113 行之間修改了 font-family Utility。

// Include any default variable overrides here (though functions won't be available)// Custom variables$viridian: hsl(158, 36%, 37%);$dawn-pink: hsl(30, 38%, 92%);$white: hsl(0, 0%, 100%);$ebony-clay: hsl(212, 21%, 14%);$storm-gray: hsl(228, 12%, 48%);

$font-montserrat: 'Montserrat', sans-serif;$font-fraunces: 'Fraunces', serif;

// Configuration@import "../node_modules/bootstrap/scss/functions";



// 2. Include any default variable overrides here$body-bg: $dawn-pink;$font-weight-normal: 500;



@import "../node_modules/bootstrap/scss/variables";

// 4. Include any default map overrides here$custom-colors: ( "viridian": $viridian, "dawn-pink": $dawn-pink, "white": $white, "ebony-clay": $ebony-clay, "storm-gray": $storm-gray);

// Merge the maps$theme-colors: map-merge($theme-colors, $custom-colors);



@import "../node_modules/bootstrap/scss/maps";@import "../node_modules/bootstrap/scss/mixins";@import "../node_modules/bootstrap/scss/utilities";

// Layout & components@import "../node_modules/bootstrap/scss/root";@import "../node_modules/bootstrap/scss/reboot";@import "../node_modules/bootstrap/scss/type";@import "../node_modules/bootstrap/scss/images";@import "../node_modules/bootstrap/scss/containers";@import "../node_modules/bootstrap/scss/grid";@import "../node_modules/bootstrap/scss/buttons";



// Import we don't needimport "../node_modules/bootstrap/scss/tables";@import "../node_modules/bootstrap/scss/forms";@import "../node_modules/bootstrap/scss/transitions";@import "../node_modules/bootstrap/scss/dropdown";@import "../node_modules/bootstrap/scss/button-group";@import "../node_modules/bootstrap/scss/nav";@import "../node_modules/bootstrap/scss/navbar";@import "../node_modules/bootstrap/scss/card";@import "../node_modules/bootstrap/scss/accordion";@import "../node_modules/bootstrap/scss/breadcrumb";@import "../node_modules/bootstrap/scss/pagination";@import "../node_modules/bootstrap/scss/badge";@import "../node_modules/bootstrap/scss/alert";@import "../node_modules/bootstrap/scss/progress";@import "../node_modules/bootstrap/scss/list-group";@import "../node_modules/bootstrap/scss/close";@import "../node_modules/bootstrap/scss/toasts";@import "../node_modules/bootstrap/scss/modal";@import "../node_modules/bootstrap/scss/tooltip";@import "../node_modules/bootstrap/scss/popover";@import "../node_modules/bootstrap/scss/carousel";@import "../node_modules/bootstrap/scss/spinners";@import "../node_modules/bootstrap/scss/offcanvas";@import "../node_modules/bootstrap/scss/placeholders";

// Helpers@import "../node_modules/bootstrap/scss/helpers";



$utilities: map-merge( $utilities, ( "width": map-merge( map-get($utilities, "width"), ( values: map-merge( map-get(map-get($utilities, "width"), "values"), (90: 90%), ), ), ), "max-width": map-merge( map-get($utilities, "max-width"), ( values: map-merge( map-get(map-get($utilities, "max-width"), "values"), (600: 680px), ), ), ), "font-family": map-merge( map-get($utilities, "font-family"), ( values: map-merge( map-get(map-get($utilities, "font-family"), "values"), ( montserrat: $font-montserrat, fraunces: $font-fraunces ), ), ), ), "letter-spacing": ( property: letter-spacing, class: lt, responsive: true, values: ( 0: 0px, 5: 5px, 10: 10px ) ) ));

// Utilities@import "../node_modules/bootstrap/scss/utilities/api";

.max-w { max-width: 300px;}

複製代碼

然後,我在 HTML 文件中使用它,如下所示:

<p class="text-uppercase text-storm-gray font-montserrat fw-normal lt-5">Perfume</p>

複製代碼

如何添加 letter-spacing 屬性

Tailwind

用下面的代碼導入 Tailwind:

<script src="https://cdn.tailwindcss.com"></script>

複製代碼

使用自定義的 Tailwind 類,如 tracking-[.5em]。

<p class="font-montserrat font-medium text-xs tracking-[.5em] uppercase text-stormGray mb-3">Perfume</p>

複製代碼

就是這麼簡單!

Bootstrap

與上面一樣,我通過 Npm 安裝 Bootstrap 和 Sass。

然後,我修改了 Utility。請看第 34 行。我創建了一個新的 Utility,它使用了 lt 類,有三個值。

$utilities: map-merge(  $utilities,  (    "width": map-merge(      map-get($utilities, "width"),      (        values: map-merge(          map-get(map-get($utilities, "width"), "values"),          (90: 90%),        ),      ),    ),    "max-width": map-merge(      map-get($utilities, "max-width"),      (        values: map-merge(          map-get(map-get($utilities, "max-width"), "values"),          (600: 680px),        ),      ),    ),    "font-family": map-merge(      map-get($utilities, "font-family"),      (        values: map-merge(          map-get(map-get($utilities, "font-family"), "values"),          (            montserrat: $font-montserrat,            fraunces: $font-fraunces          ),        ),      ),    ),    "letter-spacing": (      property: letter-spacing,      class: lt,      responsive: true,      values: (        0: 0px,        5: 5px,        10: 10px      )    )  ));

複製代碼

最後是使用它:

<p class="text-uppercase text-storm-gray font-montserrat fw-normal lt-5">Perfume</p>

複製代碼

這是一篇很長的文章,比我剛開始寫的時候預期的要長。在文章結束之前,我想告訴你們一些關於 Bootstrap 的事情。Bootstrap 3 和 Bootstrap 4 會好一些,但 Bootstrap 5 不是很好,特別是在文檔和開發者體驗方面。

我感覺 Bootstrap 正在衰落。它還沒有消亡,但核心開發團隊似乎迷失了願景,不知道要去到哪裏。也許我是錯的,但畢竟 Bootstrap 在 React 和全域 SPA 之前就已經出現了。

它在過去、現在都可以與全棧式框架結合使用,但不包括 React,至少在我看來是這樣。也許在幾年後,我們會重新迴歸,但在今天,我似乎很難向初級或高級開發人員推薦 Bootstrap。

原文鏈接: