Screenshot showing persistent highlighting in MadCap Flare TopNav menu item.

Adding Persistent Highlighting to MadCap Flare TopNav

Recently, a client asked if we could keep the highlighted state of a Flare-generated TopNav menu item when a user clicks into any topic in that menu item’s tree. Previously, we had added a hover styling for TopNav items in the skin file, but the hover styling didn’t persist when a user clicked into a topic. This article describes in detail how to add both the hover and persistent styling to the TopNav menu items. Along the way, I hope you’ll pick up some new CSS skills and insights.

Adding highlighting on hover in the Flare skin file

By default, the skins included in the TopNav templates that Flare provides don’t include any hover styling for TopNav menu items (as of this writing). However, there is an option provided in the TopNav skin file to add such styling. Open your skin file, and go to Styles > Menu Item (hover) to create background and font hover styles for TopNav menu items.

For the project I was working in, here is the menu in the non-hover state:

Screenshot of the TopNav menu with no hover higlighting

And here is what the menu looks like when hovering over an item:

Screenshot showing MadCap Flare TopNav menu with an item highlighted on hover

At this point, when a user mouses down into the menu and clicks an item, the menu item hover styling (gray background) doesn’t persist, and the menu reverts to looking just like the first example. This is the problem that I wanted to solve.

Maintaining the TopNav menu styling

While the TopNav skin file allows customization of the hover styling, there is no such option to maintain that highlighting when the user clicks into a page. In order to add this effect, you’ll need to create custom CSS and add it to your project’s stylesheet. The specific selector types that we need to rely on are attribute selectors, descendant combinators,  and child combinators.

If you want to learn more about advanced CSS selectors, see my MadCap webinar Selecting the Right Selector.

In the  html element of Flare-generated pages, there is a  data-mc-toc-path  attribute. This attribute is populated with the TOC path for whatever topic is being viewed, and it’s this attribute that provies the hook we need to start building the CSS selector. Here is the HTML code for the “FAQs” topic from the example screenshot above:

<html xmlns:madcap="http://www.madcapsoftware.com/Schemas/MadCap.xsd" lang="en-us" xml:lang="en-us" class="js no-touch svg inlinesvg svgclippaths no-ie8compat _Skins_kb_TopNav_cc" data-mc-search-type="Stem" data-mc-help-system-file-name="index.xml" data-mc-path-to-help-system="../../" data-mc-has-content-body="True" data-mc-target-type="WebHelp2" data-mc-runtime-file-type="Topic;Default" data-mc-preload-images="false" data-mc-in-preview-mode="false" data-mc-medium="non-print" data-mc-toc-path="FAQs" style="">

There is a lot of stuff in there that we don’t need to concern ourselves with. The important attribute is the  data-mc-toc-path attribute, which in this sample is the second to last attribute. This attribute shows the TOC path of the topic being viewed. As a result, every topic that is under the FAQs heading in the TOC will have a  data-mc-toc-path="FAQs" value. (If the topic you’re looking at is deeper in the navigation, then the value will show the additional navigation items.)

With this, we can start to build the first part of our CSS selector:

html[data-mc-toc-path^="FAQs"]

Let’s break this selector down:

  • The  html instructs the browser to look only in the  <html> element.
  • The brackets [ ] indicate that this an attribute selector, meaning that the browser is going to look for a specific attribute in the  <html> element.
  • data-mc-toc-path is the specific attribute the browser will search for.
  • The ^ character instructs the browser to select all instances of  data-mc-toc-path that have a value that starts with the value between the quotes.
  • FAQs is the exact attribute value the browser will select.

Next, we’ll need to add a descendant combinator to specify the specific TopNav item to style. The TopNav menu is in the  <ul class="navigation"> element of the HTML. Each list item in the <ul class="navigation">  is assigned  a data-mc-id value that will allow us to target specific TopNav menu items. The first item in the TopNav menu receives an id of “0,” and it just increments by one for each subsequent TopNav menu item.

So the complete the CSS selector for our FAQs example is:

html[data-mc-toc-path^="FAQs"] ul.navigation > li[data-mc-id="1"]

For the sake of completeness, let’s break down this descendant combinator as well:

  •  ul.navigation  instructs the browser to look only in unordered lists that have a class of “navigation”.
  • The  >  child combinator instructs the browser to look only at the direct children of  ul.navigation . This combinator keeps the browser from looking any deeper in the list.
  •  li[data-mc-id="1"]  is an attribute selector with a similar construct to the one we’ve already used. It instructs the browser to select only list items that have a  data-mc-id  value of “1”.

This selector will now work for any page in the HTML output that has “FAQs” in the second position of the TopNav. With the selector in place, you can now add whatever styles you want to apply.

Here is the code that I used for the entire TopNav example shown in the images above:

html[data-mc-toc-path^="Home"] ul.navigation > li[data-mc-id="0"],
html[data-mc-toc-path^="FAQs"] ul.navigation > li[data-mc-id="1"],
html[data-mc-toc-path^="User Guide"] ul.navigation > li[data-mc-id="2"],
html[data-mc-toc-path^="APIs"] ul.navigation > li[data-mc-id="3"],
html[data-mc-toc-path^="Help References"] ul.navigation > li[data-mc-id="4"]
{
  background-color: #f0f0f0;
  border-radius: 5px;
}

What about translation?

If you translate your project, I recommend converting your TopNav items to variables. When the TopNav TOC entry is a variable, the variable name gets used as the data-mc-toc-path  value, and that variable doesn’t change when the project is translated (only the variable resolutions get translated). So if you use the variable in your attribute selector, the CSS selectors work in any language.

To turn a TOC entry into a variable, first create new variables for the TOC items. Then, in your TOC, right click the TOC item, and select Properties. In the General tab, click the Select Variable button next to the Label box. Then select the correct variable for that TOC item.

Screenshot showing how to apply a variable to TOC entry in MadCap Flare

In the example for the TopNav shown at the top of this article, this is what the CSS looks like:

html[data-mc-toc-path^="[%=local_variables.TopNav-Home%]"] ul.navigation > li[data-mc-id="0"],
html[data-mc-toc-path^="[%=local_variables.TopNav-FAQs%]"] ul.navigation > li[data-mc-id="1"],
html[data-mc-toc-path^="[%=local_variables.TopNav-UserGuide%]"] ul.navigation > li[data-mc-id="2"],
html[data-mc-toc-path^="[%=local_variables.TopNav-APIs%]"] ul.navigation > li[data-mc-id="3"],
html[data-mc-toc-path^="[%=local_variables.TopNav-Reference%]"] ul.navigation > li[data-mc-id="4"]
{
  background-color: #f0f0f0;
  border-radius: 5px;
}

What are the risks?

There are a couple of risks to account for if you decide to implement this.

If you change the name of a TOC entry, you’ll need to update your selector to match the new name (unless you’re using the variable method described above). Also, if you change the order of the TOC entries, you’ll need to update your selectors with the correct order.

There is always risk when you build custom CSS selectors that rely on MadCap Flare generated output. There is no guarantee that Flare will continue to generate the same HTML syntax in future releases, and if that happens, then your selectors will stop working. In this case, I think the risk is acceptable for three reasons:

  • Historically, MadCap hasn’t changed the generated code much.
  • In the event that they do change the generated code, the impact is very low. The only impact will be that the persistent highlighting stops working.
  • Even in instances when MadCap does change the code that Flare generates, it’s usually just a minor CSS adjustment to fix the problem

Interested in learning more advanced techniques?

If you’re interested in learning more about CSS and other advanced CSS techniques, please visit our Training and Consulting pages.

2 thoughts on “Adding Persistent Highlighting to MadCap Flare TopNav

  1. Thanks for the tip! To reduce the height of the background color I added the following:
    html[data-mc-toc-path^=”Architecture”] ul.navigation > li[data-mc-id=”0″]:before, …(etc)… html[data-mc-toc-path^=”Developers”] ul.navigation > li[data-mc-id=”5″]:before {
    position: absolute;
    z-index: -1;
    top: 25%;
    width: 100%;
    height: 50%;
    content: “”;
    background-color: #BED230;
    border-radius: 5px;
    }
    Now the background is only half the height of the li, but centered vertically.

Comments are closed.