I should probably preface this answer with a note that it's usually not necessary — and not a good idea — to apply a font-family
style to every descendant of body
, because font properties are inherited by default by most elements anyway (except form elements and tables if I'm not wrong).
By forcibly applying font-family
to every descendant of body
, that is, body *
, you're effectively blocking inheritance for all descendants, even if you try to set a different font family on one of them expecting its own descendants to inherit.
It should be sufficient to apply the font-family
style to body
and allow its descendants to inherit it organically (and possibly do the same with table elements in a separate selector or ruleset). As I've mentioned, the form elements you're trying to exclude, i.e. input,select,textarea
, do not inherit fonts by default in most browsers anyway.
That being said, the reason why your SCSS doesn't work is because :not()
doesn't accept a list of selectors in CSS. That's a feature of jQuery. Quoting my own answer to this question:
First and foremost, to answer the question directly: you can't pass a comma-separated selector list. For example, while the given selector works in jQuery as demonstrated in the fiddle, it isn't valid CSS3:
/* If it's not in the Α, Β or Γ sectors, it's unassigned */
#sectors > div:not(.alpha, .beta, .gamma)
Is there a workaround for this if I really want to avoid relying on a script?
Thankfully, in this case, there is. You simply have to chain multiple :not()
selectors, one after another, in order to make it valid CSS3:
#sectors > div:not(.alpha):not(.beta):not(.gamma)
Therefore the solution to your problem is to chain multiple :not()
selectors:
body {
:not(input):not(select):not(textarea) {
font-family:'Roboto', sans-serif;
}
}
Notice that I do not use the &
combinator here. This SCSS will compile to the following CSS, with the space following body
being a descendant combinator and the :not()
s representing any element other than the ones being excluded:
body :not(input):not(select):not(textarea) {
font-family: 'Roboto', sans-serif;
}
Using &
will cause the :not()
selectors to be attached directly onto body
:
body:not(input):not(select):not(textarea) {
font-family: 'Roboto', sans-serif;
}
Which means you'd be matching body
, and not any of its descendants. It's also a uselessly verbose selector because the body
element can never be either an input
, select
, or textarea
. But, again, you might as well just go ahead with applying this declaration to body
. You should avoid applying inherited declarations to all elements unless absolutely necessary.