¿Cómo evito la herencia de CSS?

94

Tengo un menú de navegación jerárquico en mi barra lateral que usa listas anidadas (etiquetas <ul> y <li>). Estoy usando un tema prefabricado que ya tiene estilos para los elementos de la lista, pero quiero modificar el estilo de los elementos de nivel superior pero NO aplicarlo a los subelementos. ¿Existe una manera fácil de aplicar estilos a la etiqueta del elemento de la lista de nivel superior SIN tener esos estilos en cascada hacia los elementos de la lista secundaria? Entiendo que puedo agregar explícitamente estilos primordiales a los subelementos, pero realmente me gustaría evitar tener que duplicar todo ese código de estilo si hay una manera fácil de decir "aplicar estos estilos a esta clase y NO en cascada hasta los elementos secundarios ". Aquí está el html que estoy usando:

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

Entonces, el CSS tiene estilos para #sidebar uly #sidebar ul liya, pero me gustaría agregar estilos adicionales a #sidebar .top-level-naveso NO en cascada hacia sus sub-hijos. ¿Hay alguna forma de hacer esto simplemente o necesito reorganizar todos los estilos para que los estilos que estaban #sidebar ulactivados ahora sean específicos para ciertas clases?

Saeed Hassanvand
fuente
2
Busqué en el sitio preguntas similares y no encontré nada (no digo que no haya ninguna, pero busqué). Si sabe lo que es, ¿podría indicarme qué es? ¡Gracias!
1
stackoverflow.com/questions/747308/breaking-css-inheritance | prácticamente dice lo que respondió Matthew.
JasonV
1
Así que supongo que la respuesta es "no, no hay forma de hacerlo simplemente; tienes que anular manualmente cada configuración de estilo en el subelemento", ¿estoy interpretando esto correctamente? Gracias de nuevo.

Respuestas:

38

Hasta el momento, no hay selectores principales (o como los llama Shaun Inman , selectores calificados ), por lo que tendrá que aplicar estilos a los elementos de la lista secundaria para anular los estilos de los elementos de la lista principal.

La cascada es una especie de todo el objetivo de las hojas de estilo en cascada, de ahí el nombre.

Scott
fuente
13
Esta información está desactualizada desde IE8. Vea la respuesta de Silviu Postavaru. Considere cambiar la marca de verificación por una respuesta más apropiada.
tmuecksch
lol, estoy de acuerdo en que la cascada es un poco la esencia. Pero debería haber una forma de detener la propagación de un padre específico que está destinado a ser diferente.
Obay Abd-Algader
72

O usa el selector de niños

Entonces usando

#parent > child

Hará que solo se apliquen los estilos a los niños de primer nivel. Desafortunadamente, IE6 no es compatible con el selector de niños.

De lo contrario, puede usar

#parent child child

Para establecer otros estilos específicos para los niños que están más de un nivel por debajo.

Silviu Postavaru
fuente
1
¿Podrías mostrarme esto en acción en JSFiddle? Intenté centrar un div mostrado en bloque en línea, pero aún centra el texto dentro del div.
Calmarius
41

Hay una propiedad llamada allen el módulo de herencia CSS3 . Funciona así:

#sidebar ul li {
  all: initial;
}

A partir de 2016-12, todos los navegadores excepto IE / Edge y Opera Mini admiten esta propiedad.

Boldewyn
fuente
4
¿@AndriusDobrotinas será apoyado eventualmente? Parece que no entiendo completamente tu comentario. Hay un complemento PostCSS que proporciona esta función, si usa PostCSS: github.com/maximkoretskiy/postcss-initial
Boldewyn
1
@AndriusDobrotinas, Tu comentario es muy poco constructivo. La respuesta fue publicada por el bien de la comunidad; haga todo lo posible para ver sus beneficios.
Cody
2
A partir de ahora, solo IE y Opera Mini no lo admiten, todos los demás navegadores principales lo hacen
Legends
@Boldewyn no hay un valor 'predeterminado', por lo que se puede ver en el documento w3 vinculado ...
benomatis
@webeno había, cuando escribí la respuesta: w3.org/TR/2013/WD-css3-cascade-20130103/#all-shorthand Parece que hay algunas diferencias sutiles entre lo antiguo defaulty lo nuevo unset, pero ahora mismo ' No tengo tiempo para investigar más. Siéntase libre de editar la respuesta para actualizarla.
Boldewyn
26

Puede usar el selector * para cambiar los estilos secundarios a los predeterminados

ejemplo

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

#parent * {
    white-space: initial;
}
gracias: D
fuente
1
Esa es una solución muy atractiva, especialmente si no conoce la clase de los padres.
BurninLeo
Creo que conozco la respuesta a esto, pero ¿hay alguna forma de configurar esto en línea? <div id="parent" style="white-space:pre-wrap;*white-space:initial;"/>
1,21 gigavatios
11

Envolver con iframe hace que el CSS padre sea obsoleto.

Tuğrul
fuente
2
Es curioso que esta sea la peor respuesta porque técnicamente es la única forma física de detener la herencia de CSS. No es que esté argumentando que debas usarlo de esta manera.
davidelrizzo
2
Sugeriría no ser físico con CSS, ¡déjelo en el mundo virtual donde pertenece!
michaelward82
En realidad, agregar iframehizo que mi componente secundario fuera invisible. Pensamientos
Kevin Ghaboosi
5

La respuesta corta es: No, no es posible evitar la herencia de CSS. Solo puede anular los estilos establecidos en los padres. Ver la especificación:

Cada elemento de un documento HTML heredará todas las propiedades heredables de su padre excepto el elemento raíz ( html), que no tiene padre. - W3C

Además de anular todas las propiedades heredadas. También puede utilizar initialpalabras clave, por ejemplo color: initial;. También se puede utilizar junto con all, por ejemplo all: initial;, que restablecerá todas las propiedades a la vez. Ejemplo:

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

Tablas de soporte del navegador según ¿Puedo usar ...

  • all (Actualmente no hay soporte en IE y Edge, otros son buenos)
  • initial (Actualmente no hay soporte en IE, otros son buenos)

Puede resultarle útil si utiliza el selector de hijos directos> en algunos casos. Ejemplo:

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

El estilo de borde se ha aplicado solo a los hijos directos <li>, ya que borderes una propiedad no heredada. Pero el color del texto se ha aplicado a todos los elementos secundarios, ya que colores una propiedad heredada.

Por lo tanto, el >selector solo sería útil con propiedades no heredadas, cuando se trata de prevenir la herencia.

Pegatinas
fuente
2

Puede usar algo como jQuery para "deshabilitar" este comportamiento, aunque no creo que sea una buena solución ya que obtiene la lógica de visualización en css y javascript. Aún así, dependiendo de sus requisitos, es posible que las utilidades css de jQuery le hagan la vida más fácil que probar hacky css, especialmente si está tratando de que funcione para IE6.

Neil Richards
fuente
2

Por ejemplo, si tiene dos div en un documento XHTML.

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

Entonces intente esto en CSS.

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

afecta solo el párrafo 'div2'.

#div1 > p {
    color: red;
} 

afecta solo al párrafo 'div1'.

usuario2848911
fuente
2

No necesita la referencia de clase para el lis. En lugar de tener CSS como

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

puedes escribir

ul#sidebar > li { color:black; }

Esto aplicará el estilo solo a los limensajes que descienden inmediatamente de la barra lateral ul.

stevenvh
fuente
0

simplemente configúrelos de nuevo a sus valores predeterminados en el selector "#sidebar ul li"

Matthew Vines
fuente
Gracias por la respuesta. Sí, entiendo que puedo volver a colocarlos en el estilo del subelemento, pero estoy tratando de evitarlo porque estoy usando un tema que no creé y me pregunto si puedo ahorrar un montón de tiempo. simplemente usando alguna regla de "no cascada: verdadero" o algo así, en lugar de ubicar todos los estilos diferentes para los ul y li que están dispersos por todo el lugar y luego preocuparse por las consecuencias no deseadas en otras áreas del sitio .