Вложенность CSS селекторов без увеличения специфичности

давайте возьмем эти три селектора, отсортированных от самой высокой специфичности до самой низкой:

.special-section p { }
.weird-font        { }
p                  { }

многие гуру CSS рекомендуют против вложенности, как в первом селекторе .special-section p, потому что его специфичность достаточно высока, что вы не можете переопределить его простым классом, таким как .weird-font. Я хотел бы найти способ по-прежнему достичь вложенности, как в .special-section p, но без увеличения специфичности. Что-то вроде этого:--11-->

 .weird-font { }
 .special-section p /* with hack to decrease specificity */ { }
 p { }

использовать случае:

это довольно безопасно применять значения по умолчанию для типографики и таких документов, используя простые селекторы, такие как p. Однако, я хотел бы изменить эти значения по умолчанию для конкретного участка, как .special-section p, без необходимости использовать хаки для повышения специфичности селекторов, таких как .weird-font. Я бы предпочел использовать hack для уменьшения специфичности .special-section p чем использовать хак для повышения специфичности .weird-font. Есть ли способ сделать это?

4 ответов


в эти дни, в 2018 году, это становится почти возможным.

прежде всего, CSS4 будет иметь способ, который позволяет создавать более конкретные селекторы без увеличения специфичности:

:where(.special-section) p {
    color: red;
}

это установит цвет абзаца внутри .special-section к красному, но со специфичностью 001 (т. е. той же специфичностью, что и простой p селектор бы).

на spec по-прежнему называет этот специальный псевдо-класс :something(), но скорее всего, это будет называться :where(). (Примечание: Я действительно хочу это будет известно как"селектор медового барсука").

но это все еще в будущем.

, на самом деле есть способ достичь этого , если вам больше не нужно поддерживать IE (или довольны менее совершенными резервными вариантами), и это с помощью свойства a.к. a. CSS переменная.

Итак, вы хотите этого:

.special-section p { color: red; }
.weird-font        { color: magenta; }
p                  { color: green; }

но с первой частью, имеющей спецификацию, которая ниже, чем любой селектор с классом в нем. Вы можете сделать это так:

.special-section p { --low-specificity-color: red; }
.weird-font        { color: magenta; }
p                  { color: var(--low-specificity-color, green); }

если вы запустите приведенный ниже фрагмент в современном браузере, вы должны заметить, что второй абзац красный, потому что он находится в специальном разделе, но третий абзац пурпурный, потому что это .weird-font -- хотя .weird-font имеет спецификацию 010 и .special-section p есть 011.

.special-section p { --low-specificity-color: red; }
.weird-font        { color: magenta; }
p                  { color: var(--low-specificity-color, green); }
<p>This is a paragraph.</p>

<section class="special-section">
   <p>This is a paragraph inside a special section.</p>
   <p class="weird-font">This is a paragraph with a weird font inside a special section.</p>
</section>

   <p class="weird-font">This is a paragraph with a weird font.</p>

   <div class="weird-font">This is a div with a weird font.</div>

это работает, потому что в то время как --low-specificity-color изменяется со спецификацией 011, это только применяется С 001 специфику.


вы не можете уменьшить спецификацию, но вы можете добавить еще более конкретный селектор для исключения.

.weird-font, /* Normal weird font */
.special-section p.weird-font /* Override for special section */ 
  { }

но, как вы можете видеть, это скользящая шкала. Так что эти гуру, вероятно, правы. Если убрать .special-section p, а вместо этого дайте этим P их собственный селектор .special-section-para или что-то еще, тогда у вас не будет этой проблемы.

но лично я не против добавить исключение, подобное приведенному выше, время от времени. Я думаю, вся специфика в том, там для этой цели, и если вам нужен более конкретный селектор для стиля чего-то, мне кажется, что это правильно.

широко распространенным решением является использование !important. Проблема с !важно то, что существует только один уровень переопределения. Если вы сделаете более конкретный селектор, вы можете переопределить его еще более конкретным селектором. После использования !важно, что у тебя нет выбора. Что еще более важно, используя !important может мешать специальным таблицам стилей, которые a пользователь может иметь для повышения читаемости. По этой причине я никогда не использую !important в такой ситуации.

но опять же, я не считаю себя гуру CSS. ;)


как гуру CSS, я оплакиваю идею выбрасывания всех селекторов, чтобы избежать проблем со спецификой. Это не значит, что я не верю, что механик специфики несовершенен, но, конечно, для этого есть менее драматические обходные пути.

во-первых: нет, вы не можете уменьшить специфичность селектора. Селекторы не обеспечивают каких-либо особенностей с отрицательными уровнями специфичности, которые уменьшили бы специфичность таким образом. Самое низкое, что вы можете пойти это *, которым имеет ноль специфичность (т. е. она не делает сложный селектор более или менее специфичным).

таким образом, ваш единственный выход на уровне селектора -увеличить его. Можете ли вы сделать это без использования хаков, зависит от вашего определения "hack".

следующее-Это то, что я бы назвал Хак, потому что он использует синтаксически законный, но семантически бессмысленный селектор, такой как :not(_), что не имеет очевидной цели но чтобы добавить специфичность селектора типов к сложному селектору (что далеко не очевидно, особенно для непосвященных):

.special-section p { }
.weird-font, :not(_).weird-font { }

ниже не то, что я бы счел взломом, потому что это то, что вы бы сделали обычно в любом случае. В значительной степени единственная "проблема" заключается в том, что это явное повторение селектора одиночного класса:

.special-section p { }
.weird-font, .special-section p.weird-font { }

если вы рассматриваете какой-либо посторонний селектор для повышения специфичности a hack-который является вполне разумным POV, не ошибитесь - тогда следующая лучшая вещь, что не поделка !important.

лично я бы выбрал спецификацию hack. !important есть, кхм, важно последствия, которые не приходят со спецификой Хак-помните, что !important и специфичность имеют разную семантику. Например, нельзя переопределить !important объявление со встроенным стилем или JavaScript, если они не являются также отмечена важность.1


1на самом деле, это был мой ответ Леа веру, когда у нее был обсуждение в Twitter некоторое время назад относительно специфичности хаков против !important.


мне нравится как это на данный момент. Мне нравится оставлять место для будущих изменений CSS, поэтому не идите как можно конкретнее ради него, например:

.great-grandfather .grandfather .father .child { }

Я буду, если придется конечно. Но, взяв пример выше, если бы я хотел переопределить .child для конкретного элемента, который использует этот класс, который имеет стиль, который может быть такой:

.child {
   color: black;
}

Я бы пошел один родитель выше, чтобы переопределить его, если возможно:

.father .child {
   color: white;
}

далее по строке, если элемент на определенной странице использует .child class и в этом случае мне нужно переопределить оба .father .child, перейду еще на один уровень конкретности:

.grandfather .father .child {
   color: red;
}

это гарантирует, что вам не нужно использовать !important... Которого я избегаю, как чумы, насколько это возможно!