Implementing CSS and JS in Sitecore

Cascading Style Sheet (CSS) and JavaScript (JS) are included as a link to a file in websites. Most of the live sitecore solutions also follow the same pattern. Sitecore provides the flexibility to break free from the standard procedures and implement new solutions.

There are different solutions to a single problem and Sitecore being flexible always helps to improve an implemented solution. CSS and JS implementation are no exceptions to it and there are different ways to incorporate them in Sitecore. I have come across few different CSS and JS implementations on Sitecore and would be discussing them in this blog post.

I thought definitely there would be various implementations done by others in Sitecore Community and posted as blogs on the net. My search proved that my thinking was correct and hence I would not discuss all those implementation, instead share those implementations as links so that they can be found under one roof so look out for Nice Read section of this post for all those links.

If you are Sitecore expert you might not find this post helpful as this is something you might have already done, but would suggest to comment on this post so that more different way of implementing CSS and JS can be highlighted.

A) CSS and JS Stored as Items in Sitecore

Templates & Items

1) CSS Template & Item

CSSTemplate

CSSItem

2) JS Template & Item

JSTemplate

JSItem

3) Site Settings Template & Item

SiteSettingsTemplate

SiteSettingItem

Another way to implement StyleSheets and JavaScripts Section is to build them as a separate templates and then inherit SiteSetting template from them. This gives you flexibility in case if you want to place the Javascripts and Stylesheets on other individual templates.

Layouts

1) JS layout code

protected void Page_Load(object sender, EventArgs e){
            this.ReturnJS();

        }
        private void ReturnJS()
        {
            Sitecore.Data.Items.Item currentItem = Sitecore.Context.Item;

    	if (currentItem != null)
                {
                    string script = currentItem.Fields["JS Content"].Value;
                    Response.Clear();
                    Response.ContentType = "text/javascript";
                    Response.Write(script);
                    Response.Flush();
                    //Response.Close();
                    Response.End();
                }
        }

2) CSS layout code

protected void Page_Load(object sender, EventArgs e)
        {
                this.ReturnCSS();
        }

 private void ReturnCSS()
        {
            Sitecore.Data.Items.Item currentItem = Sitecore.Context.Item;

                if (currentItem != null)
                {
                    string css = currentItem.Fields["CSS Content"].Value;
                    Response.Clear();
                    Response.ContentType = "text/css";
                    Response.Write(css);                    
                   Response.End();
                }           
        }

Creating a static Helper method for Linking StyleSheets

Here is a brief dry run of the static method, it gets the Site Settings item and looks for a multi select field “StyleSheets”. Gets the IDs of the selected StyleSheets and based on their names differentiate them for different media (print, screen and all). Browser specific StyleSheets are also accounted and rendered.

This method builds the link tag and finally adds it to the header of the page which should be marked with runat = ”server” attribute.

public static void SetupStylesheets(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            try
            {
                if (siteSettingItem != null)
                {
                    String[] stylesheetIDs = null;
                    if (!string.IsNullOrEmpty(siteSettingItem["Stylesheets"]))
                    {
                        stylesheetIDs = siteSettingItem["StyleSheets"].Split(new char[] { '|' });
                        //set the options for the item URL
                        urlOptions.AlwaysIncludeServerUrl = true;
                        urlOptions.AddAspxExtension = true;

                        foreach (string ids in stylesheetIDs)
                        {
                            if (!string.IsNullOrEmpty(ids))
                            {
                                Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(ids);
                                if (item.Template.Name.ToLower() == "css")
                                {
                                    HtmlLink link = new HtmlLink();
                                    LiteralControl ltrl = new LiteralControl();

                                    link.Attributes.Add("type", "text/css");
                                    link.Attributes.Add("rel", "stylesheet");
                                    if (item.Name.ToLower() == "print")
                                    {
                                        link.Attributes.Add("media", "print");
                                    }
                                    else
                                    {
                                        if (item.Name.ToLower() == "mobile")
                                        {
                                            link.Attributes.Add("media", "all");
                                        }
                                        else
                                        {
                                            link.Attributes.Add("media", "screen");
                                        }
                                    }
                                    link.Attributes.Add("href", Sitecore.Links.LinkManager.GetItemUrl(item, urlOptions).Replace(".aspx", ".css"));

                                    if (item.Name.ToLower() == "ie6")
                                    {
                                        ltrl.Text = "";
                                        if (page.Header.Controls.Count > 0)
                                        {
                                            page.Header.Controls.AddAt(4, ltrl);
                                        }
                                        else
                                        {
                                            page.Header.Controls.Add(ltrl);
                                        }
                                    }
                                    else if (item.Name.ToLower() == "ie7")
                                    {
                                        ltrl.Text = "";
                                        if (page.Header.Controls.Count > 0)
                                        {
                                            page.Header.Controls.AddAt(4, ltrl);
                                        }
                                        else
                                        {
                                            page.Header.Controls.Add(ltrl);
                                        }
                                    }
                                    else
                                    {
                                        if (item.Name.ToLower() == "mobile")
                                        {
                                            page.Header.Controls.Add(link);
                                        }
                                        else
                                        {
                                            page.Header.Controls.Add(link);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Debug(ex.Message, ex);
                throw ex;
            }
            finally
            {
                urlOptions = null;
            }
        }

Creating a static Helper method for attaching JavaScript

public static void SetupJavaScripts(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            urlOptions.AlwaysIncludeServerUrl = true;
            urlOptions.AddAspxExtension = true;

            if (siteSettingItem != null)
            {

                String[] jsIDs = null;
                if (!string.IsNullOrEmpty(siteSettingItem["javascripts"]))
                {
                    jsIDs = siteSettingItem["javascripts"].Split(new char[] { '|' });

                    //set the options for the item URL
                    urlOptions.AlwaysIncludeServerUrl = true;
                    urlOptions.AddAspxExtension = true;

                    foreach (string ids in jsIDs)
                    {
                        if (!string.IsNullOrEmpty(ids))
                        {
                            Sitecore.Data.Items.Item js = Sitecore.Context.Database.GetItem(ids);
                            if (js.TemplateID == TemplateIds.Templates.JavaScript)
                            {
                                HtmlGenericControl script = new HtmlGenericControl("script");
                                script.Attributes.Add("type", "text/javascript");
                                script.Attributes.Add("language", "javascript");
                                script.Attributes.Add("src", Sitecore.Links.LinkManager.GetItemUrl(js, urlOptions).Replace(".aspx", ".js"));
                                page.Header.Controls.Add(script);
                            }
                        }
                    }
                }
            }
        }

Calling Helper methods from Layout

protected void Page_Init(object sender, EventArgs e)
        {
            Item siteSetting = Helper.GetSiteSettings();
            Helper.SetupJavaScripts(this, siteSetting);
            Helper.SetupStylesheets(this, siteSetting);
}

Advantages

– Flexibility to Content Authors for making amends to CSS and JS files and publish them.
– CSS and JS management gets easy as Developers involvement is not required for deployment and that too on different environments.

Disadvantages

– Utmost care needs to be taken by content authors otherwise wrongly made changes to CSS and JS can have adverse look and feel effect on the site.
– Changes done in CSS and JS might not reflect immediately if Sitecore Cache is not updated.
– Performance of the site might degrade as CSS and JS are now items in sitecore as compared to linking the files physically.

B) CSS and JS Stored as Media Items in Sitecore

Storing CSS and JS as Media items in sitecore gives one advantage over the previous implementation, content authors or front end developers can directly upload the files into media library without the hassle of copy pasting the content of these files into sitecore fields.

Media item approach again can be implemented in two ways where the HTML markup for tags can be static or dynamically generated from code.

Static inclusion of <link> and <script> tag in layouts

Depending on how much code one want to write the layouts can contain the tags as follows,

<script type="text/javascript" src="/~/media/JScripts/jquerymin.js"></script>	

<link href="/~/media/StyleSheets/style.css" rel="stylesheet" type="text/css" />

Layout

style

The point to consider for inclusion of static tags is, a deployment would be needed for the first time whenever a new file is introduced or a file’s reference is to be removed

Dynamic inclusion of <link /> and <script> tag in layouts

For this approach upload CSS and JS files in media library, select the media library files on site setting items and use the below code to link the media items.

Note: CSS and JS files will be linked with .ashx extension still it will not cause any problems for these files to be rendered correctly.

public static void SetupMediaStylesheets(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            try
            {
                if (siteSettingItem != null)
                {
                    String[] stylesheetIDs = null;
                    if (!string.IsNullOrEmpty(siteSettingItem["Stylesheets"]))
                    {
                        stylesheetIDs = siteSettingItem["StyleSheets"].Split(new char[] { '|' });
                        //set the options for the item URL
                        urlOptions.AlwaysIncludeServerUrl = true;
                        urlOptions.AddAspxExtension = true;

                        foreach (string ids in stylesheetIDs)
                        {
                            if (!string.IsNullOrEmpty(ids))
                            {
                                Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(ids);

                                HtmlLink link = new HtmlLink();
                                LiteralControl ltrl = new LiteralControl();

                                link.Attributes.Add("type", "text/css");
                                link.Attributes.Add("rel", "stylesheet");
                                if (item.Name.ToLower() == "print")
                                {
                                    link.Attributes.Add("media", "print");
                                }
                                else
                                {
                                    if (item.Name.ToLower() == "mobile")
                                    {
                                        link.Attributes.Add("media", "all");
                                    }
                                    else
                                    {
                                        link.Attributes.Add("media", "screen");
                                    }
                                }
                                link.Attributes.Add("href", Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(item)));

                                if (item.Name.ToLower() == "ie6")
                                {
                                    ltrl.Text = "";
                                    if (page.Header.Controls.Count > 0)
                                    {
                                        page.Header.Controls.AddAt(4, ltrl);
                                    }
                                    else
                                    {
                                        page.Header.Controls.Add(ltrl);
                                    }
                                }
                                else if (item.Name.ToLower() == "ie7")
                                {
                                    ltrl.Text = "";
                                    if (page.Header.Controls.Count > 0)
                                    {
                                        page.Header.Controls.AddAt(4, ltrl);
                                    }
                                    else
                                    {
                                        page.Header.Controls.Add(ltrl);
                                    }
                                }
                                else
                                {
                                    if (item.Name.ToLower() == "mobile")
                                    {
                                        page.Header.Controls.Add(link);
                                    }
                                    else
                                    {
                                        page.Header.Controls.Add(link);
                                    }
                                }

                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Debug(ex.Message, ex);
                throw ex;
            }
            finally
            {
                urlOptions = null;
            }
        }
public static void SetupMediaJavaScripts(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            urlOptions.AlwaysIncludeServerUrl = true;
            urlOptions.AddAspxExtension = true;

            if (siteSettingItem != null)
            {

                String[] jsIDs = null;
                if (!string.IsNullOrEmpty(siteSettingItem["javascripts"]))
                {
                    jsIDs = siteSettingItem["javascripts"].Split(new char[] { '|' });

                    //set the options for the item URL
                    urlOptions.AlwaysIncludeServerUrl = true;
                    urlOptions.AddAspxExtension = true;

                    foreach (string ids in jsIDs)
                    {
                        if (!string.IsNullOrEmpty(ids))
                        {
                            Sitecore.Data.Items.Item js = Sitecore.Context.Database.GetItem(ids);
                            HtmlGenericControl script = new HtmlGenericControl("script");
                            script.Attributes.Add("type", "text/javascript");
                            script.Attributes.Add("language", "javascript");
                            script.Attributes.Add("src", Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(js)));
                            page.Header.Controls.Add(script);

                        }
                    }
                }
            }
        }

C) Link to file statically

Being a beginner in sitecore implementations one would always stick to the standard way of adding the CSS and JS using

<link /> and

<script> tags respectively directly on the layout files.

There is no harm including files physically, it’s just that the requirements decides what should one implement a dynamic solution or a static one.

Nice reads

–       Building a Sitecore Base Page Template

–       Managing CSS Files in Sitecore by Mark Graber

–       Managing CSS in the Sitecore Media Library