Last updated October 17th, 2018 at 10:06 am
CSS descendant selectors (also known as contextual selectors) allow you to write lean, clean, semantic html and CSS markup with a minimum number of class and ID names, making your code easier to understand and maintain, and maybe even giving you a sense of harmonious calm. In this article, I explain this claim with an example.
Back in the Day…
Assisting a colleague recently in tweaking CSS, I was reminded that before I understood the power of descendant selectors, my HTML and CSS markup contained lots of superfluous stuff.
For example, if I wanted an H2 element in a sidebar to look different than an H2 element in the main body of a page, I might have added this markup to the sidebar:
<div class="sidebar"> <h2 class="sidebar">Some Heading</h2> <p>Lorem ipsum dolor sit amet...</p> </div>
Or worse, I’d write this, abandoning the structural H2 tag entirely:
<div class="sidebar"> <div class="sidebar-heading-2">Some Heading</div> <p>Lorem ipsum dolor sit amet...</p> </div>
Descendant selectors make that kind of markup unnecessary.
What are CSS Descendant Selectors?
Within the structure of an HTML document, a descendant element is any element that is within (or inside) any other element (its ancestor). For example, the body element is always a decsendant of the html element in an html document.
(It so happens that body is a child element in this example and html is the parent element. It’s worth noting that all child elements are decendant elements and all parent elements are ancestor elements but not vice versa. After all, a descendant element can be a grandchild, great-grandchild, etc.; and an ancestor element can be a grandparent, great-grandparent, etc.)
In a CSS document, a descendant selector is the right-most element in a space-separated list of two or more elements. For example, body is the decendant selector in this CSS markup:
html body { /* some rules here */ }
A descendant selector defines the context in which the rules are to be applied. Therefore, the above rule states that any body element found within/inside an html element should have the pertinent style rules applied.
If you’re thinking that this example is trivial because every body element is always a descendant of the html element, you’re almost right. In fact, I can think of almost no reason to ever include such a declaration in a CSS file. (Why "almost"? Because you might need to give more specificity to a selector in order to override some other CSS rule — for example, one that comes from a thrid-party widget. But more on that another time.)
When Might You Want to Use Descendant Selectors?
Using the example from above (Back in the Day), here’s the simplified HTML, with a basic h2 element, with no class name:
<div class="sidebar"> <h2>Some Heading</h2> <p>Lorem ipsum dolor sit amet...</p> </div>
And here’s the CSS using the descendant selector construct which reads "any h2 inside an element with a class of sidebar":
.sidebar h2 { /* style rules go here */ }
And now for another real-world (sorta) example.
TrimFast – The New Wonder Diet Pill!
Suppose we have a Web page that touts a new wonder diet pill. There are three sections on the page.
The first section gives a brief history of the diet pill with summary statistics
The second section displays instructions for administering the pill.
The third section consists of a matrix showing how much weight each of the randomly selected test subjects lost.
Each section makes use of numbers, and we want numbers to display in distinctly different ways, depending on their context.
Sample Output
Introduction
We first put TrimFast on the market in 2005. In the ensuing 10 years, we have had the pleasure of serving 3,200 customers in 8 countries on 3 continents.
Medication Instructions
Here are your instructions for administering TrimFast. Please follow them closely.
- Take 2 pills 3 times a day.
- Do not exceed 6 pills in any 24 hour period or 2,190 pills in a year.
Sample Results
A random sampling of three of our customers shows the following amazing results.
Customer | State | Weight Lost |
---|---|---|
Jones | WI | 32 |
Smith | AK | 150 |
Brown | CT | 84 |
Display Objectives and Method
I wrapped the sample output in a div with and ID of "demo-css-ds", and each section (Introduction, Medical Instructions, and Sample Results) is wrapped in a section tag with a distinct class name (introduction, instructions, and sampling, respectively). All of the numbers within this "demo-css-ds" div which I want to target with CSS are wrapped in a span with a class of "number".
And here are my basic display objectives; inspecting the CSS will reveal other rules as well, such as letter-spacing:
- A number should use the Courier New font.
- Elements with a class of "warning" should be italicized and red.
- A number in the "introduction" section should be bold white with a black background.
- Any number in the "instructions" section should, by default, be white with a green background.
- Any number in the "instructions" section which is within an element with a class of "warning" should be bold red with a yellow background.
- Any number in the "sampling" section should be right aligned, bold, and with a gray background.
The HTML Code
Here is HTML code inside of that div. Spacing and new lines have been added for readability.
First Section
<section class="introduction"> <h2>Introduction</h2> <p>We first put TrimFast on the market in 2005. In the ensuing <span class="number">10</span> years, we have had the pleasure of serving <span class="number">3,200</span> customers in <span class="number">8</span> countries on <span class="number">3</span> continents.</p> </section>
In the first section, we wanted the statistics to stand out. But note that the year 2005 on line 3, although a number, is not styled like all the other numbers.
Second Section
<section class="instructions"> <h2>Medication Instructions</h2> Here are your instructions for administering TrimFast. Please follow them <span class="warning">closely</span>. <ul> <li> Take <span class="number">2</span> pills <span class="number">3</span> times a day. </li> <li> <span class="warning">Do not exceed <span class="number">6</span> pills in any <span class="number">24</span> hour period or <span class="number">2,190</span> pills in a year.</span> </li> </ul> </section>
Here we introduced the class "warning". The first time it appears (line 4), it styles the word closely. But the second time it appears (lines 13-16), within a span within an li, it is being used as an ancestor for the child spans with a class of "number", so that those numbers can be styled distinctly.
Third Section
<section class="sampling"> <h2>Sample Results</h2> <p>A random sampling of three of our customers shows the following amazing results.</p> <table class="results widefat" cellspacing="0"> <thead> <tr> <th>Customer</th> <th>State</th> <th class="number">Weight Lost</th> </tr> </thead> <tbody> <tr> <td>Jones</td> <td>WI</td> <td class="number">32</td> </tr> <tr> <td>Smith</td> <td>AK</td> <td class="number">150</td> </tr> <tr> <td>Brown</td> <td>CT</td> <td class="number">84</td> </tr> </tbody> </table> </section>
Here we use give some th and td elements the class of "number". We do this so that we can display numbers inside of the table in a specific way — namely, with right-justified text. Elements with classes of "number" within td elements get the gray background.
The CSS
And here is the CSS:
#demo-css-ds .number { font-family: Courier, "Courier Bold", monospace; } #demo-css-ds .warning { font-style: italic; } #demo-css-ds span.warning { color: red; } #demo-css-ds .introduction .number { color: #fff; font-weight: bold; letter-spacing: 2px; padding-right: 2px; padding-left: 2px; background-color: #000; } #demo-css-ds .instructions .number { letter-spacing: 1px; background-color: green; color: #fff; } #demo-css-ds .instructions .warning .number { font-size: 2em; color: red; font-weight: bold; background-color: yellow; } #demo-css-ds .sampling .number { text-align: right; } #demo-css-ds .sampling td.number { font-weight: bold; background-color: #ddd; }
In Closing
I hope you found this explanation and illustration of descendant selectors helpful. If you think it might help others, please share it on your favorite social media platforms. If you have questions or comments, please leave a reply below. If this is the first time you’ve visited my blog and would like to keep apprised of new articles, consider subscribing to our RSS feed and/or signing up for our occasional email newsletter.
Leave a Reply