設計DOM&CSS

hailx發表於2018-09-02

本文內容主要是個人工作的總結,當然也是對他人優秀方案的借鑑

進行頁面重構時我們的主要工具手段是DOM標籤,如:沒有語義的DIV和有語義的SECTION。我們應該如何有效的管理繁雜的標籤巢狀和使用語義化標籤,這是本文的內容。

為了幫助說明設計demo來自這個網站,設計師@果汁

一,觀察設計圖

設計DOM&CSS

無論是這個demo網站的設計又或者是其它任何型別網站的設計,開始重構前做以下分析:

  • 一個頁面可以根據要展示的內容被區分為多個獨立的展示塊
    • 頭部展示塊
    • banner展示塊
    • xx內容展示塊
    • 底部展示塊
  • 每個展示塊同樣會限定資訊展示區域。
    • 全屏風格(100%寬)——資訊展示區為全屏;
    • 限定寬度(980px寬、1200px寬)——資訊展示區為指定的寬度
  • 資訊展示區佈局樣式——通常為居中佈局
  • 劃分好資訊展示區就需要對資訊展示區進行內容填充,考慮到展示資訊的多樣性我們需要對展示區進行佈局規劃
    • 兩欄佈局
    • 三欄佈局
    • 兩欄自適應佈局
    • 其它。。。
  • 內容模組——完成了資訊展示區的佈局設計,現在頁面整體框架的框架已經呈現在我們的面前(看下圖)只需填充內容模組
    設計DOM&CSS

二,頁面分析完成之後的DOM設計(設計方案)

拿到設計稿根據上面的分析思路我們可以得到:

1,展示塊

根據要展示的內容劃分展示塊,圖中紅框表示我們對展示塊的劃分

設計DOM&CSS

// 現在我們DOM結構應該如下
<!DOCTYPE html>
<html>
  <head>
    <title>demo</title>
  </head>
  <body>
    <!-- 內容展示塊 -->
    <div class="block-head"></div>
    <div class="block-nav"></div>
    <div class="block-banner"></div>
    <div class="block-service"></div>
    <div class="block-global"></div>
  </body>
</html>
複製程式碼

2,限定資訊展示區域

圖中我用黃色框表示出這個頁面每個內容展示塊中的資訊展示區域

設計DOM&CSS

<!-- 現在我們的DOM結構如下 -->
<!DOCTYPE html>
<html>
  <head>
    <title>demo</title>
  </head>
  <body>
    <!-- 同下 -->
    <div class="block-serivce">
      <!-- .g-container控制展示區域的大小和定位 -->
      <div class="g-container"></div>
    </div>
    <!-- 同上 -->
  </body>
</html>
複製程式碼

3,資訊展示區佈局樣式

增加我們的CSS實現

<!-- 現在我們的DOM結構如下 -->
<!DOCTYPE html>
<html>
  <head>
    <title>demo</title>
    <style type="text/css">
      .g-container{
        width: 1200px;
        margin: auto;
      }
    </style>
  </head>
  <body>
    ...
  </body>
</html>
複製程式碼

4,展示區進行佈局規劃

圖中我用綠色框表示對資訊展示區的佈局規劃。(以demo設計圖中我們的服務這個內容展示塊為例)
我們的服務可以被設計成成三行:

  • 第一行標題內容——單列;
  • 第二行服務介紹——三列;
  • 第三行服務介紹——三列

設計DOM&CSS


.g-row表示行佈局,.g-col-*表示列布局


<!-- 現在我們的DOM結構如下 -->
<!DOCTYPE html>
<html>
  <head>
    <title>demo</title>
    <style type="text/css">
      .g-container{
        width: 1200px;
        margin: auto;
      }
    </style>
  </head>
  <body>
    ...
    <div class="block-service">
      <div class="g-container">
        <!-- 第一行 -->
        <div class="g-row">我們的服務</div>
        <!-- 第二行 -->
        <div class="g-row">
          <div class="g-col-4"></div>
          <div class="g-col-4"></div>
          <div class="g-col-4"></div>
        </div>
        <!-- 第三行 -->
        <div class="g-row">
          <div class="g-col-4"></div>
          <div class="g-col-4"></div>
          <div class="g-col-4"></div>
        </div>
      </div>
    </div>
	...
</body>
</html>
複製程式碼

樣式:我們使用的12格柵格

<style>
  .g-row{
    width: 100%;
  }
  .g-row:after{
    content: "";
    display: table;
    clear: both;
  }
  .g-col-4{
    float: left;
    width: 33.33333%;
  }
</style>
複製程式碼

分析設計結束回頭看DOM樹已經有了一個整體的框架,就好比建一棟高樓現在大樓的主體結構已經搭建完畢接下來需要牆體裝修,然後就是每層每戶裝修,在然後就是房間裝修搬傢俱入住

設計DOM&CSS


三,DOM之後的CSS(成品展示)

有了上面DOM結構的設計,在裝修階段(CSS)如果亂搞一通結果也是豆腐渣工程。結合上面DOM的設計CSS的設計有需怎樣呢。
提示:下面程式碼基於sass,使用less的同學整體思路差不多。(假設場景:重構demo網站的首頁,sass檔案命名index.scss)

1,sass——展示塊命名

下面實現中展示塊以block-作為字首,在實際場景中如果是首頁可以採用index-或者加網站名簡寫(azoyaclub:ac)acindex-,詳情頁使用detail-acdetail
關於塊字首的建議: 如果你的字首使用了兩個以上的單詞,建議不要使用駝峰或者-_連線,直接寫成word1word2-。因為我們對字首的需求是功能劃分,雖是兩個單詞但只是名稱歸類的作用,寫在一起簡單明瞭,方便區分、管理

//index.scss
.block{
  &-head{
    ...
  }
  &-nav{
    ...
  }
  &-banner{
    ...
  }
  &-service{
    ...
  }
  &-global{
    ...
  }
}
複製程式碼

2,sass——佈局命名

學習bootstrap的經驗,佈局實現做網站公共樣式,以.g-*作為標識

// _layout.scss
$gridColumns: 12;

.g-{
  &-container{
    ...
  }
  &-row{
    ...
  }
}

@for $i from 1 through $gridColumns { 
  .g-col-#{$i} { 
    width: (1 / $i) * 100%; 
  } 
}
複製程式碼

3,sass——全域性模組命名

全域性模組也就是全站共用模組,整站的input、button、dialog、商城的商品塊等。 相信大家如果看過比較有名點的網站,在他們的DOM中經常能看到以.m-*.mod-*.module-*命名的class。
對於表示狀態的場景個人習慣.m-name.active.m-name.disable的方式

題外話,工作中為了節省開發時間通常會使用到第三方的通用UI元件,不管怎樣能有一個自己的UI框架聽起來就很不錯。老實說,如果你在完成全域性模組這一步有追求的話(質量高,通用性強),然後將他們從專案中獨立出來,恭喜你,你就有用了一個至少自己用起來順手的UI框架

// dialog 實現
%placeholer-button{
  ...
}
.m-dialog{
  &-title{
    ...
  }
  &-content{
    ...
  }
  &-cancle{
    @extend %placeholer-button
  }
  &-ok{
    @extend %placeholer-button
  }
}
複製程式碼
// button實現
%placeholder-button{
  ...
  &.active{
    ...
  }
  &.disable{
    ...
  }
}
.m-button{
  &-primary{
    ...
    @extend %placeholder-button
  }
  &-hollow{
    ...
    @extend %placeholder-button
  }
}
複製程式碼

4,sass——頁面級模組命名

在JS中我們有全域性變數、區域性變數,在CSS中同樣可以區分上面提到的全域性模組和接下來介紹的頁面級模組
開啟我們的demo網站我們的服務包含6個服務介紹模組、全球商家包含8個商家介紹模組,他們是專屬於首頁的,那我們的解決方案是什麼呢

// index.scss

// block
.block{
  &-head{
    ...
  }
  ...
}
// module
.service{
  &-pic{
  ...
  }
  &-title{
    ...
  }
  &-content{
    ...
  }
}
.business{
  &-pic{
    ...
  }
  &-logo{
    ...
  }
  ...
}

複製程式碼

看scss檔案,我們是直接在當前頁面對應的scss檔案(index.scss)中按模組進行開發。如果你擔心發生命名衝突,可以加字首.p-service-*.p-business-*或者其它你喜歡的字首方式

5,sass——樣式覆蓋

我們把一個模組樣式寫好了,面對我們產品的奇思妙想要百分百適用於全站大多時候是不可能的,這就需要我們對模組的某些樣式進行覆蓋重寫。
回顧: 前面我們對DOM樹進行設計時已經將頁面劃分多個獨立的內容展示塊,而這些全域性模組是屬於這個內容展示塊的,所以想要覆蓋全域性模組的樣式,我們的方案是在他所屬的內容展示塊中(輩分關係——祖孫)實現為

  .block-xx{
    .m-x-xx{
      ...    
    }
  }
複製程式碼

建議: 可以在內容展示塊上進行重寫或者給模組新加一個class,而不是我們常見的以模組元素的直接父元素進行重寫

// 不建議
.block-xx{
  
  &-global{
    .m-button-primay{
      ...
    }
  }
}

// 建議
.block-xx{
  .m-button-primay{
    ...
  }
}
// 或者
.m-button-primay{
  &.new-button-primay{
    ...
  }
}
複製程式碼

四、HTML5語義標籤總結版

如果你有耐心看到這裡,或者你有點認同對上面所講的理解了,恭喜你,我又要說點不一樣的東西。
個人認為好的DOM設計、適合的CSS命名是當其它開發者在瀏覽你的程式碼又或者是瀏覽器渲染頁面時大家在做一次對話。
下面結合HTML5的語義標籤讓我們的重構之路更上一層樓

1,語義標籤理解

  • header nav section aside footer :劃分模組——處於相同的上下文。

    什麼意思呢,我們把一個網頁比作人。人分頭、胸、手、屁股、腿和腳,從區域性看他們是獨立的,但他們是組成人這個整體的一員。

  • article figure video: 劃分模組——可獨立存在。

    這又是什麼意思呢,依舊把網頁比作人,人身上可以有項鍊、戒指、手機、手錶和MP3。戒指可以在左手上,也可以在右手上,鼻子耳朵上也可能有,他們屬於人,但他們作為一個物體獨立存在,沒有任何功能和語境上的限制。

  • ul dl em i:這些大家應該比較熟悉了
  • div span: 沒有語義

2,語義標籤的DOM設計

有了上面標籤語義的基礎,我們再來設計我們的DOM樹

  • 使用header nav section aside footer進行內容展示塊的劃分
  • 使用沒有語義的div 來實現佈局,當然也可以用ul+li的方式
  • 使用article figure video進行全域性模組和頁面級模組的劃分
a,資訊展示塊
<!-- 現在我們的DOM結構如下 -->
<!DOCTYPE html>
<html>
  <head>
    <title>demo</title>
    <style type="text/css">
      ...
    </style>
  </head>
  <body>
    <header class="block-head"></header>
    <nav class="block-nav"></nav>
    <main>
      <section class="block-banner"></section>
      <section class="block-service"></section>
      <section class="block-global"></section>
    </main>
    <aside class="block-aside"></aside>
    <footer class="block-footer"></footer>
  </body>
</html>
複製程式碼
b,佈局
<!-- 現在我們的DOM結構如下 -->
<!DOCTYPE html>
<html>
  <head>
    <title>demo</title>
    <style type="text/css">
      ...
    </style>
  </head>
  <body>
    ...
    <main>
      <section class="block-service">
        <div class="g-container">
          <div class="g-col-4"></div>
          <div class="g-col-4"></div>
          <div class="g-col-4"></div>
        </div>
      </section>
    </main>
    ...
  </body>
</html>
複製程式碼
c,模組填充
<!-- 現在我們的DOM結構如下 -->
<!DOCTYPE html>
<html>
  <head>
    ...
  </head>
  <body>
    ...
    <main>
      <section class="block-service">
        <div class="g-container">
          <div class="g-col-4">
            <!-- service模組 -->
            <article class="m-service"></article>
          </div>
          <div class="g-col-4">
            <!-- 展示圖片 -->
            <figure class="p-info">
              ...
            </figure>
          </div>
          <div class="g-col-4">
            <!-- 引入視訊 -->
            <video></video>
          </div>
        </div>
      </section>
    </main>
    ...
  </body>
</html>
複製程式碼

總結

前面講了這麼多,主要是從大局觀上看DOM樹的設計,CSS命名方式,算是拋磚引玉吧。
一個好的DOM、CSS程式碼設計方案只是提升我們工作效率和程式碼質量的基礎,要做一個追求完美的切圖仔還是需要過硬的基礎知識(不知道從什麼時候開始,出去面試大多隻是考察javascript的知識,對於頁面重構好像你知道就行了,哈哈哈哈哈哈哈~~~~)
前面涉及到的程式碼展示只是佈局相關,想寫好一個全域性模組的樣式對於CSS的掌握還是有一定要求的,這裡推薦張鑫旭老師的部落格,對於CSS3和sass的知識推薦大漠老師的部落格網站

寫在最後

本來表達能力就比較差,就這樣磨蹭著寫完了,也不知一些東西講清楚了沒。有疑問或有好的建議的可以在下面留言分享下。

補充

這裡主要從大局觀出發探討頁面重構的方案,如何在繁雜的標籤巢狀中理清脈絡,並不涉及到如何去實現頁面(這可不是一篇文章就能講清楚的,對於頁面模組的實現需要大家多多積累)。如果你理解了或者你已經有了解決這個問題的答案,那麼當我們在使用vue、react開發時遇到元件劃分這個問題也將不是問題。祝你好運!

相關文章