iT邦幫忙

2022 iThome 鐵人賽

DAY 2
1
自我挑戰組

掌握 Master CSS 優化開發體驗系列 第 2

Day 02 - 避免過早抽象化

  • 分享至 

  • xImage
  •  

過早抽象化

在開發網頁的時候,我們習慣為元素命名以設置元素樣式,這是導致過早抽象化的主因。
以下方卡片為例:
https://ithelp.ithome.com.tw/upload/images/20220915/20103817i7Tby0RTBd.png

  1. 為了設置卡片的樣式,我們需要 "花費時間" 為元素命名(個人偏好使用 BEM 設計模式)。
<div class="card">
  <img class="card__image" src="/images/mountain.jpg" alt="Mountain" />
  <div class="card__body">
    <h2 class="card__title">Mountain</h2>
    <p class="card__text">A mountain is an elevated portion of the Earth's crust, generally with steep sides that show significant exposed bedrock.</p>
  </div>
</div>
  1. 建立一支 _card.scss 以撰寫卡片的樣式。
// components/_card.scss
.card {
  ...
}
  1. 引入 _card.scss 到主要的 all.scss
// all.scss
@import "components/card";
  1. 上面的做法看起來沒什麼問題對吧?此時出現了另一種卡片風格,問題就會開始慢慢浮現:

https://ithelp.ithome.com.tw/upload/images/20220915/20103817vFjzCAdzoS.png

  • 新的卡片該如何命名?
  • .card 被使用過了嗎?
  • 兩張卡片風格差不多,稍微修改一下就好了吧?但會不會愈改愈髒?
  • 兩張卡片風格有落差,無法重用。
  • 之後又有新的卡片風格出現怎麼辦?
  • 花費大量的時間在 HTML、CSS 來回編輯 / 對照。
  • 最終陷入命名及編寫樣式的困境。

可以發現,一個卡片元件就能衍生如此多的問題,而一個網頁可能包含數十個元件。
這邊並不是反對 .card 這種抽象化寫法,假如是 "具有重用潛力" 的樣式,那仍然建議將其抽象化命名以簡化程式碼。

Master CSS 解決了什麼?

讓我們試著以 Master CSS 來撰寫上方的卡片。

https://ithelp.ithome.com.tw/upload/images/20220915/20103817DPzOy6BSU9.png

首先,卡片的最大寬度是 360px,我們需要 max-width 這個屬性,轉換成 Master CSS 的語法為 max-w:360,前面的 max-w 是屬性,: 冒號後面的 360 是單位。

<div class="max-w:360"></div>
.max-w\:360 {
  max-width: 22.5rem;
}

接著卡片是白色底、圓角 10px、超出的地方要裁切,需要 background-colorborder-radiusoverflow 這三個屬性,白色底轉換成 bg:white,圓角 10px 轉換成 r:10、超出裁切轉換成 overflow:hidden

<div class="max-w:360">
  <div class="bg:white r:10 overflow:hidden"></div>
</div>
.bg\:white {
  background-color: rgb(255, 255, 255);
}

.r\:10 {
  border-radius: 0.625rem;
}

.overflow\:hidden {
  overflow: hidden;
}

卡片的陰影是透明度 8% 的黑色、向下偏移 10px、模糊值 20px,需要 box-shadow 這個屬性,轉換成 shadow:0|10|20|black/.08

<div class="max-w:360">
  <div class="bg:white r:10 overflow:hidden shadow:0|10|20|black/.08"></div>
</div>
.shadow\:0\|10\|20\|black\/\.08 {
  box-shadow: rgb(0 0 0 / 8%) 0rem 0.625rem 1.25rem;
}

圖片稱滿卡片的寬度,需要 width 這個屬性,轉換成 w:full

<div class="max-w:360">
  <div class="bg:white r:10 overflow:hidden shadow:0|10|20|black/.08">
    <img
	  class="w:full"
	  src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1176&q=80"
	  alt="Mountain"
	/>
  </div>
</div>
.w\:full {
  width: 100%;
}

卡片的內距是上 24px、左右 24px、下 32px,需要 padding 這個屬性,Master CSS 的寫法非常地自由。

  1. 分別推上 pt:24、右 pr:24、下 pb:32、左 pl:24
  2. 語法糖速記 p:24|24|32|24,對應的方向分別是上 | 右 | 下 | 左。
  3. 再精簡 p:24|24|32,對應的方向分別是上 | 左右 | 下。
  4. 統一推 24px p:24,下面推 32px 覆蓋 pb:32
<div class="max-w:360">
  <div class="bg:white r:10 overflow:hidden shadow:0|10|20|black/.08">
    <img
	  class="w:full"
	  src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1176&q=80"
	  alt="Mountain"
	/>
    <!-- 方法一:針對不同方向分別給予數值 -->
    <div class="pt:24 pr:24 pb:32 pl:24"></div>
	<!-- 方法二:使用縮寫 => 上|右|下|左 -->
	<div class="p:24|24|32|24"></div>
	<!-- 方法三:使用縮寫 => 上|左右|下 -->
	<div class="p:24|24|32"></div>
	<!-- 方法四:統一推24px,下面推32px覆蓋 -->
	<div class="p:24 pb:32"></div>
  </div>
</div>
.p\:24\|24\|32 {
  padding: 1.5rem 1.5rem 2rem;
}

標題大小 24px、文字粗細 medium、文字顏色 #222、行高 1.25,需要 font-sizefont-weightfont-colorline-height 這四個屬性。

<div class="max-w:360">
  <div class="bg:white r:10 overflow:hidden shadow:0|10|20|black/.08">
    <img
	  class="w:full"
	  src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1176&q=80"
	  alt="Mountain"
	/>
    <div class="p:24|24|32">
      <h2 class="f:24 f:medium f:#222 lh:1.25">Mountain</h2>
    </div>
  </div>
</div>
.f\:24 {
  font-size: 1.5rem;
}

.f\:medium {
  font-weight: 500;
}

.f\:\#222 {
  color: rgb(34, 34, 34);
}

.lh\:1\.25 {
  line-height: 1.25;
}

最後是描述大小 16px(文字預設就是 16px,不需要特別做設定)、文字顏色 #666、行高 1.5、距離上方標題 8px,需要 font-colorline-heightmargin 這三個屬性。

<div class="max-w:360">
  <div class="bg:white r:10 overflow:hidden shadow:0|10|20|black/.08">
    <img
	  class="w:full"
	  src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1176&q=80"
	  alt="Mountain"
	/>
    <div class="p:24|24|32">
      <h2 class="f:24 f:medium f:#222 lh:1.25">Mountain</h2>
      <p class="f:#666 lh:1.5 mt:8">A mountain is an elevated portion of the Earth's crust, generally with steep sides that show significant exposed bedrock.</p>
    </div>
  </div>
</div>
.f\:\#666 {
  color: rgb(102, 102, 102);
}

.lh\:1\.5 {
  line-height: 1.5;
}

.mt\:8 {
  margin-top: 0.5rem;
}

最終我們完成了這一張卡片,可以發現 Master CSS 具有以下優勢:

  • 完全沒有把時間花費在抽象化命名。
  • 全程專注在 HTML 架構上面,沒有寫到任何的 CSS。
  • 針對設計稿給予相對應的類名,就能快速建構出用戶介面。
  • 使用具結構化的語言扁平地表達元素的樣式。
  • 不再盲目地將樣式分散在 CSS 檔案,協作人員能更快上手專案。

總結

本日 codepen 連結

這個單元用了一張卡片的案例讓大家快速地了解 Master CSS 是如何應用的。
後續的單元也會以這種切版案例的形式來讓大家逐漸熟悉 Master CSS。

參考


上一篇
Day 01 - 什麼是 Master CSS?
下一篇
Day 03 - 為何不寫行內樣式就好了?
系列文
掌握 Master CSS 優化開發體驗30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言