How To Make Your Blocks Render Correctly Within Episerver 10 Content Areas

A content area is an Episerverproperty that allows content editors to publish dynamic components like blocks and pages onto your Episerver webpages.  The first time every designer new to Episerver uses a content area they usually get a little shock.  By placing more power in the content editor's hands the end markup Episerver produces might not necessarily match the HTML you expect.  For starters, content areas will display two extra div tags around everything. So let's say we had this text within our block:

Hello World

When the block is added to a content area and eventually rendered out by EPiserver, the markup would look like this:

<div>

<div>

Hello World

</div>

</div>

If you want to know why, then it might be a good idea to open up the Episerver editor and have a look at the content area:

When you look in the editor you can see Episerver's inline editing feature.  This will highlight the content areas and add in context menus so people can set display options and various other things.  This magic is all done by those two extra div tags that the Episerver content area injects.  On most projects, it usually makes life a little more interesting compared to a standard static HTML website build, as it makes the end HTML a little harder to predict.

How Do I Make My Episerver Content Area Display Correctly?

There are a few approaches that we can take to cater for this issue and I'm going to spell them out for you..

1. You can write your HTML to take into account the extra divs.  This can work in some situations, but if you're trying to create an accordion block for example, with an ordered list, the extra divs can cause your HTML to fail a validation check.  So EPiserver provided a way to override the extra divs.  

2. To render a content area as I mentioned we use content areas.  In our Razor views, the Episerver PropertyFor HTML helper is used to get the HTML out of Episerver.  With the PropertyFor helper, you tell Episerver which content area you want to display and it does its thing., like so:

     @Html.PropertyFor(x => x.CurrentPage.LimitingDisplayOptionAre)

Another really useful feature of the PropertyFor HTML helper is the additional overload that takes a number of optional parameters.  These extra parameters will allow you to specify the tags and CSS classes that the content area will wrap around your blocks.  These classes include:

  • CustomTag - Specifies the type of tag that will be used to render the first div.
  • CssClass - Specifies the CSS class to be used on the first div
  • ChildrenCustomTagName -  Specifies the type of tag that will be used on the child divs.
  • ChildrenCssClass -  Specifies the CSS class to be used on the child divs
  • EditContainerClass - Specifies an edit mode only class to be rendered

 To give you an example, you could use PropertyFor in your Razor view like this:

@Html.PropertyFor(x => Model.CurrentPage.MainArea, new
{
    CustomTag = "ul",
    CssClass = "list",
    ChildrenCustomTagName = "li",
    ChildrenCssClass = "list_item"
})

Which would result in this mark-up:

<ul class="list">

    <li class="list_item">

HELLO WORLD

    </li>

</ul>

Setting the content area markup like this can be done on a per content area basis, so you can have content areas on different pages and different blocks producing different markup, which is a pretty standard approach.  On most projects that I've worked on, this feature usually provides the easiest and quickest way to configure Episerver in a way that meets the designer's needs. This is usually the first option I recommend that you start looking into.

3. In some cases, I've worked with designers who just want to get rid of the extra div tags completely. In this approach, a developer will have to create a custom content area render that completely strips out the tags. To get the inline EPiserver editing to work, you still need the extra div tags in the editor though... so this approach can cause issues.  In this situation, you have one set of HTML rendered on the page (no div) and a slightly different set of HTML rendered in the Episerver editors (with divs).  In this instance, you normally need to create a custom Episerver editor CSS file to fix these differences.  To learn how to do that I suggest you read, How To Add Your Own Custom CSS In The Episerver Editor.  

Being the issues of running a website with two different sets of HTML in mind, the code you will need to strip out the div tags is provided below:

    [ServiceConfiguration(typeof(NoDivContentAreaRenderer), Lifecycle = ServiceInstanceScope.Unique)]
    public class NoDivContentAreaRenderer : ContentAreaRenderer
    {
        public Injected AttributeAssembler;

        protected override void RenderContentAreaItem(HtmlHelper htmlHelper, ContentAreaItem contentAreaItem, string templateTag, string htmlTag, string cssClass)
        {
            var dictionary = new Dictionary<string, object>
            {
                ["childrencustomtagname"] = htmlTag,
                ["childrencssclass"] = cssClass,
                ["tag"] = templateTag
            };

            dictionary = contentAreaItem.RenderSettings.Concat(
                (
                from r in dictionary
                where !contentAreaItem.RenderSettings.ContainsKey(r.Key)
                select r
                )
            ).ToDictionary(r => r.Key, r => r.Value);

            htmlHelper.ViewBag.RenderSettings = dictionary;
            var content = contentAreaItem.GetContent();

            if (content == null)
                return;

            using (new ContentAreaContext(htmlHelper.ViewContext.RequestContext, content.ContentLink))
            {
                var templateModel = ResolveTemplate(htmlHelper, content, templateTag);
                if ((templateModel == null) && !IsInEditMode(htmlHelper))
                    return;

                if (IsInEditMode(htmlHelper))
                {
                    var tagBuilder = new TagBuilder(htmlTag);
                    AddNonEmptyCssClass(tagBuilder, cssClass);
                    tagBuilder.MergeAttributes(AttributeAssembler.Service.GetAttributes(contentAreaItem, IsInEditMode(htmlHelper), templateModel != null));
                    BeforeRenderContentAreaItemStartTag(tagBuilder, contentAreaItem);
                    htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
                    htmlHelper.RenderContentData(content, true);
                    htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.EndTag));
                }
                else
                {
                    htmlHelper.RenderContentData(content, true);
                }
            }
        }
        
        protected override bool ShouldRenderWrappingElement(HtmlHelper htmlHelper)
        {
            return false;
        }
    }
    

The HTML Helper will look like this:

     public static class ContentAreaHtmlHelpers
    {
        internal static Injected NoDivContentAreaRenderer;

        public static void RenderNoDivContentAreaRenderer(this HtmlHelper htmlHelper, ContentArea contentArea)
        {
            NoDivContentAreaRenderer.Service.Render(htmlHelper, contentArea);
        }
    }
   

The HTML will then look like:

       @{
          Html.RenderNoDivContentAreaRenderer(Model.CurrentPage.MainArea);
       }
   
I've written the explaination of how this code works in the Episerver 7 version of this tutorial, here. The code is basically getting the class and tag attributes that you pass in via the helper and then override the view bags rendering settings that Episever uses by default. In this way we can change the tags and classes easily.

Episerver Content Area Sample Demo Code

All the code in this tutorial and the different techniques (plus a few more) can be found on my Github page, here.

Content Area Takeaway

Episerver is a very powerful and flexible system.  If you are new to Episerver then the main takeaway I'm hoping you get is that the more control you give to content editors the more unknown your end HTML will be.  As Episerver is so flexible there are a number of different ways of working.  There is definitly no one-size fit all approach and on a usual project, its very common to take a mix and match approach, using one technique for one situation (like injecting the tags and classes via the PropertyFor, and then in another using the no div render contant area to achieve a different result somewhere else. 

In general, if you can write your HTML to take into account the extra div tags then life would be very simple... however, we also may all be out of jobs so, swings and roundabouts!

submit to reddit

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

Back to top