Селектор CSS для чего-то не внутри чего-то другого

У меня есть некоторые вложенные элементы вроде этого:

<div class="foo">
    <div class="select-inside-this">
        <div class="not-inside-this">
            <div class="one select-this"></div>
        </div>
    </div>
</div>
<div class="select-inside-this">
    <div class="two select-this"></div>
</div>
<div class="three select-this"></div>

Я хочу выбрать все .select-this внутри .select-inside-this но не те, которые завернуты в .not-inside-this. Поэтому, в конце концов, я должен иметь возможность выбирать только two.select-this из приведенного выше кода. CSS, который я пробовал, но не работал:

.select-inside-this :not(.not-inside-this) .select-this {
    /* style here /*
}

или:

.select-inside-this *:not(.not-inside-this) .select-this {
    /* style here /*
}

Любой обходной путь здесь?

Здесь я не хочу использовать JavaScript. Мне нужно чистое решение CSS3.

EDIT: я не хочу использовать прямой дочерний (>) селектор. Как я уже сказал, я хочу выделить все эти элементы с любого уровня без оболочки исключения.

Ответы

Ответ 1

:not(.not-inside-this) и *:not(.not-inside-this) с * эквивалентны; в случае первого подразумевается универсальный селектор. См. Спецификацию.

В настоящее время невозможно создать селектор CSS, который соответствует элементам, которые не являются потомками определенных элементов по причинам, указанным в следующих вопросах:

Селектор

.select-inside-this :not(.not-inside-this) .select-this

.select-this элементы, которые являются потомками какого-либо элемента, который не является .not-inside-this, который, в свою очередь, является потомком .select-inside-this. Он не соответствует .select-this элементы, которые не являются потомками .not-inside-this внутри .select-inside-this.

Это означает, что во-первых, ваш селектор будет неправильно соответствовать следующему:

<div class="select-inside-this">
    <div class="bar">
        <div class="not-inside-this">
            <div class="select-this"></div>
        </div>
    </div>
</div>

... потому что один из предков .select-this, .bar, is :not(.not-inside-this).

Кроме того, это подразумевает как минимум три уровня гнездования (хотя это может быть больше). В вашем примере нет других элементов между .two.select-this и его .two.select-this .select-inside-this, поэтому он никогда не будет соответствовать этому элементу. Вот почему Джеймс Доннелли предлагает добавить .select-inside-this >.select-this для учета этого конкретного случая.

Однако по-прежнему невозможно написать один сложный селектор с использованием компиляторов-потомков для соответствия элементам без определенного предка. Единственный способ - повторить метод детского комбинатора с таким количеством :not(.not-inside-this) по необходимости, но это требует, чтобы вы учитывали все возможные случаи. Если вы не можете этого сделать, вам не повезло с CSS-селекторами.

Ответ 2

Вы можете использовать " Выбор детского комбинатора" > для указания прямых детей:

.select-inside-this :not(.not-inside-this) .select-this,
.select-inside-this > .select-this {
    /* style here /*
}

Это выбирает любой .select-this элемент, который не является потомком какого-либо .not-inside-this а также выбирает .select-this элементы, которые являются прямыми .not-inside-this элементами .select-inside-this.

body > .select-inside-this :not(.not-inside-this) .select-this,
body > .select-inside-this > .select-this {
  color: red;
}
<div class="foo">
    <div class="select-inside-this">
        <div class="not-inside-this">
            <div class="one select-this">
                This should not be selected
            </div>
        </div>
    </div>
</div>
<div class="select-inside-this">
    <div class="two select-this">
        This should be selected
    </div>
</div>
<div class="three select-this">
    This should not be selected
</div>

Ответ 3

Немного опоздал на вечеринку, и это может не совпадать с вашим вариантом использования, но это то, что я в итоге сделал:

HTML:

<div class="foo">
    <div class="select-inside-this">
        <div class="not-inside-this">
            <div class="one select-this"></div>
        </div>
    </div>
</div>
<div class="select-inside-this">
    <div class="two select-this"></div>
</div>
<div class="three select-this"></div>

CSS:

.select-inside-this .select-this {
    background: blue;
}
.select-inside-this .not-inside-this .select-this {
    background: none;
}

Хитрость заключается в том, чтобы положительно выбрать отрицательный элемент и просто отменить стиль.

Это будет работать для простых случаев использования, по крайней мере.