CSS3 combining selectors with OR instead of AND

2019-01-08 01:57发布

问题:

Given this selector:

body[class*="page-node-add-"][class~="page-node-edit"] {background:red;}

It will match a body which has a class that contains a substring of page-node-add- AND a class which is exactly page-node-edit

I would like to say match the first OR the second (but not both). Is it possible?

The problem with using a comma:

If I have a long selector like:

body[class*="page-node-add-"] form.node-form > .field-type-field-collection > table > thead tr th,
body[class~="page-node-edit"] form.node-form > .field-type-field-collection > table > thead tr th
{...}

That is a pain I would have thought CSS3 would remedy that, I was imagining something like:

body([class*="page-node-add-"]):or([class~="page-node-edit"]) {background:red;}

Thanks

回答1:

You'll need to split them up using a comma:

body[class*="page-node-add-"], body[class~="page-node-edit"] {background:red;}

The problem with using a comma:

... is that you can't do it any other way than with a comma. Perhaps it could have been remedied with Selectors 3, but unfortunately the spec says otherwise. That is only going to be remedied by Selectors 4, either because it wasn't proposed until recently, or it was proposed but didn't make the cut for level 3.

In level 4 of Selectors you will be able to do something like this:

body:matches([class*="page-node-add-"], [class~="page-node-edit"]) form.node-form > .field-type-field-collection > table > thead tr th
{...}

Currently, this is being implemented under its originally-proposed name, :any(), with the prefixes :-moz-any() and :-webkit-any(). But using :any() in public-facing CSS is pointless given that

  1. only Gecko and WebKit support it; and

  2. you have to duplicate your rulesets because of the way prefixed selectors are handled, which not only defeats the intended purpose of the :matches() selector, but makes things even worse:

    body:-moz-any([class*="page-node-add-"], [class~="page-node-edit"]) form.node-form > .field-type-field-collection > table > thead tr th
    {...}
    body:-webkit-any([class*="page-node-add-"], [class~="page-node-edit"]) form.node-form > .field-type-field-collection > table > thead tr th
    {...}
    

In other words, until implementations update themselves to the standardized :matches(), there is no other viable solution (save from using a preprocessor to generate the repeated selectors for you).



回答2:

I found the answer here:

CSS Shorthand to identify multiple classes

Mozilla and webkit has a -moz-any or -webkit-any, though in the CSS4 spec there is a :matches. Suprised this wasn't thought of in CSS3 as it would greatly reduce the amount of repetative code without having to use SASS or LESS or whatever.



回答3:

So you really want XOR when I read your question. You can achive this by using the :not selector and say "class one and not the other" and the other way around.

div.one:not(.two), div.two:not(.one) {
    background:red;
}

Here is a fiddle: http://jsfiddle.net/XfgxK/3/