2012-05-23 12 views
53

tengo este diseño:¿Por qué mi selector jQuery: not() no funciona en CSS?

<div id="sectors"> 
    <h1>Sectors</h1> 
    <div id="s7-1103" class="alpha"></div> 
    <div id="s8-1104" class="alpha"></div> 
    <div id="s1-7605" class="beta"></div> 
    <div id="s0-7479"></div> 
    <div id="s2-6528" class="gamma"></div> 
    <div id="s0-4444"></div> 
</div> 

Con estas reglas CSS:

#sectors { 
    width: 584px; 
    background-color: #ffd; 
    margin: 1.5em; 
    border: 4px dashed #000; 
    padding: 16px; 
    overflow: auto; 
} 

#sectors > h1 { 
    font-size: 2em; 
    font-weight: bold; 
    text-align: center; 
} 

#sectors > div { 
    float: left; 
    position: relative; 
    width: 180px; 
    height: 240px; 
    margin: 16px 0 0 16px; 
    border-style: solid; 
    border-width: 2px; 
} 

#sectors > div::after { 
    display: block; 
    position: absolute; 
    width: 100%; 
    bottom: 0; 
    font-weight: bold; 
    text-align: center; 
    text-transform: capitalize; 
    background-color: rgba(255, 255, 255, 0.8); 
    border-top: 2px solid; 
    content: attr(id) ' - ' attr(class); 
} 

#sectors > div:nth-of-type(3n+1) { 
    margin-left: 0; 
} 

#sectors > div.alpha { color: #b00; background-color: #ffe0d9; } 
#sectors > div.beta { color: #05b; background-color: #c0edff; } 
#sectors > div.gamma { color: #362; background-color: #d4f6c3; } 

utilizo jQuery para añadir la clase unassigned a sectores que de otra manera no tienen una de las clases alpha, o betagamma:

$('#sectors > div:not(.alpha, .beta, .gamma)').addClass('unassigned'); 

Entonces se aplican algunas reglas diferentes a esa clase :

#sectors > div.unassigned { 
    color: #808080; 
    background-color: #e9e9e9; 
    opacity: 0.5; 
} 

#sectors > div.unassigned::after { 
    content: attr(id) ' - Unassigned'; 
} 

#sectors > div.unassigned:hover { 
    opacity: 1.0; 
} 

Y todo funciona a la perfección en los navegadores modernos.

Interactive jsFiddle preview

Pero ya que el :not() selector in jQuery se basa en :not() in CSS3, estaba pensando que podía moverlo directamente en mi hoja de estilo, para no tener que depender de la adición de una clase extra usando jQuery. Además, no estoy realmente interesado en dar soporte a versiones anteriores de IE, y otros navegadores tienen soporte excelente para el selector :not().

Así que trate de cambiar la parte .unassigned anterior a este (conociendo sólo tendré sectores Α, beta y gamma en mi diseño):

#sectors > div:not(.alpha, .beta, .gamma) { 
    color: #808080; 
    background-color: #e9e9e9; 
    opacity: 0.5; 
} 

#sectors > div:not(.alpha, .beta, .gamma)::after { 
    content: attr(id) ' - Unassigned'; 
} 

#sectors > div:not(.alpha, .beta, .gamma):hover { 
    opacity: 1.0; 
} 

Pero tan pronto como hago esto deja de funcionar - en todos los navegadores! Mis sectores no asignados no aparecen atenuados, desvanecidos o etiquetados como "Sin asignar".

Updated but not so interactive jsFiddle preview

¿Por qué el trabajo :not() selectora en jQuery, pero fracasan en CSS? ¿No debería funcionar de manera idéntica en ambos lugares ya que jQuery afirma ser "compatible con CSS3", o hay algo que me falta?

¿Existe una solución pura de CSS para esto o tendré que depender de un script?

+1

Relacionado: [Combining: not() selectores en CSS] (http://stackoverflow.com/questions/7403129/combining-not-selectors-in-css) – BoltClock

+0

También relacionado: [Encyclopedia Stack Exchange] (http : //blog.stackoverflow.com/2012/05/encyclopedia-stack-exchange) - este es mi primer experimento con él, y hasta ahora, además de ese rudo voto negativo, debo decir que resultó mejor de lo que esperaba:) – BoltClock

Respuesta

68

¿Por qué el selector :not() funciona en jQuery pero falla en CSS? ¿No debería funcionar de manera idéntica en ambos lugares ya que jQuery afirma ser "compatible con CSS3", o hay algo que me falta?

Tal vez debería , pero resulta que no se : jQuery se extiende el selector de :not() tal que you can pass any selector to it, no importa lo complejo que puede ser, y sospecho que la principal razón para esto es por paridad con .not() method, que también toma los filtros y selectores arbitrariamente complejos en consecuencia. De alguna manera mantiene una sintaxis similar a CSS, pero se extiende desde lo definido en el estándar.

Como otro ejemplo, esto funciona muy bien (ya sé que es un ejemplo increíblemente ridícula en comparación con lo que está dada en la pregunta, pero es sólo para fines ilustrativos):

/* 
* Select any section 
* that's neither a child of body with a class 
* nor a child of body having a descendant with a class. 
*/ 
$('section:not(body > [class], body > :has([class]))') 

jsFiddle preview

Recuerde que pasar una lista de selectores separados por coma a :not() significa que los elementos filtrantes que no coinciden con ninguno de los selectores enumerados.

Ahora, el :not() pseudo-class in Selectors level 3, por otro lado, es muy limitado por sí mismo. Solo puede pasar un único selector simple como argumento al :not(). Esto significa que puede pasar una sola cualquiera de estos a la vez:

  • selector universal (*), opcionalmente con un selector namespace
  • Tipo (a, div, span, ul, li, etc), opcionalmente con un selector de namespace
  • Atributo ([att], [att=val], etc), opcionalmente con un selector de clase namespace
  • (.class)
  • selector de ID (#id)
  • Pseudo-clase (:pseudo-class)

lo tanto, aquí son las diferencias entre jQuery's :not() selector y the current standard's :not() selector:

  1. En primer lugar, a responda la pregunta directamente: no puede pasar una lista de selectores separados por comas. Por ejemplo, mientras el selector dado trabaja en jQuery como se demostró en el violín, no es válido CSS:

    /* If it's not in the Α, Β or Γ sectors, it's unassigned */ 
    #sectors > div:not(.alpha, .beta, .gamma) 
    

    ¿Existe una solución CSS puro para esto o voy a tener que depender en un guion?

    Afortunadamente, en este caso, hay. Usted simplemente tiene que múltiples cadena de :not() selectores, uno tras otro, con el fin de que sea válido CSS:

    #sectors > div:not(.alpha):not(.beta):not(.gamma) 
    

    no tiene el selector que mucho más tiempo, pero la inconsistencia y la incomodidad permanece evidente.

    Updated interactive jsFiddle preview

  2. No se pueden combinar selectores simples en los selectores de compuestos para su uso con :not(). Esto funciona de jQuery, pero usa CSS válido:

    /* Do not find divs that have all three classes together */ 
    #foo > div:not(.foo.bar.baz) 
    

    Tendrá que dividirlo en múltiples negaciones (no sólo les cadena!) Para que sea válido CSS:

    #foo > div:not(.foo), #foo > div:not(.bar), #foo > div:not(.baz) 
    

    Como se puede ver, esto es incluso más inconveniente que el punto 1.

  3. No se pueden usar combinadores. Esto funciona de jQuery, pero no CSS:

    /* 
    * Grab everything that is neither #foo itself nor within #foo. 
    * Notice the descendant combinator (the space) between #foo and *. 
    */ 
    :not(#foo, #foo *) 
    

    Este es un caso particularmente desagradable, sobre todo porque no tiene ninguna solución adecuada. Hay algunas soluciones flojas (1 y 2), pero casi siempre dependen de la estructura HTML y, por lo tanto, su utilidad es muy limitada.

  4. En un navegador que implementa querySelectorAll() y el selector de :not(), utilizando :not() en una cadena de selección de una manera que hace que sea un selector CSS válido hará que el método para devolver resultados directamente, en lugar de caer a chisporrotear (selector de jQuery motor que implementa la extensión :not()). Si eres un riguroso para el rendimiento, este es un bono positivamente minúsculo que definitivamente salivarás.

Lo bueno es que Selectors 4 enhances the :not() selector para permitir una lista separada por comas de selectores complejos. Un selector complejo es simplemente un selector simple, compuesto o simple, o una cadena completa de selectores compuestos separados por combinadores. En resumen, todo lo que ves arriba.

Esto significa que los ejemplos de jQuery anteriores se convertirán en selectores de nivel 4 válidos, lo que hará que la pseudoclase sea mucho, mucho más útil cuando las implementaciones de CSS comiencen a admitirla en los próximos años.


Aunque this article dice que puede pasar una lista separada por comas de los selectores de :not() en Firefox 3, que no se supone que ser capaz de hacerlo. Si funciona en Firefox 3 como dice el artículo, se debe a un error en Firefox 3 para el cual ya no puedo encontrar el ticket, pero no debería funcionar hasta que los navegadores futuros implementen estándares futuros. Al ver con qué frecuencia se cita ese artículo hasta la fecha, he dejado un comment en este sentido, pero viendo también la antigüedad del artículo y la poca frecuencia con la que se está actualizando el sitio, no cuento con que el autor vuelva a corregirlo. eso.

+3

Ese artículo es realmente molesto. Parece ser el único responsable de las personas que piensan ': not (#foo, #foo *)' funciona en CSS. Bueno, quizás jQuery lo apoye también tiene algo que ver con eso. – thirtydot

+0

Los selectores de nivel 4 solo son compatibles con Safari hasta el momento, http://caniuse.com/#search=%3Anot – Carlos

Cuestiones relacionadas