This guest post was written by Jay Slagle, an independent consultant and certified MadCap Software Advanced Developer who is passionate about using CSS to enhance the power of MadCap Flare. After discovering MadCap Software tools over a decade ago while working as a technical writer in Seattle, he has designed and implemented Flare projects for clients in government, law, education, healthcare, and technology. When he’s not occupied with all things Flare, Jay writes fiction under the pen name JB Strand.

In this article, I will show you how to use CSS complex selectors both to enhance the functionality of your MadCap Flare stylesheet and to make your stylesheet simpler. There are many types of complex selectors, but I will focus on the simplest one, the descendant selector, which allows you to create contexts for changing the styling of elements.

With descendant selectors, you can often eliminate style classes that you use infrequently. This article uses the example of a copyright page in which the text styling differs from the standard body text styling. A typical way to handle this is to create new classes for body text, such as p.Copyright. That's perfectly fine, but then p.Copyright shows up constantly in your Flare style picker, always hanging around even though you use it only on the copyright page. A descendant selector can eliminate the need to define this style class at all.

CSS Descendant Selector

The CSS descendant selector identifies an element "inside" another element.

XHTML Structure for a Descendant Selector

The concept of "inside" has to do with the structure of the XHTML markup:

<div class="Copyright">
    <p>This is a paragraph inside of the div.Copyright element.</p>
</div>

The plain paragraph falls inside of the div’s opening tag (<div...>) and closing tag (</div>). In the stylesheet, the descendant selector tells the browser, “Whenever a standard paragraph is inside of a div.Copyright grouping, style that paragraph in the following way.”

CSS Descendant Selector Syntax

Within your stylesheet, the standard paragraph style looks like this:

p
{ 
    ...styling for standard paragraphs...
}

To create a descendant selector, you indicate the containing element first. On the same line in the stylesheet, specify the "inside" element, separating the two with a space. You can then add styling attributes for the inside element as you would for any other style:

div.Copyright p
{
    ...styling for standard paragraphs inside the copyright div...
}

Descendant Selector Pointers

Even with this simple syntax, there are some important things to grasp:

  • Because of CSS inheritance, a descendant selector should appear below the standard paragraph style in the stylesheet. This allows the descendant selector to inherit the standard style attributes and then modify them.
  • In the descendant selector shown above, the style attributes affect only the paragraph (<p>) elements within the div. They do not apply to the div itself.
  • The containing element does not need to be a div, but that's a common use. On its own, a div is simply an invisible box with no margins or padding. Although you can add styling elements such as borders and background colors to divs, you can leave all of that out and simply use div classes to group elements together and create a context for them. In my example here, the only function for div.Copyright is to modify the elements that fall within it.
  • When you use a div solely to create a descendant selector, you do not need to define the div separately within the stylesheet. Simply create the descendant selector within the stylesheet and Flare will recognize the containing div as a separate element, allowing you to group elements within it using the Group button on the GUI.

Complex Selectors in the Flare Stylesheet Editor

In the Complex Selectors section of its Advanced view, the Flare Stylesheet Editor shows complex selectors. That means you can edit descendant selector styles using the GUI editor or directly within the stylesheet text.

StyleEditorDescendant

If you make changes using the GUI style editor, keep in mind that you are editing values for the descendant element, not the selector element itself. If needed, you can edit values for the selector element in the main category for the element:

StyleEditorSelector

Example: Standard Paragraph and Div Styles

Suppose that the following are two standard elements I use throughout my Flare project. The first is the standard paragraph (<p>). The second is a general-purpose div (div.Center) that creates boxed text centered in the layout. In a typical topic, these elements look like this:

StandardStyles

Standard Styles CSS Values

In the stylesheet, the standard paragraph uses a serif typeface and some basic spacing attributes:

p
{
    font-family: var(--FontSerif);
    font-size: 13pt;
    margin-top: 8pt;
    margin-bottom: 8pt;
    text-align: left;  /* Text is left-aligned. */
}

For the bordered div, the margin-left and margin-right values center the div, which is defined to be eighty percent the width of the text layout that contains it:

div.Center
{
    width: 80%;
    margin-top: 12px;
    margin-left: auto;
    margin-right: auto;
    padding: 10px;
    border: 1px solid #000000;
    border-radius: 5px;
}

To center standard paragraphs that appear within the div, I create my first descendant selector. This styling applies to standard paragraphs that appear within the div, overriding the left text alignment that is used with the standard paragraph:

div.Center p
{
    text-align: center;  /* Text inside the div is center-aligned. */
}

Example: Copyright Page Styles

Copyright pages commonly use styling that reflects organizational branding. A descendant selector allows you to give your standard paragraph styles that alternate styling without the need to make new paragraph classes. Suppose that when these standard elements appear in the copyright topic, they need to look like this:

SelectorDiv

Grouping Elements in a Div

Within the copyright page, I place the two elements inside another div called div.Copyright by selecting the elements and then specifying the div using the Group button on the Home ribbon:

DivCreation

There's no problem with encapsulating one div inside another. The Flare GUI reflects this organization through the structure blocks at the left of the topic pane:

 SelectorDivInFlare

Copyright Page CSS Values

The important point is how the stylesheet modifies the elements within div.Copyright. Below the standard elements within the stylesheet, I use a descendant selector to change the font, apply an uppercase text transform, tweak the spacing, and center-align the text for standard paragraphs that fall inside of div.Copyright.

div.Copyright p
{
    font-family: var(--FontSansSerif);
    font-size: 12pt;
    margin-top: 10pt;
    margin-bottom: 10pt;
    text-transform: uppercase;
    text-align: center;
}

Next, I use another descendant selector to change the color and border of div.Center when it appears within div.Copyright:

div.Copyright div.Center
{
    background-color: #53538e;
    border-color: #53538e;
    border-radius: 0;
}

The last trick involves two descendant selectors that further modify the standard paragraph whenever it appears within a div.Center element that is inside div.Copyright:

div.Copyright div.Center p
{
    color: #ffffff;
    letter-spacing: 3px;
    font-weight: bold;
}

Stylistic Nesting Dolls

The two div elements I've defined above show the two main uses for these elements. The div.Copyright element is a transparent box that functions solely to provide context for modifying the elements it contains. The div.Center element has styling attributes, but those values change depending on whether the div is on its own in the topic or contained within div.Copyright.

As you can see, it's possible to create nesting dolls using descendant selectors, modifying elements that appear within other elements inside yet more elements. Note that I have used only the default paragraph element (<p>), but I've given it three separate looks based on the context in which it appears:

  1. A style for default paragraphs.
  2. A style for default paragraphs inside div.Center.
  3. A style for default paragraphs inside div.Center inside div.Copyright.

Conclusion

More than any other CSS features, complex selectors unlock the incredible power of CSS in Flare. With practice and a firm grasp of the rules of CSS inheritance, you can use complex selectors to make your Flare stylesheet more sophisticated yet also simpler. Because this is intermediate-level CSS, take it slow until you have a firm grasp on the mechanics. Once you do, you'll see that using complex selectors to solve problems in Flare is like stepping up from arithmetic to calculus, though not nearly as difficult to learn!