【问题标题】:How do I avoid `<style>` tags getting caught in my CSS selectors?如何避免 `<style>` 标签被我的 CSS 选择器卡住?
【发布时间】:2021-07-23 10:41:16
【问题描述】:

我正在使用 CSS 来设置一些现有文档的样式,并使用许多相邻的同级选择器(例如 item1 + item2)在元素之间应用间距等。但是,许多文档还在页面顶部包含&lt;style&gt; 标签,或者分散在应用了自定义样式的地方。自定义样式本身很好,但不幸的是 &lt;style&gt; 标签本身干扰了我的 CSS 选择器。例如,如果我想将margin-top 应用于除第一个元素之外的每个元素,我通常会使用* + *(又名"lobotomized owl" 方法),这很有效,直到有人在顶部放置样式标签。现在 style 标签 被读取为第一个元素,因此页面上的每个元素都被选中。我事先不知道元素类型;它们可以是有效 HTML 代码(div、span、p、table 等)的任意组合,并且还需要考虑嵌套元素 t。我要修复的键选择器是以通配符 (* + item) 开头的相邻兄弟选择器。

我首先想到的是使用:not(style) + item 之类的东西,但是如果页面中间某处有任何&lt;style&gt; 标签,那么其中一个之后的任何元素也会被错误地设置样式。

有没有一种纯粹使用 CSS 的万无一失的方法?我无法自己编辑 HTML 文件,但如果需要,可以在渲染之前使用 Javascript 对其进行预处理。

编辑: 额外的问题,我如何选择页面中的第一个元素 不是 &lt;style&gt; 标记?即,我现在如何在不选择 &lt;style&gt; 标签的情况下执行 body &gt; *:first-child

例如,我的 CSS 文件,然后是目标 HTML:

div {
  background-color: yellow;
}

*+div {
  background-color: lime;
  margin-top: 1em;
}
<style>
  div {
    font-weight: bold;
  }
</style>

<div>Yellow</div>
<div>Green</div>
<div>Green</div>
<div>Green</div>
<div>Green</div>

【问题讨论】:

  • 我刚刚意识到,如果您只需要担心脑叶切除的猫头鹰,那么我的整个答案可能会被替换为:not(body):not(style):nth-child(n+2),这对于任何数量的元素类型都是健壮的。对于更集中的答案,我建议您准确指定要替换的选择器(例如,您只需要担心 body 的孩子吗?嵌套元素呢?)。我的回答目前有点过于努力,无法涵盖各种情况。
  • 我更新了问题以澄清。我需要处理有效 HTML 的任何组合。有些地方我在段落和表格之间添加空格p + table 或者有些地方我在列表和 div 之间添加空格。它来自一组 1,000 多个文档,因此它几乎可以是任何东西。我还希望有一个通用的* + * 作为基本样式,以减少我需要输入的特殊情况排列的数量。
  • 正如我的编辑所说,我还希望替换 body &gt; *:first-child 以某种方式选择正文中的第一个元素,但忽略任何 &lt;style&gt; 标签。
  • 我对我的回答不太满意,所以我将删除它并用新的替换它。
  • 去吧。我很感激帮助。我还重新阅读了您的评论,并为您进一步更新了我的问题。

标签: javascript html css css-selectors


【解决方案1】:

随着文档布局变得越来越复杂,边距可能会变得复杂,但为了简单起见,这个答案将假设您只需要担心叶形切开的猫头鹰,以及具有相对简单的块布局的文档,其中边距在父子节点之间折叠,所以我们可以专注于手头的选择器。

以下选择器对任何数量的元素类型和任何嵌套深度(即不仅仅是body 的子元素)都是健壮的。不幸的是,它确实涉及重复相同的复合选择器:

div, p {
  background-color: yellow;
  margin: 0; /* Remove default p margins for the sake of illustration */
}

:not(style):nth-of-type(n+2),
:not(style):nth-of-type(n+2) ~ * {
  background-color: lime;
  margin-top: 1em;
}

/* Ignore .nest elements for the sake of illustration */
.nest {
  background-color: transparent !important;
}
<style>
  div {
    font-weight: bold;
  }
</style>

<div>Yellow</div>
<div>Green</div>
<p>Green</p>

<style>
  p {
    font-style: italic;
  }
</style>

<div>Green</div>
<p>Green</p>

<section class="nest">
  <div>Yellow</div>
  <div>Green</div>
  <p>Green</p>
</section>

额外问题,我如何选择页面中第一个 不是 &lt;style&gt; 标记的元素?即,我现在如何在不选择&lt;style&gt; 标签的情况下执行body &gt; *:first-child

假设在第一个非style 子元素之前永远不会有多个style 元素:

body > :not(style):first-child, body > style:first-child + *

如果您认为可能有多个连续的style 作为body 的第一个子级的文档,则需要改用this technique

body > :not(style) {
  /* Apply styles to the first non-style child */
}

body > :not(style) ~ :not(style) {
  /* Undo the above styles for following non-style children */
}

在浏览器开始实现第 4 级 :nth-child(An+B of S) 之前,没有基于选择器的替代方案是健壮的:

/* Replaces the main answer's entire selector-list */
:nth-child(n+2 of :not(body, style))

/* Replaces the bonus question's answer */
body > :nth-child(1 of :not(style))

【讨论】:

    猜你喜欢
    • 2015-10-20
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    相关资源
    最近更新 更多