Ferpalaciosd Ferpalaciosd - 6 months ago 12
CSS Question

Defining font-family in body doesn't work — but works with * and everything else

Going through a CSS course, I've bumped with an interesting problem.

Defining my font-family on body doesn't make any changes on the displayed fonts, but it works when defined with * or everywhere else, (like p, headlines, and so on). Why could this be?

Here you have the code:

This is the index.html

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Welcome</title>
<link rel="stylesheet" href="css/reset.css" type="text/css">
<link rel="stylesheet" href="css/style.css" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body> ...
</body>
</html>


This is the style.css


body{
font-family: 'Lato', sans-serif;
font-size: 15px;
line-height: 1.5em;
}


I'm also using Meyer's reset.css

Thank you!

Answer

tl;dr: always load resets and external resources before loading your site's custom CSS resources.


Explanation

What you've got here is a specificity issue with your reset CSS code.

When two CSS rules conflict with each other, the browser will use the one with the most specific selector of the two (or, in the case of equal specificity, it uses the last rule loaded).

The Mozilla Developer's Network defines "Specificity" as:

The specificity is a weight that is applied to a given CSS declaration based on the count of each selector type. In the case of specificity equality, the latest declaration found in the CSS is applied to the element. Specificity only applies when the same element is targeted. CSS rules that directly target an element will always take precedence over rules that an element inherits from an ancestor.

You said you're using Meyer's CSS Reset. That file contains a line that says font: inherit, which directly conflicts with your font-family rule (as well as your font-size). In this case, you've fallen prey to the last sentence in that definition of specificity: the reset's font property is being applied to paragraphs, headings, lists, etc., and "rules that directly target an element will always take precedence over rules that an element inherits from an ancestor" (in this case, the ancestor being the body.

You've got a couple of options here. First of all, double check that you're loading your CSS after the reset. That might fix it, but it might not. You can make your selector more specific than the selectors in the reset, which shouldn't be hard since they are designed to use the lowest specificity possible. This is why using body * as a selector worked.

The third option is one that is not recommended: using an !important decorator on any rules that you want to be treated as higher-priority than all other rules. This is dangerous, because it can easily cause unanticipated collisions.


Examples

Non-Working Example: Here is an example that doesn't work. This example doesn't work because Stack Snippets loads the CSS section before the HTML section -- since I'm including the reset in the HTML section, and since both CSS resources have a conflicting same-specifity rule, the most recently-loaded rule gets applied.

body {
  font-family: 'Lato', sans-serif;
}
<link rel="stylesheet" href="http://meyerweb.com/eric/tools/css/reset/reset.css" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css">

<p>Hello, world</p>

Working Example: Re-Order CSS Resources: Here you can see that if I explicitly load my CSS after the reset, the problem is resolved. Now my reset's rule is being used.

<link rel="stylesheet" href="http://meyerweb.com/eric/tools/css/reset/reset.css" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css">

<style type="text/css">
  body {
    font-family: 'Lato', sans-serif;
  }
</style>

<p>Hello, world</p>

Working Example: Use a More Specific Selector: This one works if you can't change the order in which your resources are included.

body * {
  font-family: 'Lato', sans-serif;
}
<link rel="stylesheet" href="http://meyerweb.com/eric/tools/css/reset/reset.css" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css">

<p>Hello, world</p>

Working Example: Use the !important Decorator: Like I said before, always think long and hard about using an !important decorator, as they're generally considered bad practice.

body {
  font-family: 'Lato', sans-serif !important;
}
<link rel="stylesheet" href="http://meyerweb.com/eric/tools/css/reset/reset.css" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css">

<p>Hello, world</p>