如何从公共CSS样式中隔离div?

时间:2012-04-08 15:58:37

标签: html css css3

我在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标签内的标签?

5 个答案:

答案 0 :(得分:94)

CSS Cascading and Inheritance Level 3介绍了the all shorthand propertythe unset keyword,它们可以让您方便地实现这一目标。

  

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

     

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

您需要将all: initial应用于您的div并all: 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;
}

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

#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速记属性的最新浏览器支持信息可用here

答案 1 :(得分:10)

技术上,你无法理解CSS是如何工作的。如果定义了任何样式 样式表中的div标签将应用于所有div元素。

您可以尝试的几件事情不要使用标记名称 ,而是提供类名并向类提供样式声明。这样你就可以确定所有款式的去向。

OR。如果你想要一些特定的Div标签没有其他Div有的风格。你可以随时重置它给出一些不同的类名或id并重置样式声明

答案 2 :(得分:1)

可能有用的一点是 CSS直接子选择器,它适用于所有浏览器,包括IE7 +。这使您可以应用不会级联到儿童中的样式。例如,在您的代码中,您可以使用此CSS:

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

CSS只会直接应用于BODY元素上的元素。

答案 3 :(得分:1)

老问题,但自从接受的答案以来,情况发生了一些变化。现在有一个名为revert的CSSWG推荐关键字,它比initialunset更适合解决此问题,因为它将元素的属性重置为定义的值在user agent stylesheet而不是属性的初始值,无论它在哪个元素上使用。例如,div内的#mydiv将其显示设置为我们预期的block,而不是inline

你必须这样做:

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

不幸的是,在撰写本文时,除了Safari(适用于Mac和iOS)之外,还有revert is not supported by any browser

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

所以你需要做这样的事情(注意#mydiv提升规则的specificity

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

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

// etc.

答案 4 :(得分:0)

如果不将其他业务逻辑复杂化,

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技巧(如已接受的解决方案here中所建议的那样有效,但由于我的页面上有许多DOM节点,最终它还是一个复杂的浏览器操作。