CSS Selectors

To style elements, we must be able to find the specific element to style. This is what selectors are for in CSS.

What is a CSS selector?

CSS is used to style HTML elements but to do this, CSS must be able to locate the elements that will be styled. HTML elements are selected using css selectors - a pattern through which to identify an element - which take the following format:

selector {
    attribute1: value;
    attribute2: value;
}
  • Each attribute represents a key: value pair
  • Each attribute pair must end with a semi-colon, this is the delimiter
  • The attributes specified within the block, {}, belong only to the specified selector

The simplest selector is the tag/type selector, this will select all elements in a document that use the specified tag. The following example demonstrates styling all paragraph text to be blue:

<html lang=en>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
    p {
        color: blue;
    }
    </style>
</head>
<body>
    <p>Some text</p>
    <p>Some more text</p>
</body>
</html>
The CSS is embedded into the file in the head of the document, it could also be specified inline or more preferably in an external stylesheet.

The previous example would render the following blue text:

Some text

Some more text

The color attribute is used to change the colour of text, specified using the American English spelling.

The id and class attributes

Often, we will want to style only a single element or a group of specific elements that cannot be solely targeted using a type selector. To do this, two attributes exist that can be used on any HTML element:

  • id: An identifier that should only be used once per document, such as for the main page heading on each page
  • class: An identifier that can be used on many different elements in the same document

In the following example, a h1 element (which should appear once per page in most cases anyway) is given the id of title:

<html lang=en>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
    <h1 id="title">The example site</h1>
</body>
</html>

To select an element by its id in CSS, using an ID Selector, specify a # followed by the name of the id to target. The following example adds a background colour to the title and changes the colour of the text:

<html lang=en>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
    #title {
        color: white;
        background-color: black;
    }
    </style>
</head>
<body>
    <h1 id="title">The example site</h1>
</body>
</html>

This will render as follows:

The example site

There will be white space around heading when displayed in the browser; this is to be expected and will be explained further in the section on the CSS Box Model.

The following example demonstrates a subtitle class being applied to multiple h2 elements:

<html lang=en>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
    #title {
        color: white;
        background-color: black;
    }
    </style>
</head>
<body>
    <h1 id="title">The example site</h1>
    
    <h2 class="subtitle">The first section on examples</h2>
    <p>Examples are often brief for the purpose of conveying core material rather than distraction</p>
    
    <h2 class="subtitle">The second section on examples</h2>
    <p>This is the second section talking more about examples.</p>
</body>
</html>

Without styling the elements with the subtitle class, the example will look as follows:

The example site

The first section on examples

Examples are often brief for the purpose of conveying core material rather than distraction

The second section on examples

This is the second section talking more about examples.

To style only elements with the subtitle class, a Class Selector must be used; first a period, ., is specified followed by the name of the class to target:

<html lang=en>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
    #title {
        color: white;
        background-color: black;
    }
    
    .subtitle {
        background-color: gray;
        color: lightgreen;
    }
    </style>
</head>
<body>
    <h1 id="title">The example site</h1>
    
    <h2 class="subtitle">The first section on examples</h2>
    <p>Examples are often brief for the purpose of conveying core material rather than distraction</p>
    
    <h2 class="subtitle">The second section on examples</h2>
    <p>This is the second section talking more about examples.</p>
</body>
</html>

The example with the subtitles styled will now look as follows:

The example site

The first section on examples

Examples are often brief for the purpose of conveying core material rather than distraction

The second section on examples

This is the second section talking more about examples.

HTML elements can have multiple ids and classes specified, the requirement is that they are separated by a space: <h1 id="title" class="large centered">...</h1>

Attribute and Universal selectors

Attribute selectors are used to select elements based on the element, its attributes, and attribute values that an element holds. Attribute selectors can take any of the following forms:

/* 
    select all matching elements that have the specified attribute, 
    irrespective of value 
*/
selector[attribute] {
}

/*
    select all elements whose attribute exactly matches the specified value
*/
selector[attribute=value] {
}

/*
    selects all elements whose attribute exactly matches the specified value or
    where an attributes values, separated by whitespace, contains the specified
    value
*/
selector[attribute~=value] {
}

First, a selector of any type is specified. A set of square brackets is opened afterwards where the attribute to check for is specified.

A universal selector is specified using the wildcard symbol, *. This indicates that every element in the document is to be selected. It is common to see this for something called a CSS reset where certain default attributes are changed, for example the following removes the default spacing in and around all elements as well as changes how element sizes are calculated (explored further in the box model):

html {
    box-sizing: border-box;
}

*, *::before, *::after {
    box-sizing: inherit;
    margin: 0;
    padding: 0;
}
The ::before and ::after are psuedo-element selectors, used to style a specific part of a selected element - in this case, every element.

Psuedo-class and pseudo-element selectors

Psuedo-class selectors

A psuedo-class selector selects elements that have some state to target, such as an element being active or being hovered on. Psuedo-classes take the following form in CSS:

selector:psuedo-class {
    /* styles */
}

There are various pseudo-classes available, some useful ones include:

  • :first-child: Targets the first child of a parent element
  • :hover: Targets an element when it is hovered over
  • :focus: Targets an element when it receives focus

The following example styles the first paragraph to be bolded and larger in font-size and makes the second paragraph change colour when hovered over:

This text is bolder and larger.

Hover over me!

The example above uses the selector .pseudo-class-example :first-child, which will target the first child element of any element matching the first selector. To make it only elements of a specific type, say a paragraph, we put the element before the pseudo-class selector like so: .pseudo-class-example p:first-child

Psuedo-element selectors

A psuedo-element selector is used to style a specific part of a selected element, this could be the first line of a paragraph of text or every 2nd line for example. These selectors act as if a whole new element was added into the HTML markup. Some useful psuedo-element selectors include:

  • ::first-letter: Targets the first letter of an element only, as if you had put a span around it.
  • ::first-line: Targets the first line of text of an element, automatically adjusting as needed when the line length changes.
  • ::selection: Targets the selected text.
  • ::before: Targets before the start of the element, as if you had inserted an element before it.
  • ::after: The inverse of ::before

The following example demonstrates making the first letter of some text larger, the first line bolder and selected text to have a light green background:

This text is bolder and larger. Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus, quod nisi nobis iusto dolores dolorum mollitia quia veniam sunt qui? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim accusantium repellat obcaecati sint distinctio, dolore necessitatibus praesentium harum minus maiores!

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Harum, alias?

The ::before and ::after pseudo-element selectors

As prior mentioned, these two selectors allow for the insertion of content before and after some element. The following example demonstrates inserting an arrow before some text and styling it:

  Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus, quod nisi nobis iusto dolores dolorum mollitia quia veniam sunt qui? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim accusantium repellat obcaecati sint distinctio, dolore necessitatibus praesentium harum minus maiores!

The example inserts an arrow before the paragraph text, to insert content into the psuedo-element you can easily use text. To insert a symbol, you must insert the escaped unicode. That is, you must place a / before the value. U+02192 would become \02192 for example.

Combinators

A combinator is a special kind of selector which combines multiple selectors together.

Descendant selector

A descendant combinator is used by combining two selectors that are separated by a space, elements that match the second selector are only selected if one of their ancestors matches the first selector.

The following example demonstrates styling paragraph elements which may be nested arbitrarily inside of some parent element:

This text will be affected.

This will also be affected.

Child selector

A child combinator is placed between two CSS selectors, it is represented by the > symbol. It selects only elements matching the second selector which are a direct descendant (child) of the first selector.

The following example demonstrates selecting only the paragraph elements which are a direct child of the parent element:

This text will be affected.

This will not be affected.

Adjacent selector

A adjacent sibling combinator, like a child combinator, is placed between two CSS selectors and is represented by the + symbol. This selector selects elements matching the second selector which are immediately preceeded by the matching element of the first selector.

The following example targets only the paragraph element immediately following the heading level 2 element:

This text will be affected.

This will not be affected.

General sibling selector

The general sibling combinator is similar to the adjacent sibling combinator, the difference is that it will select any element matching the second selector that comes after the matching element for the first selector rather than just the matching element that immediately follows the first selector.

The following example targets all paragraphs coming after the level 2 heading that are at the same level in the hierarchy:

This text will be affected.

This text will also be affected.

This will not be affected as it is not at the same level in the hiearchy, it is nested inside a div.

But this will be...