How to Apply CSS Stylesheet to Macro in Umbraco Grid

By SG Digital on 11/10/2018

One of the great things about Umbraco is the Grid Control.  When combined with Umbraco Macros, developers can give their content editors full control over layout using macros as website building blocks (i.e. Banner macro, Article List macro etc).

One of the big problems with this approach is that out of the box, macros dont apply css style in the back office cms unless its included inline within the macro.  The effect is what you see in the following image.

umbraco macro not applying css style

A really quick fix to the problem of css style not being applied in the Umbraco back office is to add the following lines of code to your macro:-

if (Request.Url.AbsolutePath.Contains("GetMacroResultAsHtmlForEditor"))
{
    <link href="~/css/umbraco-macro.min.css" rel="stylesheet" />

    html.Insert(0, "<div class='umbraco-macro'>");
    html.Append("</div>");
}

@Html.Raw(html.ToString())

All this code does is recognise the macro is being rendered in the Umbraco back office, wraps your HTML in a div with a class called 'umbraco-macro' and links to a version of your css style sheet thats is scoped to just this class.  Ok, its not the most elegant solution, and if you have multiple macros on one page (in the back office cms) you are linking to the same stylesheet multiple times, but it works and its simple! This code will not execute in your live website so nothing to worry about there either.  For a full example of how this solution works see the example below.

css style sheet applied to macro in umbraco cms

The result of applying these simple lines of code is that your css stylesheet is applied to the Umbraco macro in the cms. Happy Content Editors!

Scoping Your CSS to the Umbraco Macro in the Back Office CMS

This approach to scoping your css to the Umbraco macro works really well with SASS (SCSS).  The following example shows your main site style sheet importing components, functions, mixins etc:-

* Core ---------- */
@import 'core/colors.scss';
@import 'core/breakpoints.scss';
@import 'core/padding.scss';
@import 'core/grid.scss';
@import 'core/mixins.scss';
@import 'core/functions.scss';
@import 'core/fonts.scss';
@import 'core/icons.scss';
@import 'core/images.scss';
@import 'core/titles.scss';
@import 'core/reset.scss';
@import 'core/themes.scss';

 

/* Components ---------- */
@import 'components/breadcrumb.scss';
@import 'components/banner-image.scss';
@import 'components/buttons.scss';
@import 'components/footer.scss';
@import 'components/header.scss';
@import 'components/pos.scss';
@import 'components/nav.scss';
@import 'components/section.scss';
@import 'components/text-list.scss';
@import 'components/umbraco-grid.scss';

Then we create a second stylesheet that utilises your main site style but scopes it within an umbraco-macro class:-

.umbraco-macro
{
    @import 'site.scss';
}

Finally, within our Umbraco macro we include the logic to wrap the macro's output in a div referencing the umbraco-macro class, which is only included if the macro is being rendered in the back-office.  Job done!

@using System.Text

@inherits Umbraco.Web.Macros.PartialViewMacroPage

 

@{

    var html = new StringBuilder();

    var imageId = Model.MacroParameters["ImageFile"].ToString();

 

    if (!string.IsNullOrWhiteSpace(imageId))

    {

        var mediaItem = Umbraco.TypedMedia(int.Parse(imageId));

        string imgAlt = Model.MacroParameters["ImageAlt"] != null ? Model.MacroParameters["ImageAlt"].ToString() : string.Empty;

        string imgClass = Model.MacroParameters["ImageClass"] != null ? Model.MacroParameters["ImageClass"].ToString() : string.Empty;

        string title = Model.MacroParameters["Title"].ToString();

        string titlePosition = Model.MacroParameters["TitlePosition"].ToString();

        string titleType = Model.MacroParameters["TitleType"].ToString();

        string theme = Model.MacroParameters["Theme"].ToString();

 

        if (mediaItem != null)

        {

            html.AppendFormat("<div class='banner-image {0}'>", theme);

            html.Append("<picture>");

 

            html.AppendFormat("<source media='(min-width: 1025px)' srcset = '{0}' >", Url.GetCropUrl(mediaItem, "Banner_DesktopLarge"));

            html.AppendFormat("<source media='(min-width: 769px)' srcset = '{0}' >", Url.GetCropUrl(mediaItem, "Banner_Desktop"));

            html.AppendFormat("<source media='(min-width: 321px)' srcset = '{0}' >", Url.GetCropUrl(mediaItem, "Banner_Tablet"));

            html.AppendFormat("<img src='{0}' alt='{1}' class='{2}' style='width:100%;height:auto;display:block;'>", Url.GetCropUrl(mediaItem, "Banner_Mobile"), imgAlt, imgClass);

 

            html.Append("</picture>");

 

            if (!string.IsNullOrWhiteSpace(title))

            {

                if (string.IsNullOrWhiteSpace(titleType))

                {

                    titleType = "<span class='title-type'>||</span>";

                }

 

                if (string.IsNullOrWhiteSpace(titlePosition))

                {

                    titlePosition = "pos--middle-middle";

                }

 

                html.AppendFormat("<div class='pos {0}'>{1}</div>", titlePosition, WebUtility.HtmlDecode(titleType).Replace("||", title));

            }

 

            html.Append("</div>");

        }

    }

 

 

    if (Request.Url.AbsolutePath.Contains("GetMacroResultAsHtmlForEditor"))

    {

        <link href="~/css/umbraco-macro.min.css" rel="stylesheet" />

 

        html.Insert(0, "<div class='umbraco-macro'>");

        html.Append("</div>");

    }

 

    @Html.Raw(html.ToString())

}

Share this article...

Join the Discussion...