下面兩段代碼從HTML語義化的角度來看有什麼問題?css
<!-- 示例1 -->
<label>做者: <input type="author" texture="deep pile"></label>
<!-- 示例2 -->
<body>
<h1>【深度】扒開V8引擎的源碼,我找到了大家想要的前端算法</h1>
<h2>下次面試官再問算法,用它懟回去!</h2>
...
複製代碼
讀者能夠先試試將上面例子中的代碼進行語義化,再來看文末的答案。html
HTML 語義化(按照 W3C 規範正確地使用標籤元素和其屬性,如下簡稱「語義化」,HTML 指 HTML5)被不少文章提到,但內容大可能是先宣傳語義化的必要性,而後勸說讀者在開發中多使用語義化標籤。前端
本文不宣傳必要性, 也不賣力推薦大多數讀者能寫出語義化的代碼,只對語義化的現狀進行探究,並給出可行的語義化操做方式。html5
咱們以非語義化標籤的濫用爲例來看看目前網頁的語義化程度。node
非語義化的標籤其實只有兩個 div 和 span,原本這兩個標籤只是做爲默認標籤的補充,但現實是它們的使用頻率卻遠超其它語義化標籤。git
下面是一段統計標籤數量的 js 腳本,用它能夠統計出網頁上各個標籤數量和佔比。github
打開瀏覽器控制檯,執行下面的代碼就能夠獲得結果。面試
var total = 0
var obj = Array.prototype.reduce.call(document.querySelectorAll('*'), (acc, cur) => {
let tag = cur.tagName.toLowerCase()
acc[tag]= acc[tag] || 0
acc[tag]++
total++
return acc
}, {})
var list = []
for(let k in obj) list.push({tag: k, times: obj[k], ratio: (obj[k] * 100 / total).toFixed(2) + '%'})
console.clear()
console.table(list.sort((a, b) => b.times - a.times))
複製代碼
先來看看咱們使用最頻繁的搜索引擎頁面,語義化程度爲67.5%。算法
最好實現語義化的頁面莫過於文章帖子類的頁面,可是某博客網站頁面語義化程度61.29%。編程
再看看市值排行世界前列的某電商網站頁面,語義化程度爲43.19%。
更多的統計數據就不貼出來了,整體狀況是語義化程度很低。
爲何語義化如此不受待見?
咱們來看看現實開發場景中是如何一步一步地把工程師推向無語義化的道路上的。
HTML定義了100多個標籤,若是要把它們所有記住,確實有些難度。
即便分類記憶,也有十幾類,若是再加上各個標籤不一樣的屬性,記憶量並不算小。
因此使用的時候可能還須要查文檔。
就開發效率來講不如直接使用 div 和 span 來實現功能。
使用一項技術,首先考慮其收益,或者說它能解決什麼問題,那麼語義化能帶來什麼呢?
說了這麼多,其實概括起來就一點:加強可識別性。
識別性的重要性不言而喻,沒有識別性就像電影《風語咒》中那個村裏不少人都叫王富貴,喊一聲王富貴一片人回頭。
如此說來語義化勢在必行?
非也~
HTML 語義化並非實現可識別性的惟一手段,標籤 id、屬性、樣式名均可以。
寫個CSS樣式類,順便就把識別性的問題解決了(試想一下,若是不能自定樣式,或者樣式只能使用類選擇器,誰還能不語義化?),樣式類重複再經過屬性或id來識別。
和前面這幾種方式相比,語義化沒有明顯的使用收益。
從開發者的角度考慮,若是不使用語義化的標籤會有什麼壞處呢?
很遺憾,幾乎沒有~
既然底層開發者沒有語義化的動力,那麼管理者是否能經過規則來推進語義化呢?
我在《3種常見的代碼規範類型》提到過,若是要讓規則落地執行,光靠人的自律是很難實現的,靠人力來實現他律效率又過低,因此創建自動化的校驗機制,將人力他律做爲補充,纔是高效的方案。
不少時候咱們會用到代碼檢查工具好比 eslint、tslint ,HTML 的檢查工具也有幾個,不過這些檢查工具只能作語法檢查,沒法進行語義檢查。
舉個例子,用駝峯命名規則能夠檢查出 parent_node
這種變量名稱不符合規範,但對於一個變量是該叫a
仍是該叫user
檢查工具則無能爲力了。
因此強制語義化這條路也走不通。
語義化真的只能放棄嗎?
對於大多數工程師而言,恐怕是的。
編寫語義化代碼並不能直接帶來開發效率提高,也不能憑此獲得領導賞識而升職加薪......
但對於有技術追求的工程師而言,並非!
他們知道作對的事比作容易的事更重要!
若是你已決定踏上語義化的道路,相信如下3個步驟能夠幫助你。
對於具備必定開發經驗的工程師而言,非語義化的編程習慣是長久造成的,須要一口氣所有改掉以前的編程習慣很難。
不建議一口氣把全部標籤所有記下來,而後把以前的頁面推倒重寫,全盤實現語義化。
比較耗時耗力,很容易生成挫敗感而放棄。
因此推薦的方式是逐步實現語義化,從一個標籤甚至一個屬性開始。具體例子請看示例1
這一階段重要的是養成語義化的習慣。
不少狀況下能堅持下來造成習慣就已經成功一半了。
養成習慣之後就能夠從結構上考慮頁面的語義化了。
非語義化最主要的問題就是 div 和 span 標籤濫用。
徹底不使用 div 和 span 並不現實,畢竟這兩個標籤被髮明出來也是有使用價值的。
因此能夠首先找出一些容易被濫用的區域,這樣就能大大增長頁面語義化的程度。
首先要考慮的就是減小沒必要要的 div 和 span 標籤,而後纔是考慮用合適的語義化標籤來取代。
好比平常開發中和文本相關的內容比較多,那麼考慮使用 h1~h6 , p , q , b ... 這些標籤來取代 div 和span。
即便是佈局方面也可使用一些結構性標籤,如: main , section , footer , aside , header 來取代 div。具體例子請看示例2
若是要作到徹底語義化,還能夠利用工具。
下面是一張 html5 使用流程圖,僅供參考。
W3C 也給出了一個分類方法,很形象,動畫圖以下:
具體效果能夠查看這個網站
參考以上兩張圖,我整理了一個操做性更強的版本。
首先一些基礎標籤咱們不須要考慮在內,尤爲是在開發單頁應用的時候,咱們主要考慮開發組件時可能用到的標籤。
!DOCTYPE,html,head,meta,base,link,style,body,script,noscript,<!-- -->
而後將剩下幾十個標籤進行分類,不必定徹底貼切,但便於記憶和使用。
固然不管使用那種方式,前提仍是記住這些標籤的含義和屬性。
這戲工具的做用只是在咱們寫頁面的時候,幫咱們快速準確地判斷要使用哪一個標籤。
語義化就像是前端成長道路上的一顆石子,失去每一顆石子彷佛都不會形成影響,但只有彙集更多的石子才能鋪成更長的路~
熟練編寫語義化的頁面並不能直接幫你成爲高級前端工程師,但語義化卻能體現前端工程師的工做習慣和技術素養。
<!-- 示例1語義化 -->
<!-- type值修改成瀏覽器可識別的值 -->
<!-- 自定義屬性使用data前綴 -->
<label>做者: <input type="text" class="author" data-texture="deep pile"></label>
<!-- 示例2語義化 -->
<!-- 當出現主標題和子標題時,應使用hgroup標籤做爲父元素 -->
<body>
<hgroup>
<h1>【深度】扒開V8引擎的源碼,我找到了大家想要的前端算法</h1>
<h2>下次面試官再問算法,用它懟回去!</h2>
</hgroup>
...
複製代碼
附上答案同時再給讀者留一道思考題:
<!-- 可點擊的圖標 -->
<div class="lazy avatar avatar loaded immediate"></div>
<!-- 點擊後彈出的菜單 -->
<ul class="nav-menu user-dropdown-list">
<div class="nav-menu-item-group">
<li class="nav-menu-item">
<a href="/user/592447fb44d904006ce996f8" class="link-icon">
<i class="fengwei fw-person"></i>
<span>個人主頁</span>
</a>
</li>
<li class="nav-menu-item">
<a href="/user/592447fb44d904006ce996f8/likes">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="zan">
<span>我贊過的</span>
</a>
</li>
<li class="nav-menu-item">
<a href="/user/592447fb44d904006ce996f8/collections">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="collect">
<span>個人收藏集</span>
</a>
</li>
</div>
<div class="nav-menu-item-group">
<li class="nav-menu-item">
<a>
<i class="fengwei fw-logout"></i>
<span>登出</span>
</a>
</li>
</div>
</ul>
複製代碼
參考: