Lesson Weekend

Here's something you may not know: every browser has its own set of default CSS applied to all sites, whether or not we want them to. For instance, take a look at this super basic project:

user agent stylesheet in inspector

This site is just HTML with <h1>, <hr>, and <p> tags. It has no CSS stylesheet. Yet if we inspect it, we can clearly see a CSS rule being applied:

html {
  display: block;
}

Because this site has no stylesheet, we know this was applied by the browser.

It gets even trickier. You see, different browsers apply different default rules. (You can check out the Font Rendering Differences: Firefox vs. IE vs. Safari article by Chis Coyier for examples of how different browsers render content differently.)

These differences may seem trivial, but they can cause real issues, interfere with developers' custom CSS, and cause sites to look different in different browsers. But clients and companies want their site to appear and function the same across all platforms.

So how do we avoid issues created by differing browser default CSS? By normalizing default CSS.

CSS Normalizers

Since around 2004, developers have included their own custom CSS to override unwanted default CSS from browsers. Overriding these default styles is commonly referred to as normalizing. Tools to do this are called CSS normalizers.

These normalizers target and override styles that are notably inconsistent across different browsers, in order to make them consistent.

One of the most popular normalizers is Nicolas Gallagher's open-source, publicly available normalize.css. Click the link to take a peek at what this stylesheet is doing. Some of the CSS syntax may be new to you, but much of it should be recognizable. (And Gallagher has included detailed, helpful comments explaining exactly what each rule is doing, and why).

You are expected to include a CSS normalizer in your own projects throughout this course. But don't worry, this is simple, you can:

  1. Link the online normalize.css stylesheet in the <head> of your HTML. or;
  2. Clone down or copy/paste the normalize.css stylesheet into a normalize.css file in your own project directory, and link that local stylesheet into the <head> of your document.

That's it! One simple stylesheet, and you no longer have to worry about inconsistencies across browsers.

Border Box

However, there's one type of style that's not overridden or reset by most CSS normalizers, including the one linked above, called box-sizing. You can learn more about why it's not included in the normalize.css stylesheet in this GitHub discussion. Yet, despite not being included in this specific normalizer, it's becoming a common best practice. So we'll use it in class, too.

Here's the deal: in a standard browser's default, every box has a default box-sizing property set to the value content-box. This means that the box's size is considered to be the size of its content.

However, this rule often proves confusing for developers. Let's observe why. Check out this site titled Border Boxes Rule. At the top is a typical box model, with a default box-sizing property set to content-box.

Just below the diagram there are a few boxes in a grid filling a parent.

content-box without border

Here's the CSS for the three box row:

.box-grid {
  background: #fff;
  width: 900px;
  height: 300px;
}

.box {
  display: inline-block;
  height: 200px;
  margin: 50px 10px;
  width: 280px;
}

Notice the margins and widths of containers add to exactly 900px. There is no room for additional pixels.

But what if we wanted a visible border around each box? Here's the result:

.box-grid {
  background: #fff;
  width: 900px;
  height: 300px;
}

.box {
  border: 2px solid #444;
  display: inline-block;
  height: 200px;
  margin: 50px 10px;
  width: 280px;
}

content-box with border

The borders cause content to overflow, and boxes to flow out of their parent. You see, the browser is rendering each box with a total width of 280px without the border. Why? Because setting box-sizing to content-box instructs the browser that the box's width is only the width of the content, which doesn't include borders.

This is problematic because most developers consider borders to be a part of the box itself, not an independent element. It's also more difficult to mathematically account for all individual borders, and box contents.

Instead, we can simply tell the browser that the border should count as part of the box's total size. This can help prevent confusing errors, and makes calculations simpler. We do this by adding box-sizing: border-box to our rule:

html {
  box-sizing: border-box;
}

*, *:before, *:after {
  box-sizing: inherit;
}

.box-grid {
  background: #fff;
  width: 900px;
  height: 300px;
}

.box {
  border: 2px solid #444;
  display: inline-block;
  height: 200px;
  margin: 50px 10px;
  width: 280px;
}

These rules are best practice way to apply border-box to all box models cleanly and without them being inadvertently overwritten. The resulting grid looks like this:

border-box with border

Much better! Notice the border could get as large as necessary and will still be attributed to the space inside the total width, rather than outside.

html {
  box-sizing: border-box;
}

*, *:before, *:after {
  box-sizing: inherit;
}

.box-grid {
  background: #fff;
  width: 900px;
  height: 300px;
}

.box {
  border: 15px solid #444;
  display: inline-block;
  height: 200px;
  margin: 50px 10px;
  width: 280px;
}

border-box with thick border

Additional disclaimer

All px values in this lesson add up correctly. The width and margins of all the children in the grid equal the width of the parent. But if you try to recreate this in your own stylesheet, you may get frustrated. Truth is, each of the children above are probably more like 277px wide with 10px margins. Here's the reason, explained in Julienne Etienne's Medium article Why You Should Stop Using Pixels In CSS:

Pixels in CSS are NOT real screen sized pixels. They’re actually optical reference units. ... This could be why some spend so much time bickering with UX designers over tiny margin/ padding differences. The device pixel ratio depicts the size of the optical reference unit and that depends only on the device or the desktop zoom level set by the user.

For us, this means even when create 'pixel perfect' designs, they may represent themselves in incongruent ways... you're not crazy... it's just that px is not quite as absolute as we may be lead to believe.