by

CSS: The Breakdown || The Selector and Grammar (Part 1)

Reading Time: 11 minutes

CSS is so cool and easy! Since it’s not a programming language, anyone can do it! You just need to know the properties and how to write a selector, and the job is done!

If you agreed with any of those statements, then this post is for you.
CSS is cool, but it isn’t easy. You can spend days debugging one line of CSS in just one browser. And it is true that a designer and a programmer can learn it in the same amount of time. Because the entry-point for CSS is learning some properties and how to write a selector, CSS doesn’t often get an exhaustive breakdown, and if it does, it isn’t about selectors and inheritance.

My goal here is to give you an exhaustive breakdown of one piece of CSS: Inheritance and specificity. I want this to be a breakdown that both designers and programmers can use, so it’s going to be thorough without over-geeking it. We’re going to start with a single element in a rule set and end with how a browser renders multiple stylesheets.

A Running Analogy between CSS and…Grammar?

I’m going to make a lot of comparisons between CSS and English Grammar. Because of my experiences studying and speaking other languages, it’s the easiest analogy I have. I know you’re super excited about this, too. I can see that twinkle dread in your eyes. You’re probably wondering: “Do you personally hate me?”; “Did you want to be a dentist as a boy?”; “Is there really nothing better to read on the toilet?” ; “Are you the kind of guy that likes reading the Apple Terms and Conditions?”; “Do you seriously like writing about this stuff?”.

Probably not, definitely not, definitely, maybe, Hell Yeah!1

English Grammar: A summary

Before we get started with an extremely long analogy between a selector and grammar, the polite thing to do is provide a summary of the English parts of speech.

Noun:
a person, place, thing, or idea. e.g.:Lillith (a proper noun / person), house (place), dog (thing), loyalty (idea)
Pronoun:
a word that can sit in place of a noun. e.g: she, it, her, that
Verb:
an action. e.g.: Lillith is good.
Adjective:
something that describes a noun or pronoun. e.g.: Good dog.
Adverb:
something that describes a verb, adjective, or another adverb. e.g.:Reallygood dog.
Preposition:
a relationship that a noun or a pronoun has to another noun or pronoun. e.g.: Dog is in the house.
Conjunction:
something that combines two clauses. e.g.: and, or, but, if
Interjection:
A short exclamation. e.g.: hey! Ouch! Dangit!

The Big Picture of CSS

I am trying to keep myself inline with the language that the W3C has chosen, but I might deviate in order to make it easier to explain some concepts. The specifications might use a word or maybe one sentence to describe a pretty heavy concept, so I’ll break things down into smaller pieces, or quote definitions from other authoritative bloggers like Louis Lazaris.

First, let’s start with an overview of the different parts of CSS. Then we’ll dive into gory, gruesome detail, one blog post at a time.

Property

A property is a characteristic of a given HTML element that you are able to modify with CSS. Popular properties might include display and font-size. In CSS, the property is the thing before the colon. These are adjectives.

Element

This is a word that corresponds to an element in the HTML document. For the sake of simplicity, let’s call pseudo classes and pseudo states Elements, too. They’re just nouns about other nouns.

Combinator

Combinators are symbols that allow for us to use one or more elements in a particular order. Combinators will reflect how elements are organized in the HTML document. These are conjunctions.

Selector

Put all your elements together, add some combinators, pseudo-classes, or pseudo-elements. Everything before the curly braces ( {} ) is now a selector. We have specificity when we add up the values of each element’s specificity. This is a sentence.

Specificity

An Element contributes a specificity value of either 0 or 1 into the selector’s specificity. When we add up the values of all the elements that are targeted as elements, Id’s, and classes, we have the specificity of the selector.

Declaration Block

A declaration block is the section of CSS where the property/value pairs appear. Everything found between the curly braces (not including the comments) is a declaration block.2

Rule Set

A rule set is a single section of CSS including the selector, the declaration block, and the different lines with properties and values.2

Stylesheet

Once you have a bunch of rule sets together, you call it a stylesheet. The specificity of each selector in a rule set will tell the browser which elements get particular styles.  This stylesheet can be internal or external.

The Small Cascade

The browser analyzes the stylesheets, determines specificities of all the rule sets, and applies styles. This is also where overrides take place.

The Big Cascade

We aren’t the only party involved in styling the page; the web browser and the end-user also have a say in the styles.  The Big Cascade is composed of three small cascades, in this order:

  1. User Agent
  2. Author
  3. User (the person looking at the web page)

Part One: Element, Combinator, and Selector

Originally, I was going to discuss all of these topics in one blog post. That post would have been close to 15,000 words. No one wants that. So today, we’re going to discuss the Element, Combinator, and the subsequent formation of the selector, and that’s it. Two thousand words on just these three topics is more than enough.

The Element

Think of your element as a noun; it’s a thing in your HTML document. Everything in the HTML document is some sort of thing: an a, a p, or a div. You get down to it, they’re just elements.

Think of IDs and classes as pronouns; they’re just ways to refer to particular element or elements. While Lillith is a dog, I’m more likely to reference her using words like “she” or “Lillith” than I am to just call her “dog”. Classes and Id‘s are just ‘pronouns’ for plain old fashioned HTML elements.

The Id

If my element were a person, it would be unique, right? In grammar, that’s called a proper noun. When I say “Lillith”, there is no mistaking the person about whom I am speaking. Just as I say “Lillith” to target her over all other dogs, I use # to target one element over all others, too. Using # in my selector targets the ID attribute of an element. Using the # contributes a value of 1 to the ID portion of a selector’s specificity, and it’s the most specific way to target an element.

Lillith

#lillith { color: white}

The Class

If my element were a group of things, that’s not as specific; after all, I can make an element a member of many types of groups. So, a class is basically any group of which that element is a member. When an element is targeted as a class, we contribute a value of 1 to the class portion of the rule set’s specificity.

There are three different ways we can target an element that qualify as a class

  1. We target the class attribute
  2. We target attributes
  3. We target a pseudo-class, pseudo-element, or pseudo-selector

Targetting the class attribute

If we’re targeting an element using the class attribute, we just need to use the period.

Lillith

Maggie

.dog{
height: 35in;
}

Targetting the  Attributes

We can target an element based on any attribute that applies to it by using the square brackets “[]”. There’s two techniques with this:

Lillith

Maggie

[data-weight] {} /*all elements that have the attribute "name" */

[data-weight="fat"] {} /* all elements that have a value of "fat" in the attribute data-weight */

The pseudos

Sometimes we might not want the whole element; we might only want a certain part of it or maybe we only want it at certain times, or places. These cases might be pseudo classes or pseudo elements. We identify the “pseudos” because they start with the “:” It’s more common to see the colon  chained to another element, but I’m keeping it simple for the time being.

Lillith

Maggie

pseudo elements

As it would turn out, an element can have its own sub-element. All elements can have a :before and an :after, which are like having two extra elements! The cool part is that these pseudo-elements won’t be read by screen readers, which makes this space ideal for icons and assistive text. The proper way to denote a pseudo element is like what you see below. Despite it being proper, not many browsers (cough, cough, Internet Explorer) recognize this syntax.

::after{
content: 'poop';
}
::before{
content: 'food';
}

Another type of pseudo element actually targets the space inside of that element:

::first-letter{
font-size: 2em;
}
::first-line{
line-height: 2;
}
Dynamic Pseudo Classes

The most popular pseudo classes are called “dynamic pseudo classes”. That means that they occur only when the end user is interacting with that element in some way.

:hover
This occurs when an input device, usually a mouse, is hovering over the element
:focus
This is when the element has focus. You focus on that element by either clicking it with a mouse or with some key of the keyboard. Not all elements are focusable; it’s usually just the interactive ones like links and form inputs. You can also make ‘non-focusable’ elements work with :focus by making those elements contenteditable
:active
This is the act of clicking the button with your mouse, or hitting the enter key on the keyboard.

Typically, your dynamic pseudo classes start as a hover, then become a focus, and finally they are active.

:hover{
height: 90%;
}
:focus{
color:red
}
:active{
overflow:auto
}
Linking Pseudo Classes

As it turns out, we have two pseudo classes just for links.

:link
This is for links that haven’t yet been visited.
:visited
This is for links that have already been visited
:link{
color:blue;
text-decoration:none
}
:visited{
color:purple;
text-decoration:underline

}

So what’s the difference, then, between :link {} and a {}? The specificity! Remember, the :link is a pseudo-class, so it contributes in the class part of a rule set’s specificity, while a contributes to the element part of specificity.

numeric and algebraic pseudo classes

We can use this for indicating that we only want an element in very specific cases. Maybe it’s the first child of a parent, or possibly the last child. In CSS3 we can indicate if it’s the even-numbered child, or the child that’s divisible by three.

:first-child{
position:absolute;
}
:nth-child(even){
position:relative
}
:nth-child(3n){
position: static;
}

There is an exception to the specificity:

Not every pseudo selector adds specificity. And I mean that kind of literally, as it turns out. If you use the :not() selector, the contributed value is 0. We haven’t really dived into specificity yet, but keep that in the back of your head for the next blog post.

Lillith

Maggie

:not(.dog) {
display:none;
}

The Element

If my element isn’t a member of any sort of group, then we’re okay applying our styles to all of them. Remember, the element is just a thing, so targetting an element all on its own tells the browser, “all of of this thing”. It’s no different than saying, “dogs are good” — and it implies you’ve never had one pee on your shoes. This contributes a value of 1 to the element portion of a rule set.

Lillith

Maggie

h1 {
width: 15in;
}

The exception

There is also the * selector. This means “any”. Anything is the opposite of something, therefore this also contributes a value of 0 to specificity.

The Selector

A selector is one or more elements strung together that styles a code block. Before we get into the details of writing it, you should know how to read it. That’s because the browser reads your selector from right to left.

If you want to understand a selector, read it backwards. The right-most element is the one that gets the styles. Everything to the left of that last element just helps the browser figure out which one.

Stringing the elements together

There’s three different ways that we can string the elements together in a selector. You don’t have to string them together at all, but often it proves to be pretty helpful. The ways that you string together elements could be considered the “conjunction” of our selector-sentence.

Whitespace

This one is pretty simple: Separate two elements by a single space.  This is also called a ‘general descendant’ or ‘non-specific descendant’. This means that one element is somewhere inside of another.

body footer {} /*any footer inside of the body */

.animals .dogs {} /* any element with the class dog, that's also in the class animal*/

#franksPets #lillith {} /* the element with the id of lillith, which is inside the element franksPets */

#franksPets .dogs .mutt {} /* any element with the class mutt that is also inside the class dogs,   which is inside the element franksPets */

Chaining Classes

Think of this as saying “and is” a whole bunch. We chain elements when we eliminate the whitespace and by doing so we tell the browser that this single HTML element must be all of these things at once for the style to apply.

Lillith>Kiddo

Fatty

h1.border-collie {} /*the class border-collie and is an h1*/

.dog.border-collie{} /*the class border-collie and is the class dog*/

h1#maggie {} /*maggie when she is also an h1*/

Chaining Pseudos

Those of us who are experienced in writing CSS don’t think about it, but writing something like a:hover {} is actually a type of chaining. Now, we just understand that :hover is a pseudo class that we’re chaining to the a element. That means that we can chain pseudos a variety of interesting ways.

:link:hover{
content:'click me!' 
}
:visited:hover{
color:gray
}
:visited:hover::after{
content: 'you went here already'
}

Combinators

When you see a combinator, read this as saying, “only if”. A combinator is telling you that this style applies only if certain conditions are met in the HTML document — namely that HTML elements are organized in a specific way. This is the closest you can get to having actual logic in CSS.

Lillith>

MaggieFatty

h1 + .dog {} /* an element with the class dog, only if it comes immediately after an h1*/

.dog ~ .dog {} /* an element with the class dog, only if it comes somewhere after another element with the class dog*/

.dog > .Name{} /* element with the class Name, only if it is immediately inside of an element with the class .dog*/

#lillith + #maggie > span {} /* an element called span, only if it's immediately inside #maggie, only when it's immediately after #lillith*/

These combinators are extremely useful and they come in very handy when you’re writing CSS for HTML that’s managed in a Content Management System. Let’s explore how these combinators work in some more detail:

>Direct Descendant
This works only when one element is immediately inside another. Remember that CSS is read right-to-left, so you should read this as, “whose parent is…”
~Non-adjacent sibling
This works when another element appears before this one. Read it as, “element that is found after…”. When content may or may not be present, use this selector to create one style if the “older sibling” is present, and another when the older sibling isn’t. Keep in mind that both this element, and its sibling, must have the same parent.
+Adjacent sibling
This works when another element appears immediately before this one. Read it as, “element that is immediately after…” Again, if you don’t know when content will be present, you can use this to create one style for many blocks of content, and another when it’s all alone.

When Combinators aren’t So Useful
I love the combinators and I think that if you write CSS at an enterprise level, for content management, they must be a part of your vocabulary. However, be mindful that you are writing an extremely specific rule that won’t be used more frequently than it will be used . Think about it, if you write h3 + p{}, you’re telling the browser, “look for every p, and see if an h3 came right before it. Now think about how many times you’ve written <p> in your HTML. For this reason, folks are in the habit of advising against the combinators for performance reasons. I am yet to see any hard evidence that the combinators can cause such an issue, but I can see how it could be possible.

Combinators and IE aren’t good friends
Internet Explorer 7 is extremely fickle with these combinators. This is because IE 7 mistakenly interprets HTML comments as elements.3 As a result, something like this will fail in IE7:

Lillith

Maggie

h1 + h1 {font-size: .75em;}

Your best work-around for IE7 is to avoid the HTML comments. If that’s not going to happen, use the non-adjacent sibling selector instead.

The Selector Says a Lot

There’s a few big ideas that we get from all of this talk about selectors and sentences:

  • Everything in the selector is just a reference to an element
  • The selector should be read from right to left
  • The last element you write is the one the browser targets
  • We can be as specific, or non-specific, as we want, with how we describe the very last element in our selector
  • We’re talking about CSS selectors, not jQuery selectors

If you’ve written CSS for a while, go back, look it over, and read it like a sentence. Is it too long? Too short? Should you say it with fewer words, or use better words?

If you’re new to CSS, write a sentence first. Describe that HTML element, and then build your selector using what you’ve learned.

If you’re a cat person, try a different blog.

Now that we’ve established that your selector is a sentence, we need to determine its worth — the specificity. Stay tuned…

Sources and Whatnots

1You have no idea how hard I worked squeeze in a reference to a British pop band and an American metal band in the same sentence.
2Louis Lazaris: www.impressivewebs.com/css-terms-definitions
3Ziadrahhal.com