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.
N.B. The approach outlined for adding css to the back office and macros does not work for Umbraco 8.
Read how to add custom css to Umbraco 8 back office and macros.
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.
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()) }
Umbraco 8 - Adding a Stylesheet for Macros in the Back Office
Unfortunately, the approach suggested above to add css to a macro will not work in Umbraco 8. It appears that all inline style or associated style sheets are ignored in the Macro HTML. This has led me to a more simple approach, which should also work in Umbraco 7.
To add extra CSS and style to the back office in Umbraco 8 :-
Create a directory in the App_Plugins folder and add a package.manifest file as follows...
The content of the Manifest file should be:-
{
"propertyEditors": [],
"javascript": [],
"css": [
"~/css/umbraco-macro.min.css"
]
}
The path to the css can be changed to your css file.
Finally, ensure your macro is wrapped in a scoped div as outlined above:-
if (Request.Url.AbsolutePath.Contains("GetMacroResultAsHtmlForEditor"))
{
html.Insert(0, "<div class='umbraco-macro'>");
html.Append("</div>");
}
Leave Your Comments...