CSS

Cascading Style Sheets (CSS) consist of sets of style declarations that specify how elements in an HTML page are to be rendered stylistically by the browser.

Each declaration has the following form:

property:value;

A property must be a valid CSS property keyword and the value must be a valid quantity that is dependent on the specified property.  When a declaration is provided with an invalid property or value, the declaration is simply ignored by the CSS engine.

Declarations are grouped in what are called CSS blocks.  Blocks are defined by curly braces  { }.  A block can have 0 or more declarations.  The following is an example of a CSS block that contains 2 declarations.

{
    font-family:Verdana;
    font-size: 24px;
}

Every CSS block is preceded by one or more selectors.  A selector is code that describes a condition that identifies a set of elements on the web page for which the declarations in the CSS block will be applied.  A CSS rule consists of one or more selectors followed by a CSS block.

For example, to apply the declaration in the above block to all of the p elements in a page we would use the following rule.

p {
    font-family:Verdana;
    font-size: 24px;
 }

Incorporating CSS Rules in a HTML Document

There are 3 ways to incorporate CSS rules in a HTML Document:

  1. Declare an external style sheet in the head element using the link element
  2. Embed a set of style rules in the head element of the HTML document using a style element
  3. Define a set of style rules when declaring a HTML element using the element’s style attribute

Link elements are commonly found as nested elements within the head element.  The link element “specifies relationships between the current HTML document and an external resource.”  It is often used to link a CSS stylesheet with the current HTML document.  When used to link a stylesheet, the link element must include a rel attribute and a href attribute The rel attribute defines the relationship between the linked document and the current HTML document and is set to “stylesheet”.  The href attribute specifies the URL of the linked document.  Link elements cannot have content and so should not have a closing tag as shown below.

<link rel="stylesheet" href="stylesheets/navbar.css">
We can also specify a set of CSS rules using the style element in the head element.  For example, the rule given above can be included in a head element as follows:
<head>
    ...
    <style>
        p { 
            font-family:Verdana; 
            font-size: 24px; 
        }
    </style>
    ...
</head>

We can also specify CSS rules when we define a HTML element using the element’s style attribute.  For example, when we use a p element in the HTML document we can specify which font-family to use and which font-size to use when we declare the element as shown below.

...
<p style="font-family:Verdana; font-size: 24px;">In the beginning ...</p>
...

Selectors

There are 4 different types of selectors and 2 different ways to combine selectors in a single rule.  Below is a nice description copied from mozilla’s website.

  1. Simple selectors: Match one or more elements based on element type, class, or id.
  2. Attribute selectors: Match one or more elements based on their attributes/attribute values.
  3. Pseudo-classes: Match one or more elements that exist in a certain state, such as an element that is being hovered over by the mouse pointer, or a checkbox that is currently disabled or checked, or an element that is the first child of its parent in the DOM tree.
  4. Pseudo-elements: Match one or more parts of content that are in a certain position in relation to an element, for example the first word of each paragraph, or generated content appearing just before an element.
  5. Combinators: These are not exactly selectors themselves, but ways of combining two or more selectors in useful ways for very specific selections. So for example, you could select only paragraphs that are direct descendants of divs, or paragraphs that come directly after headings.
  6. Multiple selectors: Again, these are not separate selectors; the idea is that you can put multiple selectors on the same CSS rule, separated by commas, to apply a single set of declarations to all the elements selected by those selectors.

Lets look at each of of these below.


Simple Selectors

When the name of an element is used as a selector all of the elements of that type in the web page are stylized.  We saw this earlier when we used p as the selector.

p {
    font-family:Verdana;
    font-size: 24px;
 }

We can also stylize a single element in a HTML page.  To do so, we use #identifier as the selector where identifier is the value of the element’s id attribute.  For example if we have declared an element with the id attribute set to “nav_bar” then we can stylize that element using the following syntax.

#nav_bar {
    /* style declarations */
}

Recall that more than one element can belong to the same class.  We can apply a set of style declarations to all of the elements belonging to a particular class by using .class_name as the selector where class_name is the value of the class attribute for a set of HTML elements.

.keypad_button {
    /* style declarations */
}

Attribute Selectors

Attribute Selectors select elements based on whether or not they have a specific attribute or dependent on the value of an attribute.

There are 7 different types of attribute selectors. Each is defined within braces [ ].

Has Attribute
[attr] selects all elements that have an attribute named attr.
Has Exact Value
[attr=val] selects all elements that have an attribute named attr whose value is set to val.
Has Exact Value or Starts With Language Coded Substring
[attr|=val] selects all elements that have an attribute named attr whose value is set to val or begins with val-.
Contains Substring (may not include spaces)
[attr~=val] selects all elements that have an attribute named attr whose value contains val, where val is a string that does not include spaces.
Contains Substring (may include spaces)
[attr*=val] selects all elements that have an attribute named attr whose value contains val, where val is a string that may include spaces.
Begins with Substring
[attr^=val] selects all elements that have an attribute named attr whose value begins with val.
Ends with Substring
[attr$=val] selects all elements that have an attribute named attr whose value ends with val.

Example

Lets examine the example given in the mozilla documentation.

file.html

Ingredients for my recipe: <i lang="fr-FR">Poulet basquaise</i>
<ul>
  <li data-quantity="1kg" data-vegetable>Tomatoes</li>
  <li data-quantity="3" data-vegetable>Onions</li>
  <li data-quantity="3" data-vegetable>Garlic</li>
  <li data-quantity="700g" data-vegetable="not spicy like chili">Red pepper</li>
  <li data-quantity="2kg" data-meat>Chicken</li>
  <li data-quantity="optional 150g" data-meat>Bacon bits</li>
  <li data-quantity="optional 10ml" data-vegetable="liquid">Olive oil</li>
  <li data-quantity="25cl" data-vegetable="liquid">White wine</li>
</ul>

file.css

[data-vegetable] {
    color: green;
}

[data-vegetable="liquid"] {
    background-color: goldenrod;
}

[lang|=fr] { 
    font-weight: bold; 
}

[data-vegetable~="spicy"] {
    color: red;
}

[data-vegetable*="not spicy"] { 
    color: green; 
}
[data-quantity^="optional"] {
    opacity: 0.5;
}

[data-quantity$="kg"] {
    font-weight: bold;
}

The above code produces the following HTML:

Ingredients for my recipe: Poulet basquaise

  • Tomatoes
  • Onions
  • Garlic
  • Red pepper
  • Chicken
  • Bacon bits
  • Olive oil
  • White wine

Pseudo-classes

A CSS pseudo-class filters a set of elements (selected with another selector) selecting only those that are in a particular state.  The filter is defined by appending a colon (:) after a selector, followed by a pseudo-class keyword. Pseudo-classes allow us to select, for example, elements that are

  • :hover – selects elements under the cursor in the selected set
  • :first-child – selects the first element in selected set
  • :last-of-type – selects the last element in the selected set
  • :nth-child(n) – selects the nth element in the selected set

Note that many of the pseudo-classes in the Mozilla list are experimental and are not yet implemented in all browsers.  Check the compatibility tables before using.

Example

Consider the following HTML and CSS:

Homepage: <a href="https://n0code.net">n0code.net</a>
a:hover {
    color:red;
    font-weight:bold;
}

The above code produces the following HTML:

Homepage: n0code.net

Pseudo-elements

Pseudo-elements create “pseudo” elements with the specified styles that are inserted into existing elements.  They are defined by appending a colon (:) after a selector followed by a pseudo-element keyword.  Below are the most commonly used pseudo-elements.

Append as Last Child
::after { … }
Insert as First Child
::before { … }
Apply to First Letter of First Line of Block Element
::first-letter { … }
Apply to First Line of Block Element
::first-line { … }

Example

Consider the following HTML and CSS:

<p>of the United States, in Order to form a more perfect Union, establish Justice, 
insure domestic Tranquility, provide for the common defence, promote the general Welfare, 
and secure the Blessings of Liberty to ourselves and our Posterity, do ordain and 
establish this Constitution for the United States of America.</p>
p::before {
    content:"We the People ";
    font-size:24px;
    font-weight:bold;
}

The above code produces the following HTML:

of the United States, in Order to form a more perfect Union, establish Justice, insure domestic Tranquility, provide for the common defence, promote the general Welfare, and secure the Blessings of Liberty to ourselves and our Posterity, do ordain and establish this Constitution for the United States of America.


Combinators

Combinators allow for the selection of nodes based on the ancestry of the nodes in the DOM.  There are four types of combinators.

Descendents
elm1 elm2 { … } stylizes all elements of type elm2 that are descendants of elements of type elm1.
Direct Children
elm1 > elm2 { … } stylizes all elements of type elm2 whose parent element has type elm1.
Next Siblings
elm1 + elm2 { … } stylizes the all elements of type elm2 that are the next sibling of an element of type elm1.
All Siblings that Follow
elm1 ~ elm2 { … } stylizes all elements of type elm2 that are siblings that follow an element of type elm1.

Note: elm1 and elm2 can be defined by any of the selectors discussed above. As an example, see the last two rules in the example below.  

Example

Consider the following HTML and CSS from the mozilla documentation.

file.html

<main>
    <h1>Heading 1</h1>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
    <section>
        <h1 id="heading2">Heading 2</h1>
        <p>Paragraph 3</p>
        <p class="second">Paragraph 4</p>
    </section>
</main>

file.css

main p {
    width: 150px;
    color: blue;
}

main > p {
    background-color: yellow;
}

h2 + p {
    text-transform: uppercase;
}

h2 ~ p {
    border: 1px dashed black;
}

#heading2:hover ~ [class=second] {
    font-weight:bold;
}

#heading2:hover ~ p::after {
    content:"!";
}

The above code produces the following HTML:

Heading 1

Paragraph 1

Paragraph 2

Heading 2

Paragraph 3

Paragraph 4


Multiple Selectors

Multiple selectors allow us to apply the same rule to multiple sets of elements.

Multiple Selectors
selector1, selector2 { … } stylizes all elements selected by selector1 and selector2.