<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样式,并使用它进行渲染?

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


当前回答

因为这是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>

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

其他回答

对于“体内风格”爱好者来说,有一个坏消息:W3C最近在与WHATWG的HTML战争中失败了,WHATWG的无版本HTML“生活标准”现在已经成为官方标准,唉,它不允许体内风格。短暂的快乐时光一去不复返。,)W3C验证器现在也根据WHATWG规范工作。(谢谢@FrankConijn的提醒!)

(注意:这是“今天”的情况,但由于没有版本控制,链接可能在任何时候无效,而不通知或控制。除非你愿意链接到它在GitHub上提交的单个源代码,否则你基本上不能再稳定地引用新的官方HTML标准AFAIK。请纠正我,如果有一个规范的方法来正确地做这件事。)

过时的好消息:

耶,STYLE终于在BODY中生效了,从HTML5.2开始! (scoped也消失了。)

来自W3C规范(注意最后一行!):

4.2.6. 风格元素 ... 可以使用此元素的上下文: 需要元数据内容的地方。 在noscript元素中,它是head元素的子元素。 在正文中,期望流内容的地方。


元附注:

尽管遭受了“浏览器战争”的破坏,但我们仍然必须继续针对两个相互竞争的“官方”HTML“标准”(1个标准+ 1个标准< 1个标准)进行开发,这意味着“退回到战壕常识”的web开发方法从未真正停止应用。

This may finally change now, but citing the conventional wisdom: web authors/developers and thus, in turn, browsers should ultimately decide what should (and shouldn't) be in the specifications, when there's no good reason against what's already been done in reality. And most browsers have long supported STYLE in BODY (in one way or another; see e.g. the scoped attr.), despite its inherent performance (and possibly other) penalties (which we should decide to pay or not, not the specs.). So, for one, I'll keep betting on them, and not going to give up hope. ;) If WHATWG has the same respect for reality/authors as they claim, they may just end up doing here what the W3C did.

浏览器的真正功能是什么?

这又是一场理论与实践的辩论。没有真正的赢家。 首先让我给你们看一个CodePen:

https://codepen.io/dkellner/pen/gOzXGjz?editors=1100

CSS:

.jeff { background:red; transform:rotate(2deg); color:white; }

HTML:

<style> .jeff { margin:20% 0 0 20%; width:400px; } </style>
<div class="jeff">
  
    This is Jeff.

    <style> .jeff {background:blue; padding:40px;} </style>
</div>

<style> .jeff {background:green} </style>

解释

在这个例子中,我使用了4个不同的样式块。一个直接放在CodePen的CSS盒子里,他们会把它放在一个很好的地方,可能在头部之类的地方。下一个在div之前,然后在div里面,最后一个在div之后。杰夫现在经历了很多事。他是绿色的,因为这是最后一个规则告诉他的,但他也被旋转和定位,里面的文本是白色的,所以我们可以安全地说他已经阅读了样式标签告诉他的所有内容,并且:

应用了所有的样式块; 它们的应用顺序是正确的; 它们完全凌驾于彼此之上; 整个过程就像一个大样式表。

这就是发生的事情。

同样,浏览器是耐心的野兽。他们想让你享受互联网,而创建网站的人没有很好的纪律,所以浏览器进化到可以容忍他们疯狂的行为。

底线

是的,你可以在主体中放置样式标签 是的,正如你所期望的那样 尽可能避免,这是一个持续的争论,谁知道我们最终会在哪里结束。

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

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

我想这可能是关于有限上下文的问题,例如,非程序员用户使用web系统上的wywyg编辑器,这限制了遵循标准的可能性。有时(像TinyMCE),它是一个库,把你的内容/代码在一个文本区域标签,这是由编辑器渲染为一个大的div标签。有时,它可能是这些编辑器的旧版本。

我假设:

这些非程序员用户没有与系统管理员(或机构的web开发人员)开放的渠道,要求在系统的样式表中包含一些CSS规则。实际上,这对管理员(或web开发人员)来说是不切实际的,考虑到他们会有这样的请求数量。 这个系统是遗留的,仍然不支持更新版本的HTML。

在某些情况下,没有使用样式规则,可能是一个非常糟糕的设计体验。所以,是的,这些用户需要定制。好的,但是在这种情况下,解是什么呢?考虑到在html页面中插入CSS的不同方法,我认为这些解决方案:


第一个选择:询问你的系统管理员

要求系统管理员在系统的样式表中包含一些CSS规则。这将是一个外部或内部的CSS解决方案。如前所述,这可能是不可能的。


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

在主体标签上使用外部样式表,即在您可以访问的区域内使用链接标签(即,在网站上,在主体标签内而不是在头部标签内)。一些消息来源说这是可以的,但“不是一个好的做法”,比如MDN:

<link>元素既可以出现在<head>元素中,也可以出现在<body>元素中,这取决于它的链接类型是否为body-ok。例如,样式表链接类型是body-ok,因此<link rel="stylesheet">在正文中是允许的。然而,这并不是一个好的实践;将<link>元素从body内容中分离出来,将它们放在<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> on <body>

在主体标签上使用互联网样式表,即在您有权访问的区域内使用样式标签(即,在网站上,在主体标签内而不是在头部标签内)。这就是Charles Salvia和Sz的答案。选择这个选项时,要考虑他们的担忧。


第4、5、6个选项:JS方式

警报 这些元素与修改页面的<head>元素有关。也许学校的系统管理员不允许这样做。所以,建议先征求他们的同意。

假设许可被授予,策略是访问<head>。怎么做?JavaScript方法。

第四个选项:在<head>上新建<link>

这是第二个选项的另一个版本。在<head>标签上使用外部样式表,即在您可以访问的区域之外使用<link>元素(也就是说,在站点上,不在body标签内,在head标签内)。这个解决方案符合上文提到的MDN和w3schools关于第二种解决方案的建议。将创建一个新的Link对象。

要通过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>

在脚本标签内部:

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文件,这将看起来是可能的。

第5个选项:新建<style> on <head>

在<head>标签上使用新的内部样式表,即在您可以访问的区域之外使用新的<style>元素(也就是说,在站点上,不在body标签内,在head标签内)。一个新的Style对象将被创建。

这是通过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>

在脚本标签内部:

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

第6个选项:在<head>上使用现有的<style>

在<head>标签上使用现有的内部样式表,即在您可以访问的区域之外使用<style>元素(也就是说,在站点上,不在body标签内,在head标签内),如果存在的话。将创建一个新的Style对象或使用一个CSSStyleSheet对象(在这里采用的解决方案的代码中)。

从某种角度来看,这是有风险的。 首先,因为它可能不存在某个<style>对象。根据实现此解决方案的方式,可能会得到未定义的返回值(系统可能使用外部样式表)。 其次,因为您将编辑系统设计作者的工作(作者身份问题)。 第三,因为你所在机构的it安全政策可能不允许这样做。 所以,这样做的时候一定要征求许可(就像在其他JS解决方案中一样)。

假设,再次允许:

您需要考虑这种方法的一些限制:insertRule()。建议的解决方案使用默认场景和第一个样式表上的操作(如果存在的话)。

测试

我在这里测试了它(桌面环境,在浏览器上),它适合我。 创建一个文件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>

在脚本标签内部:

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对象(w3schools和MDN的文档)。但是考虑到覆盖系统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是不连续的? 它是否应该生成一些数据结构,使用页面上所有的css样式,并使用它进行渲染? 还是按照看到的顺序使用样式信息进行渲染?

(引用改编)

为了得到更准确的答案,我建议阅读以下文章:

浏览器如何工作:现代网络浏览器的幕后 渲染树的构造、布局和油漆 “渲染”网页意味着什么? 浏览器渲染是如何工作的——在幕后 渲染- HTML标准 10渲染- HTML5

我想这将因浏览器的不同而有所不同:全局显示规则可能会随着浏览器运行代码而更新。

当外部样式表加载延迟时,有时可以在全局显示规则中看到此类更改。类似的事情也可能发生在这里,但在如此短的连续时间内,它实际上没有被渲染。

无论如何,它都不是有效的HTML,所以我认为考虑它是徒劳的。<style>标签属于页面的头部部分。