【譯】停止濫用div! HTML語義化介紹

call_me_R發表於2019-04-13

banner

DIVS該停止(濫用)了

我們喜歡(使用)<div>標籤。它們已經存在了幾十年,這幾十年來,當需要將一些內容包裹起來達到(新增)樣式或者佈局目的的時候,它們成為首選元素。檢視線上站點時,看到像下面這些內容的情況依舊很常見:

<div class="container" id="header">
    <div class="header header-main">Super duper best blog ever</div>
    <div class="site-navigation">
        <a href="/">Home</a>
        <a href="/about">About</a>
        <a href="/archive">Archive</a>
    </div>
</div>
<div class="container" id="main">
    <div class="article-header-level-1">
        Why you should buy more cheeses than you currently do
    </div>
    <div class="article-content">
        <div class="article-section">
            <div class="article-header-level-2">
                Part 1: Variety is spicy
            </div>
            <!-- cheesy content -->
        </div>
        <div class="article-section">
            <div class="article-header-level-2">
                Part 2: Cows are great
            </div>
            <!-- more cheesy content -->
        </div>
    </div>
</div>
<div class="container" id="footer">
    Contact us!
    <div class="contact-info">
        <p class="email">
            <a href="mailto:us@example.com">us@example.com</a>
        </p>
        <div class="street-address">
            <p>123 Main St., Suite 404</p>
            <p>Yourtown, AK, 12345</p>
            <p>United States of America</p>
        </div>
    </div>
</div>
複製程式碼

Hoo,那有很多的div標籤。但是,它有效。我的意思主要是,它具有你需要的結構。並且,我確定在你完成樣式新增之後,它看起來會像你想要的那個樣子。然而,它有些嚴重的問題:

  • 可訪問性 - 許多a11y tools非常智慧,會盡力解析頁面結構,以幫助使用者按照頁面製作者的意圖來引導使用者,併為使用者提供簡單的跳轉連結來指引他們到自己關心的頁面部分。然而,<div>標籤並沒有真正傳遞有關文件結構的任何有用資訊。世界上最聰明的a11y tool仍然不是人類,不能指望其解析classid屬性,或能夠識別全世界開發人員命名塊元素的奇怪和狂野的方式。我可以識別到class="article-header-level-2"是一個副標題,但是機器不能。(如果可以的話,把它從我電腦中拿出來,可我也還沒準備好進行AGI革命呢。)

  • 可讀性 - 要閱讀此程式碼,你需要仔細掃描類名,從<div class="..."></div>樣板之間挑選出來。一旦你(的程式碼)深入幾個層次,跟蹤哪個</div>結束標記與哪個<div ...>開始標記對應,那就變得很棘手了。你開始非常依賴IDE功能,例如著色不同的縮排級別突出顯示匹配的標記以跟蹤您的位置,而在較長的文件中,它可能需要在這些功能之上進行大量的滾動。

  • 一致性和標準 - 開始新的工作或轉移到新專案,並且必須從頭學習程式碼庫中使用的讓人抓狂的標記,那可能會令人很沮喪。如果每個人都有標準化的方法來標記web文件中常見結構,那麼在不熟悉程式碼庫的情況下,都可以很容易的瀏覽HTML檔案並快速處理它應該展示的內容。如果只有一個這樣的標準...

HTML5: 這個標準

HTML5並不新奇。這是輕描淡寫;最初的工作草稿於2008年1月(11年前)釋出,以徵求公眾意見,並於4年半前,2014年10月份成為一個全面W3C的推薦。所以,就像它已經存在了一段時間。

HTML5的主要進步之一是引入了一組標準化的語義元素。術語“語義”指的是單詞或事物的含義,因此”語義元素“是用於以更有意義的方式標記文件結構的元素,這種方式可以清楚地表明它們的用途和它們在檔案中服務的目的是什麼。而且重要的是,由於它們是標準化的,定義文件的這些元素可以被每個人使用並理解,包括機器人。

我認為HTML5規範本身在<div>元素定義下的一個註釋中很好地總結了這個問題:

註釋: 強烈建議作者將div元素視為最後採取的元素,在沒有其它元素適合的(情況下)。使用更合適的元素而不是div元素可以使讀者更容易訪問,並且更容易為作者提供可維護性。-- www.w3.org/TR/html5/gr…

我將語義塊元素分為兩類:主要結構內容指標。這些不是標準的條款或者其它條款;我在這篇文章中做了一些(區分)。但我認為這種區分足夠有用。?‍♂️

主要結構

有一個超級常見的模式,可在網際網路上的網站,教程甚至CSS庫中找到,並且有充分的理由。我們經常將最頂層的頁面劃分為三個區域:頁首主頁頁尾,然後根據需要將這些區域劃分為多個區域。我在上面的例子中包含了這個來證明這點:

<div class="container" id="header">...</div>
<div class="container" id="main">
    ...
    <div class="article-section">...</div>
    ...
</div>
<div class="container" id="footer">...</div>
複製程式碼

我已經看過(並且使用過)這種模式很久了,以這種方式構造文件非常有意義,既可以讀取HTML,又可以更加簡單地在CSS中設定頁面樣式。頁首和頁尾元素頁可以使用PHP或Rails/ERB等語言中的部分模版來更易於使用,因為你可以在整個站點中包含常見的頁首和頁尾部分:

<?php include 'header.php'; ?>

<div id="main">...</div>

<?php include 'header.php'; ?>
複製程式碼

所以這就是事情:每個人都認為這是一個很好的模式。這包括WHATWGW3C的人員,他們將模式標準化為HTML5中的四個新元素,名稱非常清晰:<header>, <main>, <footer><section>

Bookends: <header><footer>

<header><footer>元素基本上是雙胞胎:它們在規範中的定義非常相似,並遵循相同的規則,關於它們被允許使用的位置,唯一區別在於它們的語義目的:頁首在事物的前面,頁尾在事物的末尾。對於事物,我的意思不僅僅是頁面的: 這對元素的設計用於文件的任何部分,代表一大塊內容,具有明確的開頭和結尾。這可以包括表格,文章,文章部分,社交媒體網站上的帖子,卡片等。

頁首和頁尾在語義上接近sectioning rootsectioning content元素。像<body>, <blockquote>, <section>, <td>,<aside>等許多其它元素;如果你想了解完整的列表,就點選上面的連結。輔助技術可以使用這些元素和其它元素生成文件大綱,這可以幫助使用者更輕鬆的訪問它。在每個sectioning root/content中,你不應該使用超過一個的<header><footer>。(一個就好,不能兩個相同)

作為最後說明,<header>經常作為其上下文儲存標題元素(<h1>-<h6>)。這不是必須的,但可以幫助將其它相關元素與標題分組,比如連結,圖片或子標題,並且可以維持一直的結構,即使標題是<header>中的唯一元素。

好東西:<main>

第三個主要區域元素--<main>很特別。規範中說明了關於<main>的兩個非常重要的內容:

文件的主要內容區域包括文件的特定內容,且不包括在一組文件中重複的內容,例如站點導航連結,版本資訊,站點的徽標,橫幅和搜尋表單(除非文件或應用的主功能是一種搜尋形式)-- www.w3.org/TR/html5/gr…

所以,<main>是你放置好東西的區域,是頁面的重要部分,特別是使用者訪問此頁面的原因(或說目的),而不是您的站點。換句話來說,主要內容。???

所有其它東西,徽標、搜尋表單和導航欄等都可以在<body>中的<header><footer>中,但是在<main>之外。

文件中不能有多個可見的main元素。如果文件中存在多個main元素,則必須使用隱藏屬性隱藏所有其它(main)例項。 -- www.w3.org/TR/html5/gr…

這很獨特。和<header><footer>(以及其它塊元素不同),<main>不能在任意切片內容的整個頁面中使用;它應該只被使用一次。或者更確切地說,它可以在文件中多次被使用,但是一次只能看到一個<main>元素,所有其它的(

)必須被使用隱藏屬性隱藏,如CSS中的display:none。如果您思考下,(你會明白)這在應用程式中預載入檢視是種很有用的模式:建立一個新的<mian hidden>,獲取使用者可能接下來檢視的一些內容(例如:系列文中的下一篇,下一張幻燈圖放映等),然後,當使用者點選連結/按鈕載入該檢視時,通過在兩者上切換隱藏屬性,將當前的<main>切換到預載入的(那個)。

在繼續之前,我們暫停下並檢視上面的示例。如果我們使用<header><main><footer>作為文章的主要結構,它的外觀如下:

<header>
    <h1>Super duper best blog ever</h1>
    ...
</header>
<main>
    <h2>Why you should buy more cheeses than you currently do</h2>
    ...
</main>
<footer>
    Contact us!
    <div class="contact-info">this.is.us@example.com</div>
</footer>
複製程式碼

那真的很棒!但是,還有很多工作要做。

分解:<section>

因此,我們為頁面提供了一個基本大綱:頁首,頁尾和主要內容區域。現在是時候新增些美妙的內容了。

通常,你會希望將你的內容分解為多個部分,尤其是對像本文這樣的大量文字內容,因為沒人喜歡閱讀這些難以理解的文字牆。

Nobody likes a wall of text

<section>派上用場了。這是在系列規則中最簡單的一個:從結構上講,它基本上只是一個具有特殊含義的<div>。一個<section>開始一個新的"sectioning content"區域,因此它可以有自己的<header><footer>

那麼,<section>和普通的舊<div>之間有什麼區別,然後,你應該在什麼時候使用它們呢?好吧,允許我再次引用規範:

筆記:

元素不是通用容器元素。當一個元素僅是用於樣式目的或為指令碼編寫提供便利的時候,鼓勵作者使用[div](https://www.w3.org/TR/html5/grouping-content.html#elementdef-div)元素。一般規則是
元素僅在元素內容在文字[大綱](https://www.w3.org/TR/html5/sections.html#outline)中明確列出時候才適用。-- [https://www.w3.org/TR/html5/sections.html#the-section-element](https://www.w3.org/TR/html5/sections.html#the-section-element)

你知道,概述來說,HTML5規範實際上是可讀的。它是那個比較可讀的規範之一。每當我瀏覽它以獲取快速答覆時,我都不可避免地學到一些意想不到的和有用的東西,尤其是當我開始點選連結的時候。有時(你也)試試吧!

簡而言之,如果要在目錄中列出文件的一部分,請使用<section>。如果沒有,請使用<div>或其它元素。

內容指標

很好,我們已經得到了一個堅固的頁面結構。我們已經明確標記了頁面的主要內容區域,而不僅僅是單獨調整<div>,我們已經調整出了頁首,頁尾和章節。但是,肯定還有比我們的文件更多的語義。

讓我們來談談HTML5中新增的一些元素,它們傳達的內容語義而不是結構。

整體:<article>

<article>元素用於表示完全獨立的內容區域,這些內容可以從頁面中提取出來並放入另一個內容中,並且仍然有意義。這可能是文字文章或部落格,但也可用於社交媒體帖子,如推特或臉書的牆貼。

HTML5規範建議文章總有一個標題,標識它是什麼,理想的情況下使用標題元素(<h1>-<h6>)<article>也可以有<header><footer><section>元素,因此你可以使用它來嵌入一個完整的文件片段,其中包含其它頁面中所需的所有結構。

從上面的方式返回到示例,我們使用<article>和我們討論的其它一些元素來重寫帶class="article-*"的元素。

<article>
    <header>
        <h1>Why you should buy more cheeses than you currently do</h1>
    </header>
    <section>
        <header>
            <h2>Part 1: Variety is spicy</h2>
        </header>
        <!-- cheesy content -->
    </section>
    <section>
        <header>
            <h2>Part 2: Cows are great</h2>
        </header>
        <!-- more cheesy content -->
    </section>
</article>
複製程式碼

這不是比原來更具可讀性嗎?而且,不僅更容易閱讀,它對輔助技術更有用;機器人不能總是弄清楚你的特定類名模式,但是它們可以遵循這種結構。

使用:<nav>

這個元素比其它元素更有名。<nav>旨在清楚地識別頁面上的主要導航塊,幫助使用者圍繞站點其餘部分找到路徑的連結組(例如站點地圖或標題中的連結列表)或當前頁面(例如目錄)。

在我們的示例頂部,讓我們將<nav>應用於標題中的那組連結。

<nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
    <a href="/archive">Archive</a>
</nav>
複製程式碼

根本不改變結構,但你知道它是什麼,一目瞭然而不需要在<div>上讀物和處理類名來找到它,更重要的是機器人也可以找到它。

接觸:<address>

我們要討論的最後一個元素是<address>。這個元素旨在調出聯絡資訊,它通常在主頁<footer>中用於標記企業的郵寄地址,電話號碼,客戶服務郵箱地址等等。

有趣的是,如何在<address>元素中標記內容的規則是開放的。規範提到有幾個其它規範可以解決這個問題,並且提供這種級別的粒度可能超出了HTML本身的範圍。

常見的解決方案是RDFa,也是W3C規範,它使用標籤上的屬性來標記資料的不同元件。下面是我們示例中的頁尾在標記<address>元素和RDFa時可能看起來的樣子:

<footer>
    <section class="contact" vocab="http://schema.org/" typeof="LocalBusiness">
        <h2>Contact us!</h2>
        <address property="email">
            <a href="mailto:us@example.com">us@example.com</a>
        </address>
        <address property="address" typeof="PostalAddress">
            <p property="streetAddress">123 Main St., Suite 404</p>
            <p>
                <span property="addressLocality">Yourtown</span>,
                <span property="addressRegion">AK</span>,
                <span property="postalCode">12345</span>   
            </p>
            <p property="addressCountry">United States of America</p>
        </address>
    </section>
</footer>
複製程式碼

無疑,RDFa有點冗長,但它對於標記資料非常方便。如果你有興趣瞭解有關RDFa的更多資訊,請點選以下連結:

總結

好了,我們已經介紹了很多,我們已經看到很多零零散散的元素應用到我們的例子中。那麼,讓我們把它們放在一起看看它的樣子。

<header>
    <h1>Super duper best blog ever</h1>
    <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
        <a href="/archive">Archive</a>
    </nav>
</header>
<main>
    <article>
    <header>
        <h1>Why you should buy more cheeses than you currently do</h1>
    </header>
    <section>
        <header>
            <h2>Part 1: Variety is spicy</h2>
        </header>
        <!-- cheesy content -->
    </section>
    <section>
        <header>
            <h2>Part 2: Cows are great</h2>
        </header>
        <!-- more cheesy content -->
    </section>
</article>
</main>
<footer>
    <section class="contact" vocab="http://schema.org/" typeof="LocalBusiness">
        <h2>Contact us!</h2>
        <address property="email">
            <a href="mailto:us@example.com">us@example.com</a>
        </address>
        <address property="address" typeof="PostalAddress">
            <p property="streetAddress">123 Main St., Suite 404</p>
            <p>
                <span property="addressLocality">Yourtown</span>,
                <span property="addressRegion">AK</span>,
                <span property="postalCode">12345</span>   
            </p>
            <p property="addressCountry">United States of America</p>
        </address>
    </section>
</footer>
複製程式碼

如果你問我(怎麼看改造後的內容?),那這比原始例子的可讀性高100倍,而且對於搜尋引擎優化和可訪問性目的而言,其效率將提高100倍。

這些絕不是HTML中唯一的語義元素。有很多其它元素可以幫助你標記和構建你的文字內容,嵌入媒體資源等等。如果你喜歡這個並且希望深入挖掘,這裡有一些(標籤)可以檢視下。你可能認識一些:

這只是一個開始!就像我說的,當你開始閱讀HTML規範時,很難停下來。它是種非常豐富的語言,我認為人們經常會低估這種語言。

原文: dev.to/kenbellows/…

文章首發:github.com/reng99/blog…

更多內容:github.com/reng99/blog…

相關文章