改变默认显示属性是一种好的做法吗?

14

TL;DR: 在CSS中更改默认的display属性是一种不好的做法吗?

问题

最近,在我们的项目中,我们必须定位2个标题标签,使它们看起来像一个。它们具有相同的字体大小和类似的样式,因此唯一的问题是如何将它们放在一起。我们有两个不同的想法,并进行了讨论,讨论是否更改默认的display属性是一种良好的做法。

因此,我们的代码基本上是这样的:

<div class="container">
    <h1>Header:</h1>
    <h2>my header</h2>
</div>

我们想要的结果:

标题:我的标题

注意: 由于在移动版本中,我们希望它们显示在不同的行中(因此保留默认的display: block),所以代码需要包含两个不同的标题。

方法1:使用display: inline

这很简单。块级元素变为内联元素,因此它们在同一行中定位。这种方法的缺点是改变了h1h2的默认显示属性。

方法2:使用float

h1可以使用float:left属性放置在左侧。这种方法保留了默认的显示属性,但如果.container长度不足以适应单行显示两个标题,则需要一些技巧。

问题

这引出了一个简单的问题:更改HTML元素的默认display属性是否是不良做法?它是否违反标准,如果可能的话应该避免使用?或者它是我们的必备技能,只要代码在语义上正确(例如标题放在h1中,文章放在article中等)就没有关系?


代码需要包含两个不同的标题,因为在移动版本中,我们希望将它们显示在不同的行中。你的问题不在于更改默认的显示类型,而在于误用标题。仅仅因为一个标题可以跨越多行并不意味着它变成了两个不同的标题(而且还是不同等级的!)。 - BoltClock
为了讨论方便,假设我们需要有两个标题。或者暂时不考虑标题。 - dotintegral
3
确实是你。 - dippas
1
@AnthonyRutledge,如何在CSS中正确选择元素超出了本问题的范围。不要过多地关注格式。 - Nils Kaspersson
4
这个问题不是关于全局重置显示值的。使用选择器只针对特定元素进行操作是隐含的。问题是一旦选定了这些元素,我们应该怎么做。 - Mchl
显示剩余4条评论
9个回答

16

回答你的主要问题:

简而言之,在我的CSS中更改默认的display属性是一种不好的做法吗?

不是


为什么?

A: 因为这与语义有关

HTML中的元素、属性和属性值被定义(由这个规范)为具有某些含义(语义)。例如,ol元素表示一个有序列表,lang属性表示内容的语言。

这些定义允许HTML处理器(如Web浏览器或搜索引擎)在作者可能没有考虑到的广泛场景下呈现和使用文档和应用程序。


所以,在你的情况下,如果你真的需要 语义上有两个标题,那么你可以改变它们的样式,包括display属性。

但是,如果你不需要 语义上有两个标题,但只是为了美化/设计(响应式代码),那么你的做法就不正确

看这个例子:

<h1>Welcome to my page</h1>
<p>I like cars and lorries and have a big Jeep!</p>
<h2>Where I live</h2>
<p>I live in a small hut on a mountain!</p>

Because HTML conveys meaning, rather than presentation, the same page can also be used by a small browser on a mobile phone, without any change to the page. Instead of headings being in large letters as on the desktop, for example, the browser on the mobile phone might use the same size text for the whole the page, but with the headings in bold.

This example has focused on headings, but the same principle applies to all of the semantics in HTML.

**上述引用中的强调是我的**

P.S - 请记住,标题

-

不应用于标记副标题或小标题,除非它们是新部分或子部分的标题。


有了上述所有内容的考虑,以下是一些(好的)方法:

如果您只是出于设计目的而使用这两个标题,则:

  • 内添加使用media query,可以使用移动优先方法(min-width)或非移动方法(max-width)。

优点 — 通过 CSS 很容易管理,仅更改属性。

缺点 — 添加额外的 HTML 标记,也需使用media query

h1 {
  /* demo only */
  background: red;
  margin:0
}
@media (max-width: 640px) {
  span {
    display: block
  }
}
<div class="container">
  <h1>Header:<span> my header</span></h1>
</div>

如果您需要语义化地使用这两个标题,则:

  • 使用flexbox布局。

优点 - 无需添加额外的HTML标记或使用媒体查询,目前在CSS中是最灵活的(基本上是上述选项中提到的缺点)。

缺点 - IE10及以下版本部分支持或不支持,可以使用flexbox吗? (IE10及以下版本的备用方法为CSS TABLES)。

.container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /*demo only*/
  background: red;
}

h1,
h2 {
  /*demo only*/
  margin: 0;
}

h2 {
  /*640px will be flex-basis value - can be changed as prefered */
  flex: 0 640px;
}
<div class="container">
  <h1>Header:</h1>
  <h2>my header</h2>
</div>

参考资料:


你真的要使用那个参数吗?我只是想要一个详细的解释,来说明你评论中的问题。我知道 target 的含义并且能够 override 它。但是在有两个标题的情况下,我没有考虑过比 flexbox 布局更好的方法。而只有一个标题则使用 span 标签实现。请再次解释一下评论和 downvote 的原因,谢谢。 - dippas
@dippas,Anthony Rutledge也给我点了踩。他含糊地评论说“目标和覆盖”,而我的答案中有类切换。所以显然他要么没有费心去真正阅读答案,要么无法理解问题和/或答案。 - zer00ne
2
显然,你对这个问题的理解不比我好;)虽然我理解了你的观点,但并没有完全理解这个问题的全部要点。这就是为什么我认为在这里给出的(几乎每一个)答案中连续投票反对是不公平的。 - dippas
1
感谢您的努力,dippas。一艘声誉之舟正朝着您驶来 :) - Mchl
1
哈哈,我在这个问题上真的玩得很开心。无论如何,@dippas 的回答很好。我还看了一些你写的其他答案,它们也非常好。我做了一些笔记。总之恭喜! :) - Jaqen H'ghar
显示剩余14条评论

7

简而言之,我在CSS中更改默认显示属性是否是一种不良实践?

不是。正如W3C所表达的那样; HTML传达的是含义,而不是呈现

作为HTML作者,您的工作是构建一个页面,使页面的每个部分都具有文档描述的预期语义,以便软件(浏览器,屏幕阅读器,机器人等)可以正确地解释您的内容。

作为CSS作者,您的工作是更改正确标记的默认样式,以呈现您想要的方式。这包括像更改默认color一样更改默认display属性。

但是,任何软件都可以决定某些CSS属性的使用方式会改变它们解释您的页面的方式。例如,搜索引擎可能会决定与其父级background颜色相同的文本对于其排名系统不产生影响。

关于副标题,使用 <hX> 元素标记副标题是不正确的。您应该决定一个 <hX> 元素,在其外部包装一个 <header> 元素,并在其中使用 <p><span> 或类似元素来标记副标题文本。
以下是来自 W3C 文档的正确副标题示例:
<header>
  <h1>HTML 5.1 Nightly</h1>
  <p>A vocabulary and associated APIs for HTML and XHTML</p>
  <p>Editor's Draft 9 May 2013</p>
</header>

注意,W3C规范和WHATWG规范存在差异,后者使用<hgroup>元素来达到特定目的,而前者已经将其弃用。个人建议遵循W3C的示例,但是如果你更喜欢WHATWG的方法,大多数软件仍然能够理解hgroup元素,可能在未来很多年内都能够理解。实际上,有些人认为当规范不同时应该遵循WHATWG而不是W3C。
在您的特定示例中,我不确定为什么您首先选择将<h1>拆分为两个元素。如果您标记为<h1>的内容实际上应该是标题的通用“标签”,那么它可能应该被视为子标题。如果您需要为了样式目的而拆分它,请将文本的两个部分包装在<span>中,如下所示:
<h1>
  <span>Header:</span>
  <span>my header</span>
</h1>

谢谢您的回答,尼尔斯。我真的希望能够以某种方式在您和 @dippas 之间分配奖赏。 - Mchl

4

简而言之,更改CSS中的默认显示属性是否是一种不好的做法?

这是一个好的做法,但需要谨慎选择何时使用它,因为它可能会导致一些关键的结构错误。

为什么这是一个好的做法

display属性可以进行更改。它使HTML简单和通用。 HTML元素带有与一般行为相匹配的默认display值 - 你通常想要的。但是它们不必保留并围绕另一个display属性进行操作。例如,考虑<div>。显然,大多数情况下您希望它具有display:block;,但是在某些情况下,display:flex;更加合适。

让我们看一个非常常见的列表示例。<li>带有list-item的显示属性,该属性会在每个新项中断行。

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

但是水平列表也非常常见。那么为什么没有专门的元素用于水平列表项?为每个常见的display行为编写特殊元素会增加复杂性。相反,惯例是将<li>的显示属性设置为inline,正如W3C所建议的(链接)

ul li {
  display:inline;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

display: inline-block; 代替 float

多年来,float 在页面布局中被广泛使用。问题在于它并不是为此任务而创建的,最初是设计用于环绕元素的文本。众所周知的一个float问题是未浮动的元素不识别浮动子元素,因为它们被从文档的正常流中移除了。你也无法将元素居中浮动,只能限制于左浮动或右浮动。

display 更适合于布局。 display: inline-block; 告诉浏览器将该元素放置在一行内,但要将其视为块级元素。这意味着我们可以使用inline-block 代替浮动,使一系列元素并排显示。它更直观,消除了浮动时需要添加的 <div class="clearfix"></div> 这种 额外的非语义化元素

当需要让其他页面内容围绕一个元素流动时,浮动很有用。但是并不总是需要将它们用于复杂的布局。

更改 display 时要避免的事情

更改 display 属性时请记住:

设置元素的显示属性只会改变元素的显示方式,而不会改变元素的类型。

<span> 测试案例:

在 HTML 的早期版本中,<span> 被认为是内联级元素,而 <div> 是块级元素。内联级元素不能包含块级元素。给 <span> 设置 display:block; 不会改变其类别。它仍然是内联级元素,并且仍然不能包含 <div>

HTML5引入了内容模型。每个HTML元素都有一个内容模型:对元素预期内容的描述。HTML元素必须具有与元素内容模型中描述要求相匹配的内容。<span>只能包含短语内容。这意味着您仍然不能在<span>中嵌套<div>(流内容)。给<span>一个display:block;仍然不会改变它。
span {
  display:block;
}

<span>
  <div>
    Still Illegal!
  </div>
<span>

总之,改变默认的display属性确实是我们的基本操作。请记住,它只会改变元素的显示方式,而不会改变元素类型,请正确使用。
现在让我们来谈谈最初的两个标题问题:
关于评论:
假设出于问题的需要,我们需要有两个标题。或者我们暂时忘记标题。 -作者
还有这个评论:
这个问题不是关于全局重置显示值。使用选择器只针对特定的元素是隐含的。问题是一旦选择了这些元素,我们应该怎么做。-悬赏者
可以通过多种方式将两个并排的标题放在一起,不仅用于处理移动布局更改。原始示例简单且正确,因此实际上是一个好方法。

h1, h2 {
  display: inline;
}
<div class="container">
    <h1>Header:</h1>
    <h2>my header</h2>
</div>

它遵循HTML规则,不需要任何额外的技巧。

1
@AnthonyRutledge 为什么要对一个明显花费了很多心血的0分答案进行贬低?你不认为评论已经足够了吗?无论如何,你能否请详细解释一下你的评论?我试图理解它,我发誓我真的尽力了...我也阅读了你在dippas回答中的所有评论,但是还是没有理解...请不要讽刺,并且如果可以,请用我的答案作为例子来解释。谢谢,我会感激不尽。 - Jaqen H'ghar
1
@努力不会抵消你答案的错误之处。我已经解释了,针对和覆盖是CSS优雅性的一部分。显示属性在各种结构化HTML元素上基本上是跨浏览器的(浏览器样式表)。填充和边距是不同的,因为它们在跨浏览器方面可能非常不同。这就是CSS重置被发明的原因。媒体查询被创建来解决这个问题带出的许多问题。没有必要更改给定元素的显示属性的默认值。这只是愚蠢的。 - Anthony Rutledge
@Melinda 是的,我想你是对的... 我只是想知道我的答案有没有问题。 - Jaqen H'ghar
1
我真的很喜欢JaqenH'ghar的回答。它提到了其他答案没有涉及到的一些有趣的话题。然而,我觉得@dippas的回答以最直接和全面的方式回答了这个问题。 - Mchl
1
@Mchl 谢谢!我也喜欢dippas的回答,所以我试图涵盖其他主题。他值得获得奖励,所以我很高兴他得到了它 :) 感谢您的积极反馈! - Jaqen H'ghar
显示剩余12条评论

2

修改默认行为是多余的,甚至可能影响性能。作为一种主观解决方案,建议使用flex(但我不确定它的性能如何,您可以在谷歌上搜索),它得到广泛支持,并且不会改变任何元素的CSS属性,只是一个布局问题,查看此内容。

.container {
  display: flex;
  justify-content: flex-start;
  flex-direction: column;
  align-items: baseline;
}
.container.mobile {
  flex-direction: row;
}
web
<div class="container">
  <h1>Header:</h1>
  <h2>my header</h2>
</div>
<hr />
mobile
<div class="container mobile">
  <h1>Header:</h1>
  <h2>my header</h2>
</div>

请注意,h1的样式保持不变。

谢谢你的回答。 - Mchl

1
改变默认的CSS属性并不是一个好主意,应该避免这样做以防止标记中出现不必要的缺陷。相反,您应该给想要自定义的所有HTML元素赋予“id”或更好的“class”,并对其进行样式设置。
此外,像“h1”,“div”等使用CSS是最慢的方式,因为引擎试图在页面中找到所有这些元素。
在您的示例中,只要给您的h1元素设置了CSS类,使用display或float都没有关系。
此外,使用正确的HTML元素以获得更好的语义可以对SEO等事项有用。

那只是一个简单的例子。但如果我添加类,基于类来更改显示是否仍然是一个好的实践呢? - dotintegral
1
是的,这是最佳实践。事实上,这就是应该的方式。类存在的目的是为了区分同一页面中外观不同的相同元素。 - abeyaz
5
改变默认 CSS 属性为什么是个坏主意?所有元素都有分配给所有属性的默认值,因此您编写的任何 CSS 都将更改默认值。 - Nils Kaspersson
重点是,更改tags上的属性可能不是一个好主意。相反,只更改您想要更改的内容。例如,span { display: block; }可能不是一个好主意,但是span.blockspan { display: block; }#myspan { display: block; }.blockspan { display: block; }可以更好地完成工作,并且不会影响页面上其他部分的任何内容。 - Nikhil Girraj

1

更新

看起来我可能没有很清楚地展示Plunker,因为Anthony Rutledge显然没有看到(或者忽略了)它。我提供了一张截图,并给出了一些关于如何使用Plunker的提示。

PLUNKER - 嵌入

PLUNKER - 信息

PLUNKER - 预览

Plunker iNFO

问答

这引出了一个简单的问题:更改HTML元素的默认显示属性是一种不好的做法吗?

不,不是。事实上,这是Web开发人员(包括我自己)经常进行的一种做法,不仅更改元素的属性,还有属性和内容等。

这是否违反标准,应该尽可能避免?

不,但也许做法本身可能会破坏代码,这比标准更重要。标准当然很重要,但并非必不可少。如果这是情况,那么Web浏览器应该遵守一个共同的标准(我在和你说话,IE :P)。以下是应该避免的几个事项:

  • Using the table element for a layout

     <table>
       <tbody>
           <tr>
            <td><img></td>
            <td><input type="button"/></td>
           </tr>
     ...
    
  • Using inline styles

      <div style="display: inline-block"></div>
    
  • Using inline event handlers

      <div onclick='makeASandwich();'></div>
    
“对于编程来说,只要代码语义正确(例如标题放在h1中,文章放在article中等),那么更改元素的显示属性是非常微小但基本必要的方面。所以,我想它可以被认为是‘面包和黄油’,这使得语义学成为‘作为装饰品使用的欧芹而从未被食用的东西’。语义学是主观的,是一种思维方式,而不是标准。我认为初学者应该意识到它的重要性(或者至少了解它对其他人的重要性),但不应该在<article><section>之间进行死板的辩论,哪一个在语义上比使用<main><aside>更好。随着时间的推移,语义学会变得‘自然而然’。”

方法一:使用display:inline

我从未找到过使用display:inline的好理由,因为display:inline-block是一个更好的选择

方法二:使用float

浮动是易碎的古董。就像处理奶奶的骨瓷晚餐盘一样,如果你打算使用它们,必须采取某些预防措施。要注意如何清除浮动,不要把它们扔进洗碗机。

基本上,如果只有这两个选项,方法一是更好的选择,特别是如果使用inline-block。我会避免使用floats,它们很反直觉并且容易出问题。我记得只用过一次,因为客户想要文字环绕图片。


CSS & CSS/JS

Provided is a Snippet comprising of 3 demos:

  1. Pure CSS solution utilizing display: flex.

  2. Pure CSS solution utilizing display: table-row/table-cell.

  3. CSS and minimal JavaScript solution utilizing display: inline-block and the classList API

Each of these demos are identical on the surface:

HTML

  <section id="demo1" class="area">
    <!--==Pure CSS Demo #1==-->
    <!--======Flexbox=======-->
    <header class="titles">
      <h1>Demo 1 -&nbsp;</h1>
      <h2>display: flex</h2>
    </header>
   </section>

This is the original markup with the following changes:

  • div.container is now header.titles

  • h1 text is: "Demo #n"

  • h2 text is: "prop:value"

  • section#demo#n.area is wrapped around everything.

This is a good example of semantics: Everything has meaning

You'll notice at the bottom of the viewport, are buttons. Each button corresponds to a demo.

Details on how each demo works as well as pros and cons are in the following files located in the leftside menu of the Plunker (see screenshot):

  • demo1.md flexbox
  • demo2.md disply: table
  • demo3.md classList

PLUNKER


These notes are not for the purpose of informing the OP of anything relevant to the question. Rather they are observations that I would like to address later on.

Further Notes

  • Demo 1 and demo 2 are powered by the pseudo-class :target. Clicking either one of them will trigger the click event It resembles an event because it's invoked by a click, but there's no way of controlling, or knowing the capture or bubbling phase if it actually exists. Upon further clicking of the first and second button, it will exhibit odd behavior such as: toggling of the other button then eventually becoming non-functional. I suspect the shortcomings of :target is that CSS handles events in a completely different way with little or no interaction with the user.

目标和覆盖。 - Anthony Rutledge
嗯...是的,请看一下我的Plunker,第三个演示是切换类。我的Plunker有3个演示,涵盖了3种不同的操作display的方式。其中2个是纯CSS解决方案,因为有CSS标签但没有JS。我还提供了另一种带有一些JS的更好的替代方案。当您投反对票时,请仔细阅读答案。最好先留下评论,等待回复,如果回复不令人满意,那么请通过投反对票来表达您对糟糕答案的不满。如果我没有理解您的陈述,请详细说明。 - zer00ne
这一切都归结为一个简单的问题:更改HTML元素的默认显示属性是否是一种不良实践? - Anthony Rutledge
1
inline-block并不总是比inline更好的选择。有时候,你希望内联级元素生成一个内联框而不是块容器。例如,你想在段落中使用<em>强调一些文本,并希望它可以在多行之间换行。 - Oriol
我更在乎结果而不是言语。欢迎您 @Mchl,很有趣。缺少资源?我有14个链接,SO确实应该考虑强调锚点。 - zer00ne
显示剩余4条评论

1
最佳实践是将两个标题分组在 hgroup 中,并使用 @media 查询更改移动设备和其他视图的显示属性。
<hgroup class="headingContainer">
  <h1>Main title</h1>
  <h2>Secondary title</h2>
</hgroup>

HTML 元素(HTML 标题组元素)代表一个部分的标题。它定义了一个单一的标题,作为隐式或显式属于的部分的标题参与文档的大纲。

由于 hgroup 为一个部分定义了单一的标题,因此在 hgroup 中更改显示属性并不是不好的做法。


hgroup已经过时,并且不再被任何浏览器官方支持。建议使用headerdiv - zer00ne

0

你应该使用:

$('element').css('display','');

这将根据当前的 CSS 级联设置显示为元素的默认内容。

例如:

<span></span>

$('span').css('display','none');

$('span').css('display','');

这将导致一个带有display: inline

但是:

span { display: block }

<span></span>

$('span').css('display','none');
$('span').css('display','');

这不是关于如何做到这一点的问题(还涉及jQuery)。而是关于应该做什么的问题。 - Mchl

-1

你也可以使用弹性盒子(flex box)来排列元素,就像这样

<div class="container" style="display: flex;">
    <h1>Header:</h1>
    <h2>my header</h2>
</div>

试着阅读一下这篇关于flex的教程,它非常棒且易于使用 https://css-tricks.com/snippets/css/a-guide-to-flexbox/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接