将<body>中的<style>标记与其他HTML一起使用


195
<html>
  <body>
    <style type="text/css">
      p.first {color:blue}
      p.second {color:green}
    </style>

    <p class="first">Hello World</p>
    <p class="second">Hello World</p>

    <style type="text/css">
      p.first {color:green}
      p.second {color:blue}
    </style>

    <p class="first">Hello World</p>
    <p class="second">Hello World</p>
  </body>
</html>

浏览器应如何呈现不连续的CSS?是否应该使用页面上的所有CSS样式生成一些数据结构并将其用于呈现?

还是按照看到的顺序使用样式信息进行渲染?


2
我说这是未定义的行为,因为它不是有效的HTML。有关更多信息,哪些元素有效,哪些无效:en.wikipedia.org/wiki/HTML_element
Felix Kling,2010年

2
抛开这个问题,将CSS和混淆是一个不好的做法HTML
0x2D9A3'5

1
@ 0x2D9A3不一定为true。请求外部CSS页面所需的时间比<head>标记中定义的CSS所需的时间更长
Kolob Canyon

@KolobCanyon同意,但是作为一般规则,CSS应该在单独的文件中。如果您有大量的CSS,则既易于管理(维护,(后处理),缩小,捆绑),又可以作为单独的文件使用,并且内容(HTML)的加载速度也可能更快,从而带来更好的UX。但是,与开发一样,所有内容都是特定于上下文的,因此YMMW :)
0x2D9A3

3
@KolobCanyon,这不是CSS是否应放在单独文件中的问题。在这种情况下,问题是关于<body>而不是中的CSS <head>
雷·巴特沃思

Answers:


312

正如其他人已经提到的那样,HTML 4要求将<style>标记放置在<head>部分中(即使大多数浏览器都允许在<style>标记内body)。

但是,HTML 5包含该scoped属性(请参见下面的更新),该属性使您可以创建在<style>标签的父元素内作用域的样式表。这也使您能够将<style>标签放置在<body>元素中:

<!DOCTYPE html>
<html>
<head></head>
<body>

<div id="scoped-content">
    <style type="text/css" scoped>
        h1 { color: red; } 
    </style>

    <h1>Hello</h1>
</div>

    <h1>
      World
    </h1>

</body>
</html>

如果您在支持的启用了HTML-5的浏览器中呈现上述代码scoped,则会看到样式表的有限范围。

只有一个主要警告...

在我撰写此答案时(2013年5月),目前几乎没有主流浏览器支持该scoped属性。(尽管显然开发人员可以使用Chromium来支持它。)

但是,scoped与此问题相关的属性有一个有趣的含义。这意味着将来的浏览器将通过该标准进行授权,以允许<style>元素在范围内<body>(只要这些<style>元素是作用域内的)。

因此,鉴于:

  • 当前几乎所有现有的浏览器都忽略该scoped属性
  • 目前,几乎所有现有的浏览器都允许<style><body>
  • 要求将来的实现方式允许<style><body>

...那么只要您将来使用属性证明标签,在体内放置标签实际上不会任何危害 * 。唯一的问题是,当前的浏览器实际上不会限制样式表的范围,而是将其应用于整个文档。但关键是,出于所有实际目的,您可以在所提供的内容中包含标签:<style>scoped<style><body>

  • 通过包含scoped属性,使HTML面向未来
  • 请了解,到目前为止,内的样式表<body>实际上不会进行范围调整(因为尚不存在主流的浏览器支持)


*当然除外,用于激怒HTML验证器...


最后,关于常见的(但主观的)主张将CSS嵌入HTML的做法不佳,应该注意的是,该属性的要点scoped是适应典型的现代开发框架,该框架允许开发人员将HTML的大块作为模块或联合内容导入。 。使用嵌入式CSS 适用于特定的HTML块非常方便,以便开发具有特定样式的封装的模块化组件。


根据Mozilla文档,自2019年2月开始更新,该scoped属性已弃用。Chrome在版本36(2014)和Firefox版本62(2018)中不再支持它。在这两种情况下,都必须由用户在浏览器的设置中显式启用该功能。没有其他主流浏览器支持它。


3
@RobertMcKee:您真的测试过吗?我希望通常在呈现之前就对整个html页面(包括所有内联样式)进行解析,因为通常它不大,浏览器在呈现之前(很短)会等待一会(很短),以免出现可能会出现的未样式化内容由于CSS链接在中head如果这是你唯一的CSS,并且如果该页面是大,如果网络连接不是很快,那么也许你会看到无样式内容的闪光灯,但它会在大多数实际情况让我感到吃惊。
Eamon Nerbonne

4
截至目前,仅Firefox支持范围内的样式元素(根据caniuse.com/#feat=style-scoped)。并且由于常见的浏览器仅支持BODY内的STYLE元素,因此如有必要,我将使用它。如果CSS应该在范围内应用,则可以在CSS源代码中的每个选择器前面加上包装器的ID /类。我实际上是在一个Web应用程序中执行此操作的,该Web应用程序在服务器端加载了HTML报告并通过AJAX呈现了它们。然后可以在JavaScript中使用简单的正则表达式为CSS加上前缀:cssString.replace(/(^ | \})([^ {] +)(\ {)/ g,'$ 1'+前缀+'$ 2 $ 3')
Adam Hošek2016年

5
支持@scoped,或scoped似乎正在消亡:在这里这里
Kiran Subbaraman

51
支持@KiranSubbaraman:我刚刚(2016年7月)在mozilla dev上阅读:“ 只有经过有限的实验性使用,Chrome和Firefox才将scoped属性从规范中删除您应该避免使用它,因为几乎可以肯定的是从这些浏览器中删除。” >> developer.mozilla.org/en-US/docs/Web/HTML/Element/...
jave.web

9
scoped属性已从当前的HTML5规范中删除。
阿尔伯特·维尔施

61

坏消息的“风格体”爱好者:W3C最近失去了HTML战争对WHATWG,其versionless HTML“生活标准” 现在已经成为了一个官方的,这,唉,不会允许 STYLEBODY。短暂的快乐日子已经过去。;)W3C验证器现在也可以通过WHATWG规范工作。(感谢@FrankConijn的单挑!)

(注意:“从今天开始”就是这种情况,但是由于没有版本控制,链接随时可能在没有通知或控制的情况下变为无效。除非您愿意链接到GitHub上的单个源提交,否则您基本上无法不再稳定引用新的官方HTML标准 AFAIK。如果有正确的规范方法,请更正我。)

过时的好消息:

耶,STYLE终于在有效的BODY,作为HTML5.2的!scoped也消失了。)

W3C规范请看最后一行!):

4.2.6。样式元素

...

可以使用此元素的上下文:

预期元数据内容的位置。

在noscript元素中,它是head元素的子元素。

在体内,预期流量含量。


元数据旁注:

尽管“浏览器之战”遭到了破坏,但我们仍然必须继续面对两个荒谬可笑的 “官方” HTML“标准”(引号1 standard + 1 standard < 1 standard)发展这一事实,这意味着“退缩到常规的常识”方法Web开发从未真正停止应用。

现在,这种情况可能最终会改变,但要引用传统的常识:当没有充分的理由反对已经在其中进行的操作时,网络作者/开发人员以及浏览器应最终决定规范中应(不应该)的内容。现实。而且大多数浏览器长期以来STYLEBODY(以一种或另一种方式;例如参见scopedattr。)提供了支持,尽管它具有固有的性能(以及其他可能的)损失(我们应该决定是否支付,而不是规格)。因此,对于我来说,我将继续押注于他们,而不会放弃希望。;)如果WHATWG像他们声称的那样尊重现实/作者,那么他们可能最终会像W3C那样做。


3
我看了规格,但听不懂。您能否stylebody验证中提供一个示例代码块?
Frank Conijn

3
@FrankConijn:好点,事情变了,更新了答案!真是令人困惑。W3C 5.2和5.3规范都将其STYLE视为元数据和流内容,但是最新的WHATWG“活着”规范却讲述了古老而乏味的“仅元数据”故事(仅在HEAD中允许使用)。而且,更糟的是,W3C验证程序似乎遵循WHATWG的风格。我还没有决定是笑还是哭,但是我个人决定决定对“浏览器+ W3C-验证程序”案例“犯错”,并允许STYLE进入BODY。(顺便说一句,别忘了:实际上,我们应该成为标准的最终来源。)
Sz。

我真的认为他们用这种胡言乱语了,如果您想在模板化系统中动态设置背景图像属性,他们基本上别无选择,只能使用线型。将编程生成的样式块放在html输出上方的侵入性要小得多。
GovCoder

32

当我看到大型站点的内容管理系统通常将一些<style>元素(某些,不是全部)放在依赖于那些类的内容附近时,我得出结论,这匹马已经离开了谷仓。

请访问cnn.com,nytimes.com,huffingtonpost.com,您最近的大城市报纸等的网页资源。所有这些都可以做到。

如果有充分的理由在正文中放置一个额外的<style>部分-例如,如果您要实时地include()包含各种独立的页面元素,并且每个元素都有自己的嵌入式<style>,该组织将变得更清洁,更模块化,更易于理解且更易于维护-我说的只是硬着头皮。当然,如果我们可以在有限范围内使用“局部”样式(例如局部变量)会更好,但是您将使用已有的HTML,而不是稍后可能想要或希望拥有的HTML。

当然,正如其他人所阐述的那样,遵循正统观念有潜在的弊端和充分的理由(如果不是总是令人信服的话)。但在我看来,它越来越像是在<body>中对<style>进行周到的使用已成为主流。


1
实用主义FTW!
Waruyama

1
你是对的。例如,我在插件的<body>中使用<style>标记。为什么,因为这是获取时尚插件内容的最简单方法。但是有一段时间,所有css类对于我的插件数据都是唯一的。
Avirtum

7

无效的HTML,无论如何,几乎每个浏览器似乎都只考虑第二个实例。

在Fedora的FF和Google Chrome的最新版本以及XP的FF,Opera,IE和Chrome的最新版本下进行了测试。


6

我猜这会因浏览器而异:全局显示规则可能会随着浏览器浏览代码而更新。

有时在加载外部样式表时有延迟时,您会在全局显示规则中看到此类更改。类似的情况可能会在这里发生,但是连续的时间太短,实际上并没有被渲染。

无论如何,它不是有效的HTML,所以我想这是徒劳的。<style>标签属于head页面的部分。


5

正如其他人所说,这不是有效的html,因为样式标签位于头部。

但是,大多数浏览器并没有真正执行该验证。取而代之的是,一旦文档被加载,样式就会被合并并应用。在这种情况下,第二组样式将始终覆盖第一组样式,因为它们是遇到的最后一个定义。



3

在您的示例中,浏览器“不应该”做任何事情。HTML无效。要么触发错误恢复,要么解析器将其恢复。

在一个有效的实例中,多个样式表被视为一个接一个地出现,级联的计算是正常的。


1

因为这是HTML无效的,所以对结果没有任何影响……这仅表示HTML确实符合标准(仅出于组织目的)。为了有效,它可以这样写:

<html>
<head>
<style type="text/css">
  p.first {color:blue}
  p.second {color:green}
</style>
</head>
<body>
<p class="first" style="color:green;">Hello World</p>
<p class="second" style="color:blue;">Hello World</p>

我的猜测是浏览器将应用它遇到的最后一种样式。


1

我想这可能是有关有限上下文的问题,例如非程序员用户使用的Web系统上的WYIWYG编辑器,这限制了遵循标准的可能性。有时(例如TinyMCE),它是一个将您的内容/代码放入textarea标签中的库,该标签由编辑器呈现为大div标签。有时,它可能是这些编辑器的旧版本。

我认为:

  1. 这些非程序员用户没有与系统管理员(或机构的Webdev)接触的开放渠道,要求在系统的处包括一些CSS规则stylesheets。实际上,对于管理员(或webdev)而言,考虑到他们可能会有的请求数量,这是不切实际的。
  2. 该系统是旧系统,仍然不支持HTML的较新版本。

在某些情况下,如果没有使用style规则,这可能是非常糟糕的设计体验。因此,是的,这些用户需要自定义。好的,但是在这种情况下,解决方案是什么?考虑到在html页面中插入CSS的不同方式,我假设以下解决方案:


第一种选择:询问您的sysadm

询问您的系统adm在系统的处包括一些CSS规则stylesheets。这将是外部或内部CSS解决方案。如前所述,这可能是不可能的。


第二个选项:<link><body>

在标签上使用外部样式表body,即在您有权访问的区域使用link标签(即在站点上,在标签内而不是标签内)。一些消息来源说这还可以,但是“不好的做法”,例如MDNbodyhead

<link>元件可以在任一发生<head><body>元件,这取决于它是否有链路类型,它是身体-OK。例如,stylesheet链接类型为body-ok,因此<link rel="stylesheet">允许在body中使用。但是,这不是遵循的好习惯。将您的<link>元素与身体内容分开,将其放在内更有意义<head>

其他一些人则将其限制在本<head>节中,例如w3schools

注意:此元素仅出现在头部,但可以出现多次。

测试中

我在这里(台式机环境,在浏览器上)对其进行了测试,并且对我有用。创建一个文件foo.html

<!DOCTYPE html>
<html>
<head></head>
<body>
    <link href="bar.css" type="text/css" rel="stylesheet">
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
</body>
</html>

然后是位于同一目录的CSS文件bar.css

.test1 { 
    color: green;
};

好吧,如果您可以在机构系统的某个位置上载CSS文件,这似乎才有可能。也许是这样。


第三种选择:<style>开启<body>

在标签上使用Internet样式表body,即style在您有权访问的区域内使用标签(即在网站上,body标签内而不是head标签内)。这就是Charles SalviaSz在这里的答案。选择此选项时,请考虑他们的担忧。


第四,第五和第六种选择:JS方式

警报这些与修改<head>页面元素有关。机构的系统管理员可能不允许这样。因此,建议先征得他们的许可。

好的,假设授予了权限,则策略是访问<head>。怎么样?JavaScript方法。

第四个选项:新<link>功能<head>

这是第二个选项的另一个版本。在标签上使用外部样式表<head>,即在您有权访问的区域之外使用<link>元素(即在站点上,不在标签内,而是在标签内)。该解决方案符合MDNw3schools关于第二选项解决方案的建议,如上所述。将创建一个新对象bodyheadLink

为了通过JS解决问题,有很多方法,但是在以下代码行中,我演示了一种简单的方法。

测试中

我在这里(台式机环境,在浏览器上)对其进行了测试,并且对我有用。创建一个文件f.html

<!DOCTYPE html>
<html>
<head></head>
<body>
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
    <script>
        // JS code here
    </script>
</body>
</html>

里面的script标签:

var newLink = document.createElement("link");
newLink.href = "bar.css";
newLink.rel = "stylesheet";
newLink.type = "text/css";
document.getElementsByTagName("head")[0].appendChild(newLink);

然后在CSS文件的同一目录中调用bar.css(如第二个选项所示):

.test1 { 
    color: green;
};

正如我已经说过的:如果您可以在机构系统的某个位置上载CSS文件,这似乎才有可能。

第五个选项:新<style>功能<head>

在标签上使用新的内部样式表<head>,即在您有权访问的区域之外使用新<style>元素(即在网站上,不在标签内,而是在标签内)。将创建一个新对象bodyheadStyle

这是通过JS解决的。下面演示一种简单的方法。

测试中

我在这里(台式机环境,在浏览器上)对其进行了测试,并且对我有用。创建一个文件foobar.html

<!DOCTYPE html>
<html>
<head></head>
<body>
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
    <script>
        // JS code here
    </script>
</body>
</html>

里面的script标签:

var newStyle = document.createElement("style");
newStyle.innerHTML = 
    "h1.test1 {"+
        "color: green;"+
    "}";
document.getElementsByTagName("head")[0].appendChild(newStyle);

第六选择:使用现有<style><head>

在标签上使用现有的内部样式表<head>,即,在您可以访问的区域之外使用<style>元素(即,在网站上,不在标签内部,而是在标签内部)(如果存在)。将创建一个新对象或将使用一个对象(在此处采用的解决方案代码中)。bodyheadStyleCSSStyleSheet

从某些角度来看,这是有风险的。 首先,因为它可能不存在某些<style> 对象。根据实现此解决方案的方式,您可能会获得undefined回报(系统可能使用外部样式表)。 其次,因为您将编辑系统设计作者的作品(作者问题)。 第三,因为您所在机构的IT安全策略可能不允许这样做。因此,一定要征得许可才能这样做(与其他JS解决方案一样)

再次假设已授予许可:

您将需要考虑对这种方法可用的一些限制:insertRule()。建议的解决方案使用默认方案stylesheet,如果有的话,则在第一个方案中进行操作。

测试中

我在这里(台式机环境,在浏览器上)对其进行了测试,并且对我有用。创建一个文件foo_bar.html

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
    <script>
      // JS code here
    </script>
  </body>
</html>

里面的script标签:

function demoLoop(){ // remove this line
    var elmnt = document.getElementsByTagName("style");
    if (elmnt.length === 0) {
        // there isn't style objects, so it's more interesting create one
        var newStyle = document.createElement("style");
        newStyle.innerHTML =
            "h1.test1 {" +
                "color: green;" +
            "}";
        document.getElementsByTagName("head")[0].appendChild(newStyle);
    } else {
        // Using CSSStyleSheet interface
        var firstCSS = document.styleSheets[0];
        firstCSS.insertRule("h1.test2{color:blue;}"); // at this way (without index specified), will be like an Array unshift() method
    }
} // remove this too
demoLoop(); // remove this too
demoLoop(); // remove this too

解决方案的另一种方法是使用CSSStyleDeclaration对象(w3schoolsMDN上的文档)。但是考虑到覆盖系统CSS上现有规则的风险,这可能并不有趣。


第7个选项:内联CSS

使用内联CSS。这解决了问题,尽管取决于页面大小(在代码行中),代码的维护(由作者本人或其他指定人员)可能非常困难。

但是,根据您在机构中所处角色的背景或其Web系统安全策略,这可能是您唯一可用的解决方案。

测试中

创建一个文件_foobar.html

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <h1 style="color: green;">Hello</h1>
    <h1 style="color: blue;">World</h1>    
  </body>
</html>

严格回答加根提出的问题

浏览器应如何呈现不连续的CSS?

  1. 是否应该使用页面上的所有CSS样式生成一些数据结构并将其用于呈现?
  2. 还是按照看到的顺序使用样式信息进行渲染?

(引用改编)

为了获得更准确的答案,我建议Google使用以下文章:

  • 浏览器如何工作:现代网络浏览器的幕后花絮
  • 渲染树的构造,布局和绘制
  • “呈现”网页是什么意思?
  • 浏览器渲染的工作原理-幕后
  • 渲染-HTML标准
  • 10渲染-HTML5

+1个好主意,包括脚本标签并使用JavaScript添加CSS,这对于愚蠢的所见即所得CMS编辑器来说是完全合法的HTML
djolf

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.