人人都用 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:[email protected];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。

原文連結: