什么
我正在尝试创建一个CSS选择器,用于选择给定父级中的所有子级;但只要路径上的任何元素都有某个类,就排除它们。
上下文
我在Javascript中创建了一些物化类,它将一些元素替换为它们的材料版本。这是在顶级应用程序上运行。每个用户都可以创建自己的应用程序,我希望能够说某个元素组不应该经历这个过程。
示例
应该选择:
<div>
<input />
</div>
不应选择此项:
<div class="no-material">
<input />
</div>
主要的挑战是这个标签可以在任何地方。例如:
<main>
<section class="no-material">
<form>
<fieldset>
<input />
</fieldset>
</form>
</section>
</main>
或者可能是:
<main>
<section>
<form class="no-material">
<fieldset>
<input />
</fieldset>
</form>
</section>
</main>
已经过测试
我尝试了几次尝试。最好的情况是:
div:not(.no-material) > input:not(.no-material), div:not(.no-material) *:not(.no-material) input:not(.no-material)
但是,它仍然会产生一些误报。通过添加许多级别,我可以更加准确:
div:not(.no-material) > input:not(.no-material),
div:not(.no-material) > *:not(.no-material) > input:not(.no-material),
div:not(.no-material) > *:not(.no-material) > *:not(.no-material) > input:not(.no-material)
就像20-50级(或更多?)那样,但那不是很聪明。
实时版
您可以通过在Javascript中编辑cssSelector来测试您的选择器。
let cssSelector = [
// Independent selectors
'div:not(.no-material) > input:not(.no-material)',
'div:not(.no-material) *:not(.no-material) input:not(.no-material)'
].join(',');
// This will get elements and run their names. We should get yes1-5, but not no1-5.
let inputs = document.querySelectorAll(cssSelector);
for (let input of inputs) console.log(input.getAttribute('name'));
&#13;
<!-- Do not edit HTML, just the CSS selector -->
<main style="display: none;">
<!-- Not selectable -->
<div class="no-material">
<input name="no-1">
</div>
<div>
<input name="no-2" class="no-material">
</div>
<div>
<label class="no-material">
<input name="no-3">
</label>
</div>
<div>
<label class="no-material">
<span>
<input name="no-4">
</span>
</label>
</div>
<div>
<label>
<span class="no-material">
<input name="no-5">
</span>
</label>
</div>
<!-- Selectable -->
<div>
<input name="yes-1">
</div>
<div>
<input name="yes-2">
</div>
<div>
<label>
<input name="yes-3">
</label>
</div>
<div>
<label>
<span>
<input name="yes-4">
</span>
</label>
</div>
<div>
<label>
<span>
<input name="yes-5">
</span>
</label>
</div>
</main>
<!-- Do not edit HTML, just the CSS selector -->
&#13;
注意:我已经想到了解决这个问题的其他方法,例如迭代一个名为&#39; .no-material&#39;的元素的所有子元素。并添加课程&#39; no-material&#39;对所有人而言,这是消耗资源的,如果可能的话,我想从CSS选择器的角度来解决这个问题。
谢谢
答案 0 :(得分:1)
找到所有元素(all
),然后在元素或其父元素(no-material
)上找到no
的元素,然后将第二个元素从第一个元素中删除找到那些剩下的(yes
)。
const difference = (a, b) => a.filter(elt => b.indexOf(elt) === -1);
const all = document.querySelectorAll("input");
const no = document.querySelectorAll(".no-material input, input.no-material");
const yes = difference([...all], [...no]);
console.log(yes.map(elt => elt.name));
&#13;
<main style="display: none;">
<!-- Not selectable -->
<div class="no-material">
<input name="no-1">
</div>
<div>
<input name="no-2" class="no-material">
</div>
<div>
<label class="no-material">
<input name="no-3">
</label>
</div>
<div>
<label class="no-material">
<span>
<input name="no-4">
</span>
</label>
</div>
<div>
<label>
<span class="no-material">
<input name="no-5">
</span>
</label>
</div>
<!-- Selectable -->
<div>
<input name="yes-1">
</div>
<div>
<input name="yes-2">
</div>
<div>
<label>
<input name="yes-3">
</label>
</div>
<div>
<label>
<span>
<input name="yes-4">
</span>
</label>
</div>
<div>
<label>
<span>
<input name="yes-5">
</span>
</label>
</div>
</main>
&#13;
答案 1 :(得分:0)
在现代浏览器中,您可以使用css变量。
在根级别定义它,在类中重新定义它:
:root {
--mycolor: lightblue;
}
.container {
--mycolor: lightgreen;
}
.test {
background-color: var(--mycolor);
}
<div class="test">BASE</div>
<div class="container">
<div class="test">BASE</div>
</div>