剛開始寫 CSS 時,我們都知道要有意義的命名,但即使命名都有自己的意義,卻發現選擇器之間有很多重複的屬性,完成第一份作業後,就有問彭彭老師,老師就提到選擇器的命名規則是滿值得討論的議題,並讓我查詢「css bem naming」,我就開始調查,CSS 怎麼樣才是好命名,並查學習一些常見網頁的命名方式。

  • 重要的命名觀念
  • BEM
  • KKBOX 的導覽列分解
  • KKBOX 的導覽列總結
  • 參考資料

重要的命名觀念

  1. 抽象化命名,例如: left 就只能放在左邊,改為 aside 就可以放在左右
  2. 避免針對性命名,例如: 作業的歡迎橫幅 welcome,可以改為 banner 內容就不一定是歡迎
  3. 狀態命名,例如: 導航欄連結在當前頁面狀態 menu-item 加上 is-active,其他頁面則只有 menu-item

BEM

Block Element Modifier (BEM) 是一種為了讓 CSS 類別更好維護的命名方式

  1. Block 區塊 .block {}

    主要負責描述大範圍功能,例如 headercontainer

  2. Element 元素 .block__element {}

    區塊的小部分,區塊可以不包含元素,但元素一定要包含在區塊,用於表達目的,中間用雙底線連結
    例如 list__itemnavbar__toggler

  3. Modifier 修飾器 .block__element--modifier {}

    區塊或元素的狀態,同一個區塊或元素可能有多種狀態,使用修飾器表達,中間用雙中線連結
    例如 nav__item--activestar--activestar--inactive

KKBOX 的導覽列分解

  1. KKBOX 導覽列分為兩個選擇器,並在寬度 1024 切換

    Mobile Desktop
    0 ~ 1024 display: flex display: none
    1024 ~ display: none display: flex
    1
    2
    3
    pm-header
    ├─ pm-mobile-header
    └─ pm-desktop-header
    pm-header
    圖1 pm-header
    pm-desktop-header
    圖2 pm-desktop-header
    pm-mobile-header
    圖3 pm-mobile-header
  2. 桌面版本裡面的 pm-container 有兩個區塊,位於旁邊的 pm-header-aside,和位於另一端的 pm-header-menu

    1
    2
    3
    4
    5
    6
    pm-header
    ├─ pm-mobile-header
    └─ pm-desktop-header
    └─ pm-container*
    ├─ pm-header-aside*
    └─ pm-header-menu*
    pm-container
    圖4 pm-container
    pm-header-aside
    圖5 pm-header-aside
    pm-header-menu
    圖6 pm-header-menu
  3. 在旁邊的 pm-header-aside 裡面只有一個 pm-logo

    1
    2
    3
    4
    5
    6
    7
    pm-header
    ├─ pm-mobile-header
    └─ pm-desktop-header
    └─ pm-container-menu
    ├─ pm-header-aside
    | └─ pm-logo*
    └─ pm-header-menu
    pm-logo
    圖7 pm-logo
  4. 而 pm-header-menu 包含的東西就比要多,有 pm-drop-down、pm-search-button 和普通的 a

    • pm-drop-down: 下拉式選單,例如: 特色功能、娛樂情報等
    • pm-search-button: 搜尋按鈕
    • a: 非下拉式選單,例如: 訂閱方案和下載
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    pm-header
    ├─ pm-mobile-header
    └─ pm-desktop-header
    └─ pm-container-menu
    ├─ pm-header-aside
    | └─ pm-logo
    └─ pm-header-menu
    ├─ pm-drop-down*
    ├─ pm-search-button*
    └─ a*
    pm-drop-down
    圖8 pm-drop-down
    pm-search-button
    圖9 pm-search-button
    pm-normal pm-download
    圖10 普通的 a
  5. 利用狀態顯示顏色,像是搜尋按鈕和下載都是藍色,使用選擇器 pm-highlight

    pm-search-button
    圖11 帶有 pm-highlight 的 pm-search-button
    pm-download
    圖12 帶有 pm-highlight 的 a
  6. 接下來介紹 pm-mobile-header,裡面都是圖片 pm-menu-icon、pm-search-icon、pm-logo
    其中 pm-logo 是 mobile 和 desktop 共用選擇器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    pm-header
    ├─ pm-mobile-header
    | ├─ pm-menu-icon*
    | ├─ pm-search-icon*
    | └─ pm-logo*
    └─ pm-desktop-header
    └─ pm-container-menu
    ├─ pm-header-aside
    | └─ pm-logo
    └─ pm-header-menu
    ├─ pm-drop-down
    ├─ pm-search-button
    └─ a
    pm-menu-icon
    圖13 pm-menu-icon
    pm-search-icon
    圖14 pm-search-icon
    pm-logo-m
    圖15 pm-logo
  7. 最後,當 pm-menu-icon 和 pm-search-icon 被點擊都會展開左或右側的菜單,所以他們都有狀態 pm-active,
    這個狀態將背景圖片都改為叉叉,複寫原本的選單或放大鏡

    pm-menu-icon-active
    圖16 帶有 pm-active 的 pm-menu-icon
    pm-search-icon-active
    圖17 帶有 pm-active 的 pm-search-icon

KKBOX 的導覽列總結

用 BEM 角度看 KKBOX 的導覽列,從中看到 Block 中都是可被單一重複使用,Element 需要依賴在特定 Block 之下,Modifier 則可以直接附加在 Block 或 Element

  • Block: pm-header、pm-menu-icon、pm-search-icon、pm-logo、pm-drop-down、pm-search-button
  • Element
    • pm-header 的 element: pm-mobile-header、pm-desktop-header
    • pm-desktop-header 的 element: pm-header-aside、pm-header-menu
  • Modifier: pm-highlight、pm-active

參考資料