71

我有一些代码,例如在 html 中

<html>
 <body>
  <img src='an image source'/>
  <h1>Hi it's test</h1>
  <div id='mydiv'>
    <img src='an image source'/>
    <h1>Hi it's test</h1>
  </div>
 </body>
</html>

如果我使用以下 CSS 代码对其进行样式设置:

img{
   width:100px;
   height:100px;
}
h1{
   font-size:26px;
   color:red;
}

问题是:如何防止和隔离 mydiv div 标签内的标签与公共标签样式的样式?

4

5 回答 5

123

CSS Cascading and Inheritance Level 3引入all速记属性关键字unset它们一起让您可以方便地实现这一点。

例如,如果作者all: initial在一个元素上指定,它将阻止所有继承并重置所有属性,就好像在级联的作者、用户或用户代理级别中没有出现任何规则一样。

这对于包含在页面中的“小部件”的根元素很有用,它不希望继承外部页面的样式。但是请注意,应用于该元素的任何“默认”样式(例如,display: block来自块元素的 UA 样式表,例如<div>)也将被吹走。

您需要申请all: initial您的 divall: unset及其后代:

#mydiv {
  all: initial; /* blocking inheritance for all properties */
}
#mydiv * {
  all: unset; /* allowing inheritance within #mydiv */
}

您可能希望在您的 div 上使用一个类而不是一个 id,这样您编写的任何为其后代设置样式的规则都不必匹配或超过此规则中使用的高特异性。

为了真正安全,您可能还希望阻止潜在伪元素后代的样式:

#mydiv::before,
#mydiv::after,
#mydiv *::before,
#mydiv *::after {
  all: unset;
}

或者,对于更广泛的浏览器支持,您可以手动尝试all通过设置所有已知的 CSS 属性来执行此操作(不要忘记前缀版本):

#mydiv {
  /*
   * using initial for all properties
   * to totally block inheritance
   */
  align-content: initial;
  align-items: initial;
  align-self: initial;
  alignment-baseline: initial;
  animation: initial;
  backface-visibility: initial;
  background: initial;
  ...
}

#mydiv::before,
#mydiv::after,
#mydiv *,
#mydiv *::before,
#mydiv *::after {
  /*
   * using inherit for normally heritable properties,
   * and initial for the others, as unset does
   */
  align-content: initial;
  align-items: initial;
  align-self: initial;
  ...
  color: inherit;
  ...
}

您可以通过以下问题链接鼓励浏览器支持all速记属性并跟踪其采用情况:

all速记属性的最新浏览器支持信息可在此处获得。

于 2013-05-29T16:08:54.153 回答
13

老问题,但自从接受答案以来,情况发生了一些变化。现在有一个名为 CSSWG 推荐的关键字revert,它更适合initialunset解决这个问题,因为它将属性重置为它们在用户代理样式表中定义的内容,而不是它们的初始值(不考虑它们用于哪个元素)。因此,例如,使用revertdiv内部#mydivblock按照我们的预期设置其显示,而不是inline(的初始值display)。

你必须这样做:

#mydiv,
#mydiv::before,
#mydiv::after,
#mydiv *
#mydiv *::before,
#mydiv *::after {
  all: revert;
}

在撰写本文时,revertEdge、Firefox、Chrome 和 Safari 支持,但不支持 IE 或 Opera。

关于接受的答案,还有其他一些事情需要考虑。如果你想在里面设置任何样式#mydiv,你需要使用一个至少与你用来取消设置或恢复所有内容的选择器一样具体的选择器,否则它将被该规则覆盖,即使它在它之后CSS。

所以你需要做这样的事情(注意#mydiv提高规则的特异性):

#mydiv p {
  margin-top: 20px;
}

#mydiv .bg-black {
  background-color: black;
}

// etc.
于 2018-03-15T23:16:21.200 回答
10

从技术上讲,你不能,这就是 CSS 的工作方式。如果在样式表中为 div 标签定义了任何样式,它将应用于所有 div 元素。

您可以尝试的几件事是不要使用标签名称设置样式, 而是给出类名称并将样式声明给类。这样您就可以确定所有样式的去向。

或者。如果您希望某些特定的 Div 标签没有样式而其他 Div 有。你可以随时重置它,给它一些不同的类名或 id 并重置样式声明

于 2012-04-08T16:07:48.257 回答
3

如果 iframe 不会使其他业务逻辑复杂化,它也是一个不错的样式隔离解决方案。此外,这可以在纯 JavaScript 中完成,也可以在旧版浏览器中使用。

const HTMLToIsolate = `...` // get your div tag as HTML string
const parentContainerRef = document.body; // or something else
const newIframe = document.createElement('iframe');
// set height & width to 100% and remove borders for newIframe

parentContainerRef.appendChild(newIframe)
newIframe.contentWindow.document.open('text/html', 'replace');
newIframe.contentWindow.document.write(HTMLToIsolate);
newIframe.contentWindow.document.close();

// bonus to remove scroll bars by setting proper iframe's height
newIframe.addEventListener('load', function onIFrameLoad(e) {
    const iframeBody = this.contentDocument.querySelector("body");
    this.style.height = `${iframeBody.scrollHeight}px`;
});

当我必须将一个复杂的 HTML 文件嵌入到我的网页中时,这对我来说非常有效,没有MixedContent警告并且没有覆盖嵌入 HTML 的父 HTML 样式。感谢https://benfrain.com/sandbox-local-htmlcss-code-snippets-inside-iframe-style-guidespattern-libraries/这个好主意!

尽管#mydiv * { all: unset }CSS 技巧,正如在此处接受的解决方案中所建议的那样有效,但它最终成为一个复杂的浏览器操作,因为我的页面上有许多 DOM 节点。

于 2019-08-17T22:12:02.033 回答
2

可能有用的一件事是CSS 直接子选择器,它在包括 IE7+ 在内的所有浏览器中都可用。这使您可以应用不会级联到子级的样式。例如,在您的代码中,您可以使用以下 CSS:

body > img {
  width:100px;
  height:100px;
}
body > h1 {
  font-size:26px;
  color:red;
}

并且该 CSS 仅适用于直接在 BODY 元素上的元素。

于 2012-04-08T17:59:57.157 回答