When you work with Bootstrap within EpiServer, your HTML will still need to work on a row and column format in order for your pages to render correctly whenever a site visitor comes to look at it. In the rules of Bootstrap, pages should be made up of rows, each containing items with column widths that add up to 12.
Episerver, on the other hand, provides a really flexible and configurable backend that allows content editors to arrange page layouts in new and creative ways that weren't possible 5 years ago.
These two requirements, create a bit of friction between Bootstrap and Episerver. Content editors need to have an understanding of Bootstrap grid layouts when they work with Episerver, otherwise, they might break the grid layout that bootstrap expects and your web pages will start to behave in unexpected ways.
There are a number of ways of configuring Episerver to work with Bootstrap nicely and, in today's tutorial, I'm going to cover all the code that you need in order to create a content area, that only accepts a row block. The row block will then be configured with a custom Episerver validation attribute that will prevent content editors adding blocks with widths that are greater than 12 columns.
This approach isn't the only way of configuring EPiserver to work with Bootstrap but I've personally used it on a few projects and this approach does give content editors the flexibility to add blocks onto a page and set the widths how they see fit, all while being forced to work within the Bootstrap grid system correctly, so let's begin:
How Do I Restrict A Content Area To Only Content Editors To Add Certain Blocks
This bit is very simple when you define your pages/block you use the 'AllowedTypes' attribute, like so:
Using this approach, now ensures that your HTML will always have a wrapping row block. The row blocks HTML simply looks like this:
And the Row definition:
The only issue we have now is that the content editors can still add as many blocks they want to inside the row block, breaking the maximum of 12 column per row rule. To get around this we can create a custom validation attribute. To pre-warn you now, you'll need a lot of boilerplate code to enable this.
You need your display options set. I'll cover the validation attribute first as that's the clever bit. I'll add the boilerplate code afterwards, however, as there's so much, I've uploaded a Display option Sample Project into my Github account here (just in case you get stuck)
In the example above, we inherit from ValidationAttribute and implement the IsValid method. In here, we get all the content area items (usually blocks) within content area and iterate through each one.
For each block, we get the display option that has been associated with it, get its width and add that number to a total width count. If that count gets higher than 12, we return false which will prevent the content editor from adding it.
Whenever I enable Display Options, I recommend using a custom DisplayOptionEnum enum. In this way, you can have one thing that defines the display option name, the bootstrap class name and the import bit in our case an integer value indicating the columns width. If you are wondering how you attach the attribute to your pages or blocks, you simply decorate your content area property with it, like so:
Now, if you run Episerver and try and drop too many blocks that exceed the bootstrap column limit you will see this error:
All the above code can be downloaded in a fully working website from my github account here. #ILoveEpiserver
As someone said in a Marvel film once, "with great content editing power comes more headaches for developers". The aim of this tutorial is to help you think in terms of structuring the Episerver backend in a way that makes it easy for content editors to use, but still enforcing the HTML that the designers will need.
This approach isn't the only way of enforcing the Bootstrap markup is outputted correctly. This approach does mean you can 100% ensure the end row and columns HTML structure is rendered in the way you need it to be, enjoy!