如何在<body>标签内独立于特定元素地插入CSS样式?

5

传统上,您可以通过以下三种方式添加 CSS:

  1. 通过 <link rel="stylesheet" href="foo.css"> 外部链接 CSS
  2. <head> 元素中通过 <style> h1 { ... } 的内部 CSS
  3. 针对特定元素的 style="..." 属性内联 CSS

内联 CSS 的缺点是我无法使用 CSS 类,而这恰恰是我需要做的事情。有没有一种方法来定义内部 CSS(例如在 <body> 元素中的 <style></style> 片段)?

这对我来说将更加容易,因为我可以创建一个自包含的 HTML 片段,并在我的服务器代码中使用方法。这个方法是必需的,因为我无法控制 <head> 部分。它归商业产品所有。我只能插入内容到 <body> 内。

例如:

<div>
 <style>
  .myclass {...}
 </style>
 <div class="myclass">...</div>
</div>

相关链接:https://htmx.org/essays/locality-of-behaviour/

我发现其他网站(如https://amazon.com)似乎在<body>内部有多个样式标签。

理论和实践之间存在巨大的差距。许多网站在中使用<style>

编辑们决定不这样做。但也许将来会有改变:https://github.com/whatwg/html/issues/1605


4
在HTML5标准中,必须将<style>标签添加在<head>元素内才有效。在其他任何位置都是无效的。有关详细信息,请参见此链接:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style 和 https://html.spec.whatwg.org/#the-style-element。 - Mihai T
1
好的 - 自定义 Web 组件 是否有用 - 它们可以包含自己的 CSS,不会传播到父 DOM,并且在组件内立即可用。 - Professor Abronsius
请查看此链接:https://stackoverflow.com/questions/38941889/how-to-apply-imported-stylesheet-to-template-tag-content-for-a-custom-element - Chris P
6个回答

7

假设您不关心与内的


如果规范和日常实践之间存在很大差异,你可以采取什么措施呢?是更改日常实践,还是调整规范? - guettli
没有访问<head>部分似乎是一种不寻常的做法。但请参阅此讨论。它似乎在HTML5.2 W3C中实现。_...应该小心使用..._。至少要注意未样式化内容的闪烁,通常是由放置在<body>中并在之后加载的样式引起的。这就是为什么我要防止它。FOUC和FOIT对用户不太友好。 - ztom

1
简单回答你的问题是“是”,我将通过下面的几个例子详细解释。无论您在 <head> 还是 <body> 中放置 <style> 标签,它都可以正常工作。
虽然在 <body> 标签中放置 style 标签从技术上违反了 HTML 语法规则,但在实践中,甚至一些大公司也经常这样做。
有几种不同的方法可以在项目中包含 <body> 级别的 <style> 标签。
1. 纯 HTML <style> 标签(静态方法)
如果您已经编写好所有需要的样式,并且没有需要动态生成的部分,您可以将这些样式静态地写入一个 <style> 标签中,并将其包含在代码中,如下面的示例所示:

<html>
  <head></head>
  <body>
    <div class="custom-widget">
      <h1>This is a title</h1>
      <p>This is some text.</p>
      <style>
        .custom-widget {
          display: block;
          padding: 20px;
          border: 5px double red;
        }
        .custom-widget h1 {
          text-transform: uppercase;
        }
        .custom-widget h1::first-letter {
          font-size: 150%;
        }
        .custom-widget p {
          font-style: italic;
        }
      </style>
    </div>
  </body>
</html>

2. 使用JavaScript将样式作为文本写入<style>标签

如果您需要动态地将样式加载到<style>标签中,并且只需要纯文本样式,而不需要在创建后进行太多更改。您可以创建<style>块,然后根据需要将CSS样式注入为纯文本,如下面的示例所示:

const counter = document.getElementById('counter');
  let count = +counter.dataset.count;
const customWidgetStyle = document.querySelector('.custom-widget style'),
      countdown = setInterval(() => {
        if (count--) {
          counter.innerText = `Importing CSS in ${count}…`;
        } else {
          clearInterval(countdown);
          counter.remove();
          customWidgetStyle.innerHTML = `
            .custom-widget {
              display: block;
              padding: 20px;
              border: 5px double red;
            }
            .custom-widget h1 {
              text-transform: uppercase;
            }
            .custom-widget h1::first-letter {
              font-size: 150%;
            }
            .custom-widget p {
              font-style: italic;
            }
          `;
        }
      }, 1000);
<html>
  <head></head>
  <body>
    <div class="custom-widget">
      <h1>This is a title</h1>
      <p>This is some text.</p>
      <style></style>
    </div>
    <span id="counter" data-count="3">Importing CSS in 3…</span>
  </body>
</html>

3. 使用JavaScript CSSStyleSheet.insertRule() 方法创建<style>标签中的cssRules样式

如果您需要更加灵活地添加样式,可以使用CSSStyleSheet.insertRule()方法(MDN文档),它将动态地允许您更加细粒度地添加和管理样式。这可能对于您的特定需求来说过于复杂,但是在使用CSSOM时有很多的强大、灵活和可控性。

以下是使用此方法的示例,其中我使用了MDN文档页面上定义的addStylesheetRules函数示例,在标题Examples下,此处

const addStylesheetRules = (rules, stylesheet) => {
  if (stylesheet === undefined) {
    const style = document.createElement('style');
    stylesheet = style.sheet;
    document.head.appendChild(style);
  }
  for (let i = 0; i < rules.length; i++) {
    let j = 1,
        propStr = '';
        rule = rules[i];
    const selector = rule[0];
    if (Array.isArray(rule[1][0])) {
      rule = rule[1];
      j = 0;
    }
    for (let pl = rule.length; j < pl; j++) {
      const prop = rule[j];
      propStr += prop[0] + ': ' + prop[1] + (prop[2] ? ' !important' : '') + ';\n';
    }
    stylesheet.insertRule(selector + '{' + propStr + '}', stylesheet.cssRules.length);
  }
}

const customWidget = document.querySelector('.custom-widget'),
      customWidgetStyleTag = document.createElement('style');
customWidget.appendChild(customWidgetStyleTag);
const customWidgetStylesheet = customWidgetStyleTag.sheet;
addStylesheetRules([
  ['.custom-widget',
    ['display', 'block'],
    ['padding', '20px'],
    ['border', '5px double red']
  ],
  ['.custom-widget h1',
    ['text-transform', 'uppercase']
  ],
  ['.custom-widget h1::first-letter',
    ['font-size', '150%']
  ],
  ['.custom-widget p',
    ['font-style', 'italic']
  ]
], customWidgetStylesheet);
<html>
  <head></head>
  <body>
    <div class="custom-widget">
      <h1>This is a title</h1>
      <p>This is some text.</p>
    </div>
  </body>
</html>


请告诉我是否还有其他上下文可以添加,以更好地回答您的问题。


“specificity”部分似乎完全不相关。你为什么要包括它?特异性与所提出的问题无关。如果删除整个部分,这个答案会更好。 - TylerH
@TylerH 我想讲一下将CSS包含在组件内部而不是头部本身的具体优势,但为了让我的回答更简洁,我会将其删除。谢谢。 - Brandon McConnell

0

你不能使用JavaScript来定位 head 元素并编写程序插入样式吗?

<script>
  var head = document.querySelector('head')[0];
  var css = 'div { background: red; }',
    
  var style = document.createElement('style');

  style.appendChild(document.createTextNode(css));

  head.appendChild(style) ;

</script>

0
据我理解,根据您提供的描述,您无法访问<head>...</head>元素,但可以自由编辑正文。此外,您想要使用CSS3类,但是在内联CSS中,您无法这样做。
我无法找到纯HTML/CSS的方法,因此建议您使用JQuery。
<script async src="https://cdn.statically.io/libs/jquery/3.6.0/jquery.min.js" />
<script>$('head').append('<style>/*Your styles here*/</style></script>');


现在,将类添加到html元素中并编辑<style />标签之间的内容。
此外,将此脚本放置在<body>的末尾,以避免将其放置在其中可能引起的奇怪问题。 XD
但请记住,这将在用户加载页面更改头部。 因此,理论上,用户将首先看到没有样式的丑陋html页面,然后再加载样式,他们会看到带有样式的页面。
有关更多解释,请查看官方文档:https://api.jquery.com/append/


1
请添加更多细节以扩展您的答案,例如工作代码或文档引用。 - Community

0

你的例子应该可以工作。我使用自定义HTML来使用WordPress,其中所有自定义代码都放在<body>标签中,像这样的样式应该可以在每个页面中工作(添加了更多的div只是为了展示一个例子,一个样式标签可以包含一个div内所有div的类):

<div> 
   <style> 
      .className { ... }
      .classNameTwo{ ... } 
      .classNameThree{ ... }
   </style>
   <div class="className"></div>
   <div class="classNameTwo">
      <div class="classNameThree"></div>
   </div>
</div>

0

它将在HTML5中工作,即使在HTML4中被视为无效。
我现在的工作中有一个例子。

我们正在为图书馆目录中的一些书籍添加幻灯片,因为这是使用插件完成的,所以唯一可能的样式方法是在HTML中包含<style>块,因为此插件没有且不应该访问所设计的CMS的<head>

但是,由于CMS的构建限制,这种解决方案是最后的选择,应该避免使用。


2
这些信息已经过时了 - 支持scoped样式的计划早已被放弃(https://github.com/w3c/csswg-drafts/issues/137)。 - vsync
@vsync 我希望我能鼓励你友好地行事,不过这可能需要你自己的决定。 - Timothy Alexis Vass

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