Attribute Selectors – Advanced CSS Selectors – Part 4

Attribute selectors offer more options than selectors for HTML tags, IDs, and classes.

As with all selectors, you can combine them to create powerful and specific selectors.

Contents

  1. Review of Attributes Seen So Far
  2. Attribute
  3. Exact Value
  4. Exact Match a Single Value
  5. Partial Match at Start of Value #1
  6. Partial Match at Start of Value #2
  7. Partial Match at End of Value
  8. Partial Match Anywhere in Value
  9. Case Sensitivity
  10. Closing Thoughts
  11. References

Review of Attributes Seen So Far

Attributes are additional information included inside HTML tags. So far, we have seen 9 of them (each item links to their first use in this tutorial series):

  1. id
  2. class
  3. href
  4. target
  5. download
  6. src
  7. alt
  8. reversed
  9. start

Example use is shown below:

<div id="main">
  <p class="important todo scale">
    Some paragraph text.
  </p>
</div>  

<a href="http://example.com"
   target="_blank"
   download="file.txt">
   This is a link.
</a>

<img src="/img/picture.jpg"
     alt="Description of the image">

<ol reversed
    start="101">
  <li>Item 1</li>
  <li>Item 2</li>
</ol>

Attribute

You can select elements by the attributes they contain by writing the attribute between square braces:

/*
  select all HTML elements containing the
  'reversed' attribute
*/
[reversed] {
  /* specificity = 0:1:0 */
}

/*
  select all HTML elements containing the
  'id' attribute
*/
[id] {
  /* specificity = 0:1:0 */
}

Exact Value

You can select by specifying the exact attribute and its value. The value must be in quotes:

[id="footer"] {
  /* specificity = 0:1:0 */
}

[class="red box"]{
  /* specificity = 0:1:0 */
}

[start="101"] {
  /* specificity = 0:1:0 */
}

Exact Match a Single Value

If you have attributes with multiple values (classes are a good example), you can select based on one of the values by placing a tilde (~) before the equals sign:

[class~="box"] {
  /* specificity = 0:1:0 */
}

The selector above will select the following HTML elements because they all contain box:

<p class="red box">This is a selected paragraph.</p>
<p class="box blue">This one too.</p>
<p class="red green box blue">This too!</p>

The attribute values must be separated by spaces:

<!--
  Validly separated attribute values
-->
<p class="red box a b c"></p>

<!--
  incorrectly separated attribute values
-->
<p class="red,box,a,b,c"></p>
<p class="a, b, c"></p>

You can only match one attribute value:

/*
  THIS NEVER MATCHES ANYTHING

  Even if you have an element like this:

  <p class="a red box blue">

*/
[class~="red box"] {

}

Partial Match at Start of Value #1

You can match the beginning of a value string by using the vertical-bar before the equals sign (|=). The match must be followed by a hyphen:

[class|="cf"] {
  /* specificity = 0:1:0 */
}

The selector above will match the following:

<div class="cf-abc"></div>

<div class="cf-"></div>

<div class="cf-d blue box"></div>

The selector above will not match any of the following:

<!--
  cf is not followed by a hyphen
-->
<div class="cf"></div>

<!--
  cf is not at the start of the value string
-->
<div class="red cf- box"></div>

This is an extremely specific behaviour that was originally introduced for dealing with language codes.1

Partial Match at Start of Value #2

This is the more common way to match the start of an attribute value string.

You can match the beginning of a value string by using the caret before the equals sign (^=):

[class^="cf"] {
  /* specificity = 0:1:0 */
}

The selector above will match the following:

<div class="cfabc"></div>

<div class="cf"></div>

<div class="cf-"></div>

<div class="cf-d blue box"></div>

The selector above will not match any of the following:

<!--
  cf is not at the start of the value string
-->
<div class="red cf box"></div>

It should be obvious that you can make the ^= equivalent to the |= by simply appending a hyphen to your string:


/*
  These two selectors are identical.
*/
[class^="cf-"] {

}

[class|="cf"] {

}

Partial Match at End of Value

You can match the end of a value string by using the dollar symbol before the equals sign ($=):

[class$="nt"] {
  /* specificity = 0:1:0 */
}

The selector above will match the following:

<div class="nt"></div>

<div class="plant"></div>

<div class="cf-d blue box plant"></div>

The selector above will not match any of the following:

<!--
  nt is not at the end of the value string
-->
<div class="red nt box"></div>

<div class="plants"</div>

Partial Match Anywhere in Value

You can match the value anywhere in a string by using the asterisk symbol before the equals sign (*=):

[class*="nt"] {
  /* specificity = 0:1:0 */
}

The selector above will match the following:

<div class="nt"></div>

<div class="planter"></div>

<div class="cf-d blue plant box"></div>

The selector above will not match any of the following:

<!--
  nt is not is not found in any value string
-->
<div class="red flat box"></div>

<div class="explains"</div>

Case Sensitivity

If you want to match values without regard to upper and lower case, you append i to the end of the attribute selector:

[class="red" i] {
  /* specificity = 0:1:0 */
}

The selector above will match any of the following:2

<div class="red"></div>

<div class="RED"></div>

<div class="Red"></div>

<div class="rED"></div>

<div class="rEd"></div>

<div class="ReD"></div>

<div class="REd"></div>

<div class="reD"></div>

It is a good idea to be consistent in your use of case to avoid situations where you might need to use case insensitive matching.

Closing Thoughts

  1. Attribute selectors provide 7 different ways to match attributes and their values.
    1. [attribute] – select only by attribute name
    2. [attribute=“value”] – select by attribute name and exact value
    3. [attribute~=“value”] – select by attribute name and exact match one value in the value string
    4. [attribute|=“val”] – select by attribute name and exact match at the beginning of the value string which must then be followed by a hyphen
    5. [attribute^=“val”] – select by attribute name and exact match match at the beginning of the value string
    6. [attribute$=“lue”] – select by attribute name and exact match at the end of the value string
    7. [attribute*=“value”] – select by attribute name and exact match anywhere in the value string
  2. You can combine attribute selectors with other selectors and combinators:
    /*
      only selects ordered lists that contain the
      attribute reversed and the attribute list
    */
    ol[reversed][start] {
      /* specificity 0:2:1 */
    
    }
    
    /*
      selects elements contained within objects
      having an ID of #main if those elements
      contain an attribute of target
    */
    #main [target="_blank"] {
      /* specificity = 1:1:0 */
    }
  3. You could colour code links to visually show if they refer this site or an external site:
      /*
        as long as the link contains
        complet-concrete-concise.com
        we assume is points to this website
      */
      a[href*="complete-concrete-concise.com"] {
        color: green;
      }
  4. You could colour code links to visually show if a link uses a secure or unsecured connection:
      /*
        secure links begin with https
      */
      a[href^="https:"] {
        color: green;
      }
    
      /*
        unsecured links begin with http
      */
      a[href^="http:"] {
        color: red;
      }
  5. Given the following HTML code:
    <p class="box">Some paragraph.</p>

    There is no functional difference between these pairs of selectors:

    
    [class="box"] {
    
    }
    
    .box {
    
    }
    
    
    p[class="box"] {
    
    }
    
    p.box {
    
    }
  6. Given the following HTML code:
    <p class="box blue">Some paragraph.</p>

    These pairs of selectors behave differently:

    /*
      selects only if the class is exactly "box"
    */
    [class="box"] {
    
    }
    
    /*
      selects if the class contains "box"
    */
    .box {
    
    }
    
    
    p[class="box"] {
    
    }
    
    p.box {
    
    }

    You might be tempted to rewrite the attribute selector as:

    [class*="box"] {
    
    }

    But that selector will match not only box, but also: matchbox, bitbox, and any other class with box in it.

    The correct substitution would be:

    [class~="box"] {
    
    }
  7. Analyzing 4632 CSS rules3 from the home pages of 5 different websites4 revealed the following attribute selector distribution:5
    • 2.5% of the rules use attribute selectors
    • 85.2% of the attribute selectors use an exact match ([attribute=“value”])
    • 11.3% of the attribute selectors match the attribute ([attribute])
    • 3.5% of the attribute selectors do a partial on the start of the value ([attribute^=“val”])
    • No other attribute selector types were used
  8. To see some real world selector examples using attribute selectors, consider the following from the WordPress 2016 Theme:6
    /*
      Style a link (<a>) only if:
      (1) the value of href begins with "mailto:"
      (2) it is somewhere inside a block with a
          class of .social-navigation
    
      :before is a pseudo-element which will be
      covered in a later tutorial. Pseudo-elements
      add 0:1:0 to specificity
    
      specificity = 0:3:1
    */
    .social-navigation a[href^="mailto:"]:before {
        content: "\f410";
    }
    
    /*
    Style a link (<a>) only if:
    (1) the value of href ends with "/feed/:"
    (2) it is somewhere inside a block with a
        class of .social-navigation
    
    :before is a pseudo-element which will be
    covered in a later tutorial. Pseudo-elements
    add 0:1:0 to specificity
    
    specificity = 0:3:1
    */
    .social-navigation a[href$="/feed/"]:before {
        content: "\f413";
    }
    
    /*
      Style <img> tags only if:
      (1) they have a class name containing
          "wp-image-"
      (2) they are somewhere inside a block with
          a class of .wp-caption
    
      specificity = 0:2:1
    */
    .wp-caption img[class*="wp-image-"] {
        display: block;
        margin: 0;
    }

References

  1. CSS Attribute Selectors

  1. This will be covered in a future tutorial. Essentially, language tags allow on to specify the primary language and a subset of that language. For example: en specifies the English language, en-ca specifies Canadian English, en-nz specifies New Zealand English, etc.
  2. This does not work with all browsers. It does not work with Internet Explorer, Microsoft Edge version 18 or lower, Android Browser (Android version 4.4 or earlier). A good site to check if a particular HTML or CSS feature is supported is Can I Use.
  3. Yes, it is a lot of rules.
  4. I pulled the CSS from the main landing pages of the following:
    • BBC,
    • Engadget,
    • The Verge,
    • Wikipedia,
    • WordPress

  5. Take these numbers as a rough guide to their relative use.
  6. There is plenty in the CSS Styling that you haven’t seen – but they will be covered in future tutorials.