【问题标题】:Semantic HTML5 structure versus CSS layout needs语义 HTML5 结构与 CSS 布局需求
【发布时间】:2013-05-21 23:34:15
【问题描述】:

我有一个类似下面的网页:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Title</title>
    </head>
    <body>
        <header>
            <span>Logo</span>
            <nav>Navigation</nav>
        </header>
        <main>
            <h1>Page heading</h1>
            <div>
                Page content
            </div>
        </main>
        <footer>
            Content information
        </footer>
    </body>
</html>

页面结构类似于当前 HTML5 草案中的一个示例:http://www.w3.org/html/wg/drafts/html/master/grouping-content.html#the-main-element,我认为它在语义上是正确的。

现在我想使用 CSS 设置此文档的样式。我想成为顶部的页眉和底部的页脚,这当然很容易做到。在标题内,我想将徽标放在右侧,将导航放在中间,这也可以(例如,通过使用现代浏览器以一种或另一种方式支持的灵活框布局模型,或者通过使用浮动)。

当我想将主要的内容标题(h1 元素)直观地放在标题的左侧时,我的问题就开始了。我可以使用 position: absolute 但这样的布局不是很灵活,并且一旦标题或标题的大小发生变化就会中断。提议的 CSS 网格布局 http://www.w3.org/TR/css3-grid-layout/ 可能完全符合我的要求,但据我所知,它仅在 IE 10 中(不知何故)受支持。

一个简单而有效的解决方案是简单地重组我的页面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <h1 id="heading">Page heading</h1>
            <header>
                <span>Logo</span>
                <nav>Navigation</nav>
            </header>
        </div>
        <main aria-labelledby="heading">
            <div>
                Page content
            </div>
        </main>
        <footer>
            Content information
        </footer>
    </body>
</html>

这种解决方案虽然易于布局,但其完整语义仅通过 aria-* 属性表示,并且似乎违背了 HTML5 语义的精神(尤其是主要元素)。

虽然我的示例页面可能很简单,但您可以轻松想象一个更复杂的页面,其中更多元素的视觉位置与 HTML5 标记的流顺序不同(并且嵌套以便灵活的框布局order 属性是不够的)。你会如何解决这个问题?用非语义元素(例如 div)重写 HTML5 标记,使其更符合视觉布局,然后尽可能使用新结构通过语义元素(例如页脚或主)交换非语义元素?

【问题讨论】:

  • 我认为您提出的解决方案非常好。用于演示目的的&lt;div&gt; 标签应该与语义标签结合使用。不过,我很想看看那些比我更精通这些问题的人的答案......
  • 使用 flexbox,您可以拥有源顺序独立性。您可以使用order 属性(在IE10 中为flex-order,在旧WebKit 和Firefox 中为box-ordinal-group)。有关更多信息,请参阅我文章的源顺序独立部分coding.smashingmagazine.com/2013/05/22/…
  • @David Storey:感谢您分享您的文章。我知道 flexbox 的 order 属性,但这不允许我在不同的 flex 容器之间打乱,是吗?在我的第一个语义标记中,标题位于主容器内,但我不想将主容器放在标题之前,而只是将主容器的一个元素放在标题内(或在标题的其他元素之前)。

标签: css html accessibility semantic-markup wai-aria


【解决方案1】:

我遇到了和你一样的难题,我很感激这种挫败感。我会尝试一个否定的答案,因为我觉得这两个积极的答案(也就是说你可以达到你的目的)都没有抓住重点。

首先,在我看来,您的主要困难是 CSS 无法将元素移动到新容器中。这两个答案分为两类:

  1. 有些是超特定 hack(主观而言),涉及浮动、负边距和/或绝对定位,可以将项目从其容器中移出。这些可能是有效的,但仅限于非常特殊的情况。随着您的需求增长,它变得难以维护,并且需要设置一个相当大的思维上限来解决您之前错过的每个新需求或边缘案例。 @jennifit 的答案试图将您推向这个方向。我相信这是那些努力遵循语义HTML5精神的人所采取的正常路线,这是令人钦佩的。但它可能是一个泥潭,让你开始问到底你在为谁维护你的语义纯度?是为了搜索引擎、屏幕阅读器还是易于维护?我会在下一次分类后回到这个。

  2. 有些是实用的合理化,它们声称在语义上是等价的,但实际上是不同的语义含义。在我看来,这些确实是语义黑客。 @volker-e 的答案就是一个例子。他是对的,这是一种可行的替代标记——但是,它不等于相同的语义。 h2 作为 h1 属于 main ——在页面标题中移动它是没有意义的。实际上,您是在说您的标题与您的主要内容无关。在某些方面,这比使用您想要使用的 div 更糟糕,因为您通过将页面标题和站点标题分组到相同的语义上显着 header 来建立错误的语义关系。在我看来,headermain 的语义无意义的容器(例如 div)实际上不那么反常。

所以,回到我所说的你为谁维护语义纯度,这是真正的哲学问题。通常有一个明显、有效且可维护的解决方案,而不会合理化 滥用现有的语义元素或 css“技巧”。在您的情况下,如果有一个项目在语义上是孩子但在表面上不是孩子,答案就是您已经提出的问题:

用非语义元素(例如 div)重写 HTML5 标记,以便 它更对应于视觉布局,然后交换 [原文如此] 语义元素(例如页脚或主元素)的非语义元素 新结构可以实现。

无论你的语义纯度是否适合

,这都是正确的做法
  • 可访问性:在这种情况下,您可以使用 ARIA 角色以非分层方式实现这一目标。
  • 搜索引擎:搜索引擎仍然理解的做事方式,因此如果您遵循旧的语义方法,您就不会陷入 SEO 麻烦。
  • 维护:这是大多数人被吸引的原因——但问题是,可维护的 HTML 和不可维护的 CSS 有什么意义,或者反过来呢?您别无选择,只能将您的维护视为 CSS 和 HTML 的组合,并且您必须找到中间立场,当您遇到困难的表现问题时,它们会同样混乱。

如果您认为 HTML 语义才是最重要的,那么唯一可能的答案是接受分层 HTML 语义对布局的限制。问题是,CSS 中没有办法重新创建布局层次结构。在此之前,您必须接受 HTML 既是一种表现语言又是一种语义语言,因此,语义始终是“更好”和“更差”的问题。在许多(如果不是大多数)布局中,都无法实现真正​​美丽、丰富或完美的语义。

【讨论】:

    【解决方案2】:

    我的方法如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <a class="aural" href="#content">Jump to content</a>
        <header role="banner">
            <h1 class="site-logo">Logo</h1>
            <nav role="navigation" aria-labelledby="nav-heading">
                <h6 id="nav-heading">Navigation</h6>
                <ul>…</ul>
            </nav>
            <h2 id="heading">Page heading</h2>
        </header>
        <main id="content" role="main" aria-labelledby="heading">
            Page content
        </main>
        <footer role="contentinfo">
            Content information
        </footer>
    </body>
    </html>
    

    然后选择 CSS 规则集,例如:

    header h1,
    header h2,
    header nav {
        float: right;
    }
    

    差异:

    【讨论】:

      【解决方案3】:

      如果 中有 position:relative 并且在 h1 上使用 position:absolute 并带有 z-index 和 -ve 边距,第一个结构可能仍然有效。这样,标题将始终浮动在与主要内容相关的相同位置的顶部。虽然它可能不是最好的解决方案,但我认为它不会破坏布局(?)

      【讨论】:

        猜你喜欢
        • 2012-03-27
        • 2016-04-30
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2012-10-06
        • 2021-09-06
        • 2011-02-07
        • 1970-01-01
        相关资源
        最近更新 更多