Comment empêcher l'héritage CSS?

94

J'ai un menu de navigation hiérarchique dans ma barre latérale qui utilise des listes imbriquées (balises <ul> et <li>). J'utilise un thème prédéfini qui a déjà des styles pour les éléments de liste, mais je souhaite modifier le style des éléments de niveau supérieur mais PAS l'appliquer aux sous-éléments. Existe-t-il un moyen simple d'appliquer des styles à la balise d'élément de liste de niveau supérieur SANS avoir ces styles en cascade jusqu'à ses éléments de liste enfants? Je comprends que je peux explicitement ajouter des styles de remplacement aux sous-éléments, mais j'aimerais vraiment éviter d'avoir à dupliquer tout ce code de style s'il existe un moyen simple de dire simplement "appliquer ces styles à cette classe et NE PAS cascade les jusqu'à tous les éléments enfants ". Voici le html que j'utilise:

<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>

Donc, le CSS a des styles pour #sidebar ulet #sidebar ul lidéjà, mais j'aimerais ajouter des styles supplémentaires #sidebar .top-level-navqui ne se répercutent PAS sur ses sous-enfants. Existe-t-il un moyen de le faire simplement ou dois-je réorganiser tous les styles pour que les styles qui étaient activés #sidebar ulsoient désormais spécifiques à certaines classes?

Saeed Hassanvand
la source
2
J'ai cherché sur le site des questions similaires et je n'ai rien trouvé (sans dire qu'il n'y en avait pas, mais j'ai cherché). Si vous savez ce que c'est, pourriez-vous s'il vous plaît me diriger vers lui? Merci!
1
stackoverflow.com/questions/747308/breaking-css-inheritance | cela dit à peu près ce que Matthew a répondu.
JasonV
1
Je suppose donc que la réponse est "non, il n'y a aucun moyen de le faire simplement - vous devez remplacer manuellement chaque paramètre de style sur le sous-élément" - est-ce que j'interprète cela correctement? Merci encore.

Réponses:

38

Pour le moment, il n'y a pas de sélecteurs parents (ou comme Shaun Inman les appelle, des sélecteurs qualifiés ), vous devrez donc appliquer des styles aux éléments de la liste enfant pour remplacer les styles sur les éléments de la liste parent.

La cascade est en quelque sorte le but des feuilles de style en cascade, d'où le nom.

Scott
la source
13
Ces informations sont obsolètes depuis IE8. Voir la réponse de Silviu Postavaru. Veuillez envisager de changer le chèque en la réponse la plus appropriée.
tmuecksch
lol, je suis d'accord que la cascade est un peu l'essence. Mais il devrait y avoir un moyen d'arrêter la propagation d'un parent spécifique qui est censé être différent.
Obay Abd-Algader le
72

Soit vous utilisez le sélecteur d'enfant

Donc en utilisant

#parent > child

Ne fera appliquer que les enfants de premier niveau aux styles. Malheureusement, IE6 ne prend pas en charge le sélecteur d'enfant.

Sinon, vous pouvez utiliser

#parent child child

Pour définir un autre style spécifique pour les enfants qui sont plus d'un niveau en dessous.

Silviu Postavaru
la source
1
Pourriez-vous me montrer cela en action dans JSFiddle? J'ai essayé de centrer un div affiché en bloc en ligne, mais il centre toujours le texte à l'intérieur du div.
Calmarius
41

Il existe une propriété appelée alldans le module d'héritage CSS3 . Cela fonctionne comme ceci:

#sidebar ul li {
  all: initial;
}

Depuis 2016-12, tous les navigateurs sauf IE / Edge et Opera Mini prennent en charge cette propriété.

Boldewyn
la source
4
@AndriusDobrotinas sera éventuellement soutenu? Il me semble que je ne comprends pas complètement votre commentaire. Il existe un plugin PostCSS qui fournit cette fonctionnalité, si vous utilisez PostCSS: github.com/maximkoretskiy/postcss-initial
Boldewyn
1
@AndriusDobrotinas, Votre commentaire est très peu constructif. La réponse a été publiée pour le bien de la communauté; essayez de votre mieux pour voir ses avantages.
Cody du
2
Pour le moment, seuls IE et Opera Mini ne le prennent pas en charge, tous les autres principaux navigateurs le font
Legends
@Boldewyn il n'y a pas de valeur `` par défaut '', pour autant que l'on puisse dire d'après le document w3 lié ...
benomatis
@webeno il y avait, quand j'ai écrit la réponse: w3.org/TR/2013/WD-css3-cascade-20130103/#all-shorthand Il semble qu'il y ait des différences subtiles entre l'ancien defaultet le nouveau unset, mais en ce moment je ' Je n'ai pas le temps d'enquêter davantage. N'hésitez pas à modifier la réponse pour la mettre à jour.
Boldewyn
26

Vous pouvez utiliser le sélecteur * pour rétablir les styles enfants par défaut

exemple

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

#parent * {
    white-space: initial;
}
merci: D
la source
1
C'est une très belle solution - surtout si vous ne connaissez pas la classe des parents.
BurninLeo
Je pense que je connais la réponse à cela, mais y a-t-il de toute façon pour définir cela en ligne? <div id="parent" style="white-space:pre-wrap;*white-space:initial;"/>
1,21 gigawatts
11

L'emballage avec iframe rend le css parent obsolète.

Tuğrul
la source
2
C'est drôle que ce soit la pire réponse car techniquement, c'est le seul moyen physique d'arrêter l'héritage CSS. Non pas que je dise que vous devriez l'utiliser de cette façon.
davidelrizzo
2
Je suggérerais de ne pas devenir physique avec CSS, laissez-le dans le monde virtuel auquel il appartient!
michaelward82
En fait, l'ajout a iframerendu mon composant enfant invisible. Pensées?
Kevin Ghaboosi
5

La réponse courte est: Non, il n'est pas possible d'empêcher l'héritage CSS. Vous ne pouvez remplacer que les styles définis sur les parents. Voir les spécifications:

Chaque élément d'un document HTML héritera de toutes les propriétés héritables de son parent à l'exception de l'élément racine ( html), qui n'a pas de parent. - W3C

En plus de remplacer chaque propriété héritée. Vous pouvez également utiliser des initialmots clés, par exemple color: initial;. Il peut également être utilisé avec all, par exemple all: initial;, qui réinitialisera toutes les propriétés à la fois. Exemple:

.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>

Tableaux de support du navigateur selon Puis-je utiliser ...

  • all (Actuellement pas de support à la fois dans IE et Edge, les autres sont bons)
  • initial (Actuellement aucun support dans IE, d'autres sont bons)

Vous pouvez le trouver utile en utilisant le sélecteur d'enfants direct> dans certains cas. Exemple:

.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>

Le style de bordure a été appliqué uniquement aux enfants directs <li>, tout comme borderune propriété non héritée. Mais la couleur du texte a été appliquée à tous les enfants, tout comme colorune propriété héritée.

Par conséquent, le >sélecteur ne serait utile qu'avec les propriétés non héritées, lorsqu'il s'agit d'empêcher l'héritage.

Autocollants
la source
2

Vous pouvez utiliser quelque chose comme jQuery pour "désactiver" ce comportement, bien que je ne pense pas que ce soit une bonne solution car vous obtenez une logique d'affichage en css et javascript. Néanmoins, en fonction de vos besoins, vous constaterez peut-être que les utilitaires css de jQuery vous facilitent la vie que d'essayer de pirater css, surtout si vous essayez de le faire fonctionner pour IE6

Neil Richards
la source
2

Par exemple, si vous avez deux div dans un document XHTML.

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

Ensuite, essayez ceci en CSS.

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

n'affecte que le paragraphe «div2».

#div1 > p {
    color: red;
} 

n'affecte que le paragraphe «div1».

user2848911
la source
2

Vous n'avez pas besoin de la référence de classe pour le lis. Au lieu d'avoir CSS comme

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

tu peux écrire

ul#sidebar > li { color:black; }

Cela appliquera le style uniquement aux lis qui descendent immédiatement de la barre latérale ul.

Stevenvh
la source
0

il suffit de les remettre à leurs valeurs par défaut dans le sélecteur "#sidebar ul li"

Matthieu Vines
la source
Merci d'avoir répondu. Oui, je comprends que je peux les remettre dans le style du sous-élément, mais j'essaie d'éviter cela parce que j'utilise un thème que je n'ai pas créé et je me demande si je peux gagner beaucoup de temps en utilisant simplement une règle "do-not-cascade: true" ou quelque chose comme ça, au lieu de localiser tous les styles différents pour les ul's et li's qui sont dispersés un peu partout, puis de s'inquiéter des conséquences involontaires dans d'autres zones du site .