Wolf X Machina

Back to blog

Auto Anchors in 2SXC

Posted in DNN on September 12, 2019

My clients love to be able to send their users directly to anchored sections of content on a page. For example, an anchor like this. It's so convenient to be able to send someone to a specific part of a page. And if you have CSS smooth scroll, there's a satisfying scroll.

Unfortunately, anchors in DNN aren't really that easy to set up. You can configure them through the CKEditor but it's not obvious how to do it and it only works for text generally. I regularly get asked to set up these types of anchors for entire sections of content so I wanted to come up with a solution that was easy for everyone.

In DNN, using 2SXC Content module and C# Razor templates, I've come up with a pretty clever and relatively simple solution to both make anchors automatically but also give my content editors the ability to customize their anchors. So read on below!

Anchors aren't always the easiest for content editors for these reasons:

  1. If you're using structured content where content editors have limited editing abilities, they might not be able to add an anchor tag in the fields you provide
  2. Sometimes designs are precise and they need an anchor to go to a specific spot to account for spacing or sticky headers or navigation
  3. It's not always obvious what the name of the anchor is

To that end, to make anchors easy to maintain for myself and my clients, I wanted to take an approach that achieved a few things:

  1. Anchors should be automatically made based on the title or main heading of the section of content
  2. Content editors should be able to modify the anchor to make it any text that they want
  3. Even if the content editor types the anchor in the wrong format, the template should correct it
  4. The anchor should be obvious to the content editor at all times so they don't have to view the generated page source
  5. Ideally the solution should be HTML, CSS, and razor only

Using just a basic "Content" content type and template, I'm going to show you how I made an easily reusable setup to make anchors automatically in all your 2SXC modules.

Step 1: The title field

First things first: For your "Content" type, be sure to add a Title field that is required. We're going to use this field as the anchor text by default so we want the users to fill it out.

2SXC Edit Form

Step 2: The anchor field

I also want my content editors to be able to define anchor their own anchors if they don't want to use the title field. So in my "Content" content type, I also create an "Anchor" string field to let content editors define a custom anchor.

I also like to include some help text to tell the user that an anchor should be lowercase, hyphenated, and not include characters other than text and hyphens. (It's good to guide your users as much as you can even if the template will handle things.)

Anchor field in 2SXC

Step 3: The razor template

In your C# razor template, we want to add a simple if/else statement to create an anchor based on the title of the content if an anchor is not defined already. This is the code:

@if (Content.Anchor != "") {
    <a class="content-anchor" name="@Html.Raw(Content.Anchor.ToLower().Replace(" ", "-").Replace("&", "and").Replace("\n",""))"></a>
} else {
    <a class="content-anchor" name="@Html.Raw(Content.Title.ToLower().Replace(" ", "-").Replace("&", "and").Replace("\n",""))"></a>
}

This piece of the template is relatively simple. If the Content Editor fills out the "Anchor" field, then the anchor is created using the anchor field. Otherwise, it uses the title of the module.

Notice I use @Html.Raw and a series of .Replace()'s to handle spaces, &, and carriage returns. Because an anchor should look like #my-awesome-team, I need to replace those things if the user enters them into the title or anchor field. It's not a perfect solution, but it should take care of most scenarios. Between this code and the instructions in your field's Notes section, the anchors should work.

Note: if you're applying these anchors to an entire section for a list, update the Content.Anchor to ListContent.Anchor and Content.Title to ListContent.Title

Step 4: The anchor label

One big thing my content editors are always asking me is "how do I know what anchor to use?" Now that they can easily edit the Anchor field, they can know by going to the edit modal of the item and looking at the anchor. But an even better way is to create a special label that writes out the section's anchor on the page. Here's what it should look like for content editors:

Anchor label using CSS

So for that, I came up with this CSS:

/* give the anchor a bit of style to offset it from the sticky header (sticky header height is 125px) */

.content-anchor {
    display: block;
    position: relative;
    top: -125px;
    visibility: hidden;
    margin-bottom: auto;
}

/* when DNN is in "Edit Mode", make the content anchor visible */

.dnnEditState .content-anchor {
    position: relative;
    z-index: 99;
    display: block;
    top: 0;
    visibility: visible;
}

/* using the content attribute in CSS, display the value of the anchor in the label */

.dnnEditState .content-anchor[name]::after {
    content: "Anchor: #" attr(name);
    position: absolute;
    bottom: 0;
    left: 0;
    display: inline-block;
    font-size: 13px;
    border: 2px solid #333;
    background: #fff;
    z-index: 1;
    color: #333;
    padding: 5px 10px;
    border-radius: 3px;
    white-space: nowrap;
    margin-bottom: 15px;
}

Here I'm doing two things:

  1. I've styled my anchor to be invisible and even offset it from the sticky header. (Based off of this article: https://stackoverflow.com/questions/10732690/offsetting-an-html-anchor-to-adjust-for-fixed-header)
  2. When the Content Editor is in Edit Mode, use CSS to show them the anchor content in a little label.

Step 5: Re-use it everywhere!

Once you've applied this method to your basic content type, don' stop there. Add it to every other content type and template that you can. Once the CSS is in place, you can re-use this code easily and it will apply across the board.

In Conclusion

I came up with this because my clients were always asking for me to add anchors for them to content sections and I wanted to come up with a more permanent solution where they could manage it themselves. In terms of work, I only really have to add one extra "Anchor" field to each content type, and then more or less copy and paste that C# razor code into every new template. It's a fairly low tech solution to a common problem. I love situations like these where I learn a need (or gripe) of a client and find a way to solve that for them. I hope it works well for you too. If you have any questions, shoot me an email.

Hope you enjoyed this article. If you're looking for ways to make your DNN website better designed and easier to maintain, check out my page about Expert DNN Development

Aaron Lopez

Aaron Lopez

Founder & Lead Developer at Wolf X Machina

Wolf X Machina

Next Level Interface Development for the DNN CMS

DNN themes, module design, and more from Wolf X Machina.

Learn More