Как предотвратить наследование CSS?

94

У меня на боковой панели есть иерархическое меню навигации, в котором используются вложенные списки (теги <ul> и <li>). Я использую готовую тему, в которой уже есть стили для элементов списка, но я хочу изменить стиль для элементов верхнего уровня, но НЕ применять его к вложенным элементам. Есть ли простой способ применить стили к тегу элемента списка верхнего уровня БЕЗ каскадного распространения этих стилей на его дочерние элементы списка? Я понимаю, что могу явно добавить переопределяющие стили к подпунктам, но мне бы очень хотелось избежать дублирования всего этого кода стиля, если есть простой способ просто сказать «применить эти стили к этому классу и НЕ каскадировать» их вплоть до любых дочерних элементов ". Вот HTML, который я использую:

<ul id="sidebar">
  <li class="top-level-nav">
    <span>HEADING 1</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
  <li class="top-level-nav">
    <span>HEADING 2</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
</ul>

Итак, в CSS есть стили для #sidebar ulи #sidebar ul liуже, но я хотел бы добавить к ним дополнительные стили, #sidebar .top-level-navкоторые НЕ переходят в его дочерние элементы. Есть ли способ сделать это просто или мне нужно переставить все стили, чтобы стили, которые были #sidebar ulвключены, теперь были специфичными для определенных классов?

Саид Хассанванд
источник
2
Я искал на сайте похожие вопросы и ничего не нашел (не говорю, что их нет, но я смотрел). Если вы знаете, что это, не могли бы вы направить меня к нему? Благодарность!
1
stackoverflow.com/questions/747308/breaking-css-inheritance | это в значительной степени говорит о том, что ответил Мэтью.
JasonV 05
1
Итак, я полагаю, что ответ - «нет, нет способа сделать это просто - вам нужно вручную переопределить каждый параметр стиля в подпункте» - правильно ли я это интерпретирую? Еще раз спасибо.

Ответы:

38

Пока что нет родительских селекторов (или, как их называет Шон Инман , квалифицированных селекторов ), поэтому вам придется применить стили к элементам дочернего списка, чтобы переопределить стили для элементов родительского списка.

Каскадирование - это своего рода суть каскадных таблиц стилей, отсюда и название.

Скотт
источник
13
Эта информация устарела с IE8. См. Ответ Сильвиу Поставару. Пожалуйста, подумайте о том, чтобы поменять отметку на более подходящий ответ.
tmuecksch
lol, я согласен, что каскадирование - это своего рода суть. Но должен быть способ остановить распространение от определенного родителя, который должен отличаться.
Обай Абд-Альгадер,
72

Вы либо используете дочерний селектор

Итак, используя

#parent > child

Сделает только дочерние элементы первого уровня, к которым будут применены стили. К сожалению, IE6 не поддерживает дочерний селектор.

В противном случае вы можете использовать

#parent child child

Чтобы установить другие конкретные стили для детей, которые находятся более чем на один уровень ниже.

Сильвиу Поставару
источник
1
Не могли бы вы показать мне это в действии в JSFiddle? Я попытался центрировать отображаемый блок inline-block, но он все еще центрирует текст внутри div.
Calmarius
41

Существует свойство называется allв модуле CSS3 наследования . Это работает так:

#sidebar ul li {
  all: initial;
}

По состоянию на 2016–2012 гг. Это свойство поддерживают все браузеры, кроме IE / Edge и Opera Mini .

Болдевин
источник
4
@AndriusDobrotinas в конечном итоге получит поддержку? Кажется, я не совсем понимаю ваш комментарий. Есть плагин PostCSS, который предоставляет эту функцию, если вы используете PostCSS: github.com/maximkoretskiy/postcss-initial
Boldewyn
1
@AndriusDobrotinas, Ваш комментарий очень неконструктивный. Ответ был опубликован ради сообщества; изо всех сил старайтесь увидеть его преимущества.
Cody
2
На данный момент только IE и Opera Mini не поддерживают его, все другие основные браузеры поддерживают
Legends
@Boldewyn нет значения по умолчанию, насколько можно судить по связанному документу w3 ...
benomatis
@webeno было, когда я писал ответ: w3.org/TR/2013/WD-css3-cascade-20130103/#all-shorthand Кажется, есть некоторые тонкие различия между старым defaultи новым unset, но сейчас я У меня нет времени на дальнейшее расследование. Не стесняйтесь редактировать ответ, чтобы обновить его.
Boldewyn
26

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

пример

#parent {
    white-space: pre-wrap;
}

#parent * {
    white-space: initial;
}
Спасибо д
источник
1
Это очень красивое решение, особенно если вы не знаете родительский класс.
BurninLeo
Я думаю, что знаю ответ на этот вопрос, но есть ли способ установить это встроенным? <div id="parent" style="white-space:pre-wrap;*white-space:initial;"/>
1,21 гигаватт
11

Обертка с помощью iframe делает родительский css устаревшим.

Tuğrul
источник
2
Забавно, что это худший ответ, потому что технически это единственный физический способ остановить наследование CSS. Не то чтобы я утверждаю, что вы должны использовать это таким образом.
davidelrizzo
2
Я бы посоветовал не заниматься физическими упражнениями с помощью CSS, оставить его в виртуальном мире, которому он и принадлежит!
michaelward82
Фактически добавление iframeсделало мой дочерний компонент невидимым. Мысли?
Кевин Габуси
5

Краткий ответ: нет, наследование CSS невозможно предотвратить. Вы можете переопределить только стили, установленные для родителей. См. Спецификацию:

Каждый элемент в документе HTML унаследует все наследуемые свойства от своего родителя, кроме корневого элемента ( html), у которого нет родителя. - W3C

Помимо переопределения каждого унаследованного свойства. Вы также можете использовать initialключевое слово, например color: initial;. Его также можно использовать вместе all, например all: initial;, для сброса всех свойств сразу. Пример:

.container {
  color: blue;
  font-style: italic;
}
.initial {
  all: initial;
}
<div class="container">
  The quick brown <span class="initial">fox</span> jumps over the lazy dog
</div>

Таблицы поддержки браузера в соответствии с Могу ли я использовать ...

  • all (В настоящее время нет поддержки как в IE, так и в Edge, другие хороши)
  • initial (В настоящее время нет поддержки в IE, другие хороши)

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

.list > li {
  border: 1px solid red;
  color: blue;
}
<ul class="list">
  <li>
    <span>HEADING 1</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
  <li>
    <span>HEADING 2</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
</ul>

Стиль границы был применен только к прямым дочерним <li>элементам, так как borderэто ненаследуемое свойство. Но цвет текста был применен ко всем дочерним элементам, как colorэто унаследованное свойство.

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

Наклейки
источник
2

Вы можете использовать что-то вроде jQuery, чтобы «отключить» это поведение, хотя я не думаю, что это хорошее решение, поскольку вы получаете логику отображения в css и javascript. Тем не менее, в зависимости от ваших требований вы можете обнаружить, что утилиты jQuery css облегчают вам жизнь, чем попытки взломать css, особенно если вы пытаетесь заставить его работать для IE6.

Нил Ричардс
источник
2

Например, если у вас есть два div в документе XHTML.

<div id='div1'>
    <p>hello, how are you?</p>
    <div id='div2'>
        <p>I am fine, thank you.</p>
    </div>
</div>

Затем попробуйте это в CSS.

#div1 > #div2 > p{
    color: red;
}

влияет только на абзац 'div2'.

#div1 > p {
    color: red;
} 

влияет только на абзац 'div1'.

user2848911
источник
2

Вам не нужна ссылка на класс для lis. Вместо CSS вроде

li.top-level-nav { color:black; }

ты можешь написать

ul#sidebar > li { color:black; }

Это применит стиль только к тем liэлементам, которые непосредственно спускаются с боковой панели ul.

Стивенвх
источник
0

просто установите для них значения по умолчанию в селекторе "#sidebar ul li"

Мэтью Вайнс
источник
Спасибо за ответ. Да, я понимаю, что могу вернуть их в стиль подпункта, но я стараюсь избегать этого, потому что я использую тему, которую не создавал, и мне интересно, смогу ли я сэкономить кучу времени просто используя какое-то правило "do-not-cascade: true" или что-то в этом роде, вместо того, чтобы находить все разные стили для ul и li, которые разбросаны повсюду, а затем беспокоиться о непредвиденных последствиях в других областях сайта .