2

I'm trying to apply a custom font in my CSS for all non-input fields under the body (I'm using SASS btw). How do I do that? This isn't working:

body {
    &:not(input,select,textarea) { 
        font-family:'Roboto', sans-serif; 
    }
}

Edit

I originally posted this question because I suspected (incorrectly) that input fields inherited the font styles from the body. This isn't the case in general. However, I was using the Twitter Bootstrap framework, and it turns out that they've set font-family:inherit; on the input fields (which forces them to inherit the font set on the body elements).

FloatingRock
  • 6,741
  • 6
  • 42
  • 75
  • 2
    isn't it easier to set the different font to the input tags instead of everything else? even if there is a solution for what you are looking for - this won't work on old browsers - and it seems like doing thing upside down – Yaron U. Apr 20 '14 at 20:09
  • What is it you're actually trying to achieve? The code above and the accepted answer are useless, so it might help to explain the desired outcome. If it's any help, the input and textarea elements don't inherit font family by default. – Barney Apr 21 '14 at 10:14
  • @Barney RE: "`input`s and `textarea` elements don't inherit fonts." They do too -- on my browser anyway (Firefox 28 running Ubuntu 13.10). Do you have a reference that backs up your statement or is it purely experiential? – FloatingRock Apr 23 '14 at 10:59
  • That's right. So what are you trying to do with the code above? In other words, what is the problem you're trying to solve? – Barney Apr 23 '14 at 11:01
  • @Barney check out my updated comment – FloatingRock Apr 23 '14 at 11:01
  • I couldn't find anything specifying the behaviour, although Mozilla's article on styling forms [makes reference to it](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Styling_HTML_forms#Fonts_and_text). [It's a common problem on StackOverflow](http://stackoverflow.com/questions/2874813/why-textarea-and-textfield-not-taking-font-family-and-font-size-from-body) and [it's a popular thing to be fixed in reset stylesheets](https://github.com/necolas/normalize.css/blob/master/normalize.css#L243-L258). – Barney Apr 23 '14 at 11:18
  • That's really interesting – I had no idea Ubuntu behaved differently. [Can you confirm that using this test case I set up](http://codepen.io/barneycarroll/pen/xlGDm)? I get monospace on input and textarea, Lucida on the select, and Roboto everywhere else. – Barney Apr 23 '14 at 11:20
  • 1
    @Barney no wait, you're right. The font isn't inherited (it shows Ubuntu as the font). Turns out it's a Bootstrap thing; they set `font-family:inherit;` on the input fields and that causes the inheritance to happen. Thanks for the help Barney! – FloatingRock Apr 23 '14 at 11:20

1 Answers1

7

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.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 1
    Which evil soul went and -1'd the mans answer? This is the most correct answer yet. Thanks @BoltClock! – FloatingRock Apr 21 '14 at 07:19
  • 1
    @FloatingRock: [This meta answer](http://meta.stackoverflow.com/questions/251299/should-i-comment-or-just-downvote/251300#251300) might be relevant ;) – BoltClock Apr 21 '14 at 08:00
  • +1 Came here because of the comment on meta. Stayed for the great explanation of SCSS! – KyleMit Apr 21 '14 at 14:27