Introduction to CSS3

Laying down the foundation on which we'll be building all of our CSS knowledge..

Scroll down...




Welcome to CSS3! Just like HTML5, CSS has undergone a healthy revamping over the past several years. The old specification, CSS2, showed up in 1998 (and was updated to CSS2.1 in 2011). Just like with HTML5, CSS3 isn't a single massive release but the evolution of a standard over time. Because of this, the major browsers already support most features.

Where HTML5 helps you to add functionality to the page and better define the semantic structure of its content, CSS3 is all about expanding your available creative options. Some of its features, which we'll emphasize in this lesson, can make your life a lot easier than the hacks you'd otherwise have to implement. Others are best left until you've spent enough time with CSS to get truly familiar with its power (we'll briefly cover those at the end).

This lesson won't attempt to span the breadth of CSS3 (that'd take up the entire course). And, frankly, the best way to expand your CSS vocabulary is just to try and build something, Google for an example of it, and implement it yourself.

Our goals for this lesson are more targeted -- we want introduce some practical ways for using the dozen-or-so best new parts of CSS3. We'll be covering these in more detail as we move through the upcoming lessons.

A Brief Overview

Here's a quick look at what we'll cover below:

  • Media Queries are used everywhere to activate certain CSS depending on certain browser properties (like its width). They are used to gracefully degrade a site's structure from web browsers to mobile.
  • Box Sizing lets you optionally enforce the specified height and width of an element (instead of making them a function of padding / border as well)
  • Attribute Selectors allow you to target CSS at elements based solely on their attributes, for instance links that point to a particular href.
  • Rounded Corners have been around for awhile, but are technically CSS3.
  • Shadows give you all kinds of control over the shadow produced by your elements (e.g. buttons that look like they stick out from the page)
  • Calculations allow you (in supported browsers) to make one attribute (e.g. width) a function of multiple values (e.g. both % and px). Useful for those "Center it at 50% minus 40px" cases.
  • Web Fonts give you access to an enormous array of fonts that are freely available online. You can download them into your page dynamically.
  • Generated Content allows you to use CSS to prepend or append elements with additional elements, for instance to put novelty quotes around your blockquote.
  • Other Cool Stuff includes animations, gradients, paragraph columns, highly targeted pseudo-classes like :nth-child(4), and multiple backgrounds.

Media Queries

Media queries are one of the biggest advances in enabling the convergence of web and mobile sites. Unless you've lived under a rock, you can see that mobile is a massive growth area and so serving mobile devices needs to be at the front of your mind.

Media queries basically allow you to ask the browser for some of its properties (like how wide the viewport is) and then only apply a group of styles if the specified conditions are true. This has allowed designers to create websites which "degrade gracefully" from a full-width layout to a single-column mobile-friendly grouping as the browser width is reduced.

Using media queries is extremely simple -- just specify a condition and anything inside the brackets gets executed if it evaluates to true. You can use it either within an existing stylesheet or on the link to import a stylesheet:

// CSS media queries on link elements
<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
<link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" href="iphone4.css" type="text/css" />

// CSS media query within a stylesheet
  .facet-sidebar {
    display: block;
  @media (max-width: 600px) {
    .facet-sidebar {
      display: none;

Check out the MDN Media Queries Guide for a comprehensive reference, but you won't need to dig too deep to use media queries effectively. The example above should tell you pretty much all you need to know about how they're structured.

For a live example, try resizing your browser and seeing what happens to the navbar on this site. At certain widths, media queries are activated and its properties are changed slightly.

Media Query Options and Examples

Some of the properties you can use to define your query are:

// *** More Common ***

// Width
@media (min-width: 1100px) { ... }

// Height (of the browser viewport, not the HTML page)
@media (max-height: 400px) { ... }

// Screen aspect ratio (width / height)
@media screen and (min-aspect-ratio: 1/1) { ... }

// Orientation (common on mobile)
@media all and (orientation: portrait) { ... }

// *** Less Common ***

// Color (is it a color display?)
@media all and (color){ ... }

// Device properties (as opposed to page properties above)
@media screen and (device-aspect-ratio: 16/9) { ... }
@media screen and (max-device-width: 799px) { ... }
@media screen and (max-device-height: 799px) { ... }

// Grid (Is this a TTY accessibility device?)
@media handheld and (grid) and (max-width: 15em) { ... }

// Device resolution (e.g. the printer you're using)
@media print and (min-resolution: 300dpi) { ... }

For a more complete example, to specify a stylesheet for handheld devices and screen devices with a width greater than 20em, use:

@media  handheld and (min-width: 20em),
        screen and (min-width: 20em) { ... }

Media Query Tricks and Tips

When working with media queries, there are a few tricks to keep in mind:

  • CSS that's activated by a media query takes its normal place in the CSS hierarchy... meaning if you want to override the styling of an element but don't put the media query in the right spot within your stylesheet (e.g. below the prior styles), it won't do anything. This may sound intuitive but we promise that you will more than once put queries in the wrong place and pull your hair out trying to figure out why they won't activate. It takes practice.
  • You can use the logical operators and, not, or (by separating terms with commas) and only to define your query. For instance:

    @media screen and (max-width: 600px) { ... }
  • To specify an entirely different stylesheet, add a media attribute to your link tag:

    <link rel="stylesheet" media="screen and (max-device-height: 799px)" />
  • Most of the properties just listed can be prefixed by min- or max-, which does exactly what you'd expect it to.

  • When you want to implement media queries, simply find an example on the web and copy it.

  • Media queries apply to more than just device properties. You can, for instance, specify a totally separate stylesheet for printing.


You've probably already found frustration dealing with the CSS box model, especially around how padding actually expands the height and width of the box. When things go all wonky on you, simply set box-sizing: border-box; and feel the sanity slowly return.

"Border-box" fixes the width and height of the element. That means that the padding, instead of outwardly expanding the size of the element box like normal, will reduce the size of the inner content box instead. See the MDN docs for more info.

Attribute Selectors

Just like being able to identify elements based on their tag, class or ID, CSS3 lets you target based on their attributes:

  • [attr=val] -- matches a DOM element having the attribute attr and the value "val"
  • [attr^=val] -- matches a DOM element having the attribute attr and a value starting with val
  • [attr$=val] -- matches a DOM element having the attribute attr and a value ending with the suffix val
  • [attr*=val] –-- matches a DOM element having the attribute attr and a value containing the substring val

For example, to emphasize all links that point toward the blog:

    font-weight: bold;

Or to target a specific input type (frequently used):

    font-size: 2em;

Rounded Corners

This used to be obnoxiously hard, and now... so easy with the border-radius property:

    border-radius: 4px;

If you make the border radius larger than the height or width of the element, the element typically displays as a circle or like a round-ended hot dog.

10px Border Radius!
100px Border Radius!

You no longer need to use vendor prefixes (e.g. -webkit-border-radius) with this property.


box-shadow lets you specify a drop shadow for an element. It takes several inputs which determine the width and positioning of the shadow. Its inputs, in order, are:

box-shadow: horizontal-shadow vertical-shadow blur-width spread-width color [or inset or initial or inherit];

For example:

    box-shadow: 5px 15px 10px 0 #f00 inset;
Shadow Box!

See the box-shadow docs for details. You no longer need to use vendor prefixes (e.g. -moz-box-shadow) with this property.

You can also add a text-shadow, which does (predictably) the same thing to text. Use this sparingly unless you want your text to look awful...


You can use the calc() function inside of CSS to do simple units-based arithmetic like subtracting 80 pixels from half the width of the containing div:

.banner {
  width: 90%;  /* fallback for browsers without support for calc() */
  width: calc(50% - 80px);
  border: solid black 1px;
  box-shadow: 1px 2px;
  background-color: yellow;

This used to be really frustrating stuff, so having the ability to do simple math directly in CSS3 has been a lifesaver. Play around with it -- it just sort of "works". See the MDN docs for more info.

Web Fonts

It's not terribly new, but the ability to import external fonts to your sites was a big deal when the functionality first arrived. Now you can import fonts from Google, Typekit, or your own server just by using the @font-face rule to specify its origin.

Web fonts are a two-step process -- they often first import a stylesheet from the source, and that stylesheet contains the detailed font information.

The markup you add to your <head> section:

<link href="" rel="stylesheet" />

And what that imports automatically when the page loads:

/* latin */
@font-face {
  font-family: 'Satisfy';
  font-style: normal;
  font-weight: 400;
  src: local('Satisfy'), url( format('woff2'), url( format('woff');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;

Now the font "satisfy" (only the 400 weight) is available for you to use in your font-family property.

Generated Content

You can now automatically add another div-like element either before or after the existing element by purely using CSS. This is done with the ::before and ::after pseudo-elements. These elements, which should have the content attribute specified (even if it's blank), can be used to add annotations or stylistic flairs to either side of an existing element.

For example, if we wanted to create a simple footnote notification bubble after a line of text:

    content: "1";
    font-size: .5em;
    vertical-align: super;
    border-radius: .5em;           // to make it circular
    background-color: lightyellow;

Other Interesting CSS3 Tidbits

This stuff should all be in the territory of "looks interesting, I'll check it out later if I need to". We're including it here so you have an idea of what's out there not so you can start using it right away.


CSS3 provides lots of support for animations, an arena typically reserved for JavaScript. They often cover simple cases and can render more smoothly than equivalent JavaScript animations.

The most common way is by using the transition property to transition a CSS property from one value to another based on some trigger (like hovering or activating it with JavaScript code). If you really need to get into animations, check out the MDN Animations Guide, but it's a rabbit hole so don't get lost.


It used to be a real pain to add in gradients (think a single pixel image repeating), but now CSS3 lets you specify the properties of the gradient and whether it's meant to be linear or radial. The syntax can be a bit odd so there are all kinds of gradient generators out there to help you out. See Additional Resources for more information.

The basic syntax of a gradient used in a background looks like:

background: linear-gradient(to bottom, blue, white);

CSS Columns

If you want to break the interior of a paragraph into 2 columns... just use the CSS columns property! Shown below with some vendor prefixes:

.container p{

New Pseudo-classes

CSS3 has several new pseudo-classes which target elements based on their position in the document or their relation to other elements. You shouldn't immediately start using these... this is just to show you what's out there:

  • :only-child – in case you have an element in the document tree that is the only child of its parent, it can be targeted by this pseudo-class.
  • :empty – targets elements that don’t have any children or any text, for example an empty element such as <p></p>.
  • :nth-child(n) – it takes advantage of numeric (n) values and targets child elements in relation to their position within the parent. To give you a precise example, a list of blog comments would probably look more appealing with alternating background colors – this can be done using this pseudo-class.
  • :first-of-type – this targets the first of a specific type of element within a parent, and is the opposite of :last-of-type.
  • :first-child – targets the first child element in a parent, regardless of its type. It is the opposite of :last-child.
  • :not(s) – this one targets elements that are not matched by the specified selector (s).
  • :root – this one targets the root element of a document.
  • ::first-letter - for making that first letter really pretty.
  • ::first-line - target only the first line in a paragraph.

Multiple Backgrounds

You can pass a comma-delimited list of background properties to actually set multiple layered background images to an element. Designers use this to achieve interesting parallax effects by using JavaScript to animate different backgrounds at different rates while the user scrolls. See the MDN docs for more info.

Browser Prefixes

There's one last important bit that you need to understand in order to effectively implement CSS3. Because each browser does things slightly differently, you'll sometimes have to list the same style multiple times by using the "browser prefixes". Each prefix applies to the primary CSS engine used by a particular browser.

This is a legacy thing -- modern browsers are capable of using the standard properties. For many developers, supporting the old browsers isn't necessary so you don't need to worry about the prefixing. You'll certainly see them in older CSS and older examples on the web.

As an example, a real-world implementation of the box-sizing property would actually look like the following:

 -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
      -o-box-sizing: border-box;
         box-sizing: border-box;

Just make sure to put the non-prefixed version last and you're good to go.

Check out this article from CSS-snippets for more information about this and this blog post for a more up-to-date listing of which prefixes are actually needed (as of 2014).

Code Review

The important bits of code from this lesson

/* Apply only on wider than 500px browsers */
@media (min-width: 500px) { ... }

/* Import this stylesheet only on mobile */
<link rel="stylesheet" media="handheld" />

/* Chain multiple criteria */
@media screen and (min-aspect-ratio: 1/1) { ... }

/* Media Query Types */
@media (min-width: 1100px) { ... }
@media (max-height: 400px) { ... }
@media (min-aspect-ratio: 1/1) { ... }
@media (orientation: portrait) { ... }
@media (color){ ... }
@media (device-aspect-ratio: 16/9) { ... }
@media (max-device-width: 799px) { ... }
@media (max-device-height: 799px) { ... }
@media (grid) { ... }
@media print and (min-resolution: 300dpi) { ... }

/* Make padding and borders push inward */
box-sizing: border-box;

/* Select based on a given attribute */
[attr=val]{ ... }

/* Match parts of an attribute */
[attr^=val]{ ... }  // Starts with "val"
[attr$=val]{ ... }  // Ends with "val"
[attr*=val]{ ... }  // Contains "val"

/* Rounded corners */
border-radius: 10px;

/* Red fuzzy inset shadow */
box-shadow: 2px 2px 2px 0 #f00 inset;

/* Dynamically calculate values (with fallback!) */
width: 90%;  /* fallback for browsers without support for calc() */
width: calc(50% - 80px);

/* Import a google webfont */
<link href="" rel="stylesheet" />

/* Use the imported font (just like a normal one) */
font-family: Satisfy, serif;

/* Put novelty quotes before and after a blockquote */
blockquote:before {
  color: #ccc;
  content: "<<";  // Can use special UTF chars too
  font-size: 4em;
blockquote:after {
  color: #ccc;
  content: ">>";
  font-size: 4em;

/* Target the first child element */
.parent-class:first-child{ ... };

/* Browser Prefixes (outdated mostly) */
 -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
      -o-box-sizing: border-box;
         box-sizing: border-box;

Wrapping Up

Hopefully you pulled some useful tidbits out of these examples. CSS3 has a lot of stuff on top of the already-expansive CSS. Don't worry if you're forgetting things. Remember -- you really learn by building and you'll get plenty of opportunity to do that soon. We also have more detailed lessons on these concepts coming up in this section.

Oh, before we go... the most painful thing you'll do is probably centering elements. Take a glance through this helpful blog post and this code generator before you get too many gray hairs.

Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

Sorry, comments aren't active just yet!