Sitecore’s flexibility allows it to go beyond just management of content but rather also manage other aspects of a website. The media library is generally used to store images, PDFs, documents, SWFs, etc. Presentation layer building blocks can also be stored in Sitecore’s Media Library, specifically CSS files. This article is a walk though on how you can add CSS files to the Media Library so they can be dynamically used on the site.
Why Manage CSS in Sitecore?
Your first question about this idea might be, why? Good question. Sitecore is a CMS after all, and after a lot of projects the request does come along at some point from a client to manage CSS dynamically. Traditionally, CSS is part of static content on a website, such as the base HTML structure for layouts, CSS for the presentation, and structural images (boxes, shadows, gradients, borders, etc). Though these static pieces are generally static on the file system, some end users like to be able to manage these in the CMS. This CMS management provides some benefits:
- Versioning: since the CSS items are in Sitecore, they can be versioned, and thus easily tracked for historical purposes.
- Ease of access: end users may not have access to the web server (you generally don’t provide that access to marketers) so Sitecore is a perfect interface for them to get to CSS files.
UPDATE: To clarify this specific scenario, this is not to include ALL CSS files in Sitecore. This is a nice approach if the client needs to manage a few aspects of a page that may change, e.g. color scheme. So you could have CSS files in Sitecore that change just a few things (e.g. red theme, blue theme, etc). This is the exact scenario I recently had work against. The layout of the article page is defined, but based on which article type (managed in Sitecore) certain colors needed to change. By making this CSS manageable in Sitecore, the client is able to create their own “themes” with their own CSS.
Configure The Site to Handle CSS Uploads
In order to allow CSS files to be uploaded into the media library, you need to tweak a config setting. In App_Config/MimeTypes.config
, find the CSS line and add <forceDownload>false</forceDownload>
. E.g.
[xml]
<mediaType extensions="css">
<mimeType>text/css</mimeType>
<forceDownload>false</forceDownload>
</mediaType>
[/xml]
Note: This change must be done before uploading CSS files to the Media Library. If it is not, any CSS file uploaded before the change will not render to the browser and direct requests to the file will prompt a download window.
Code to Read in CSS Files
Front-end:
[xml]
<asp:Literal ID="ltlDynamicCss" runat="server" />
[/xml]
C# Code-Behind:
[csharp]
FileField cssFileField = item.Fields["CSS File"];
Item mediaItem = cssFileField.MediaItem;
if(mediaItem != null) {
string cssPath = StringUtil.EnsurePrefix(‘/’, Sitecore.Resources.Media.MediaManager.GetMediaUrl(mediaItem));
ltlDynamicCss.Text = string.Format("<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />", cssPath);
}
[/csharp]
Beyond CSS
The code and technique is very simple here. Upload CSS to the media library, create a File field on an item template and populate it with the uploaded CSS, and read the direct path to the CSS file to render as a CSS link. This basic technique can also be applied for JavaScript.
This would be one of those instances where I would suggest against managing code in Sitecore. While it would be perfectly acceptable to maintain a link to said code within, say, a settings folder in the CMS, you should no more managed CSS or JavaScript within Sitecore than you should a codebehind.
The reasoning is simple — ease of update, and keeping your source control central. Back end and front end developers should be operating within the same source control, and removing CSS from that overall structure adds time, rather than convenience.
In short, is it cool that you can do this? Absolutely. Should it be done? Absolutely not. The same goes for JavaScript.
This technique is fairly common in Sharepoint environments… where you have to publish code updates. Publishing a style update is an excruciating exercise. Code is code — let’s leave it at that.
Hi Sam,
I certainly understand and agree with you. As I mentioned, this was to meet a specific client business requirement. Keeping general marketers away from CSS is the way to go, same for JS. When you work on a lot of Sitecore projects, at some point you may get some edge case where the client demands they have access to CSS and are willing to accept the risks and overhead of managing it (think of the nightmare of including CMS-uploaded images in CMS-managed CSS, zing!). Source control and separation of concerns is why we as developers keep CSS away from end clients. That said, we work for our clients, and when our clients have a business requirement in this, this is the solution. Thanks for your feedback!
Very creative, but the real question is can you manage the entries in the css file so you don’t have to re-upload it?
No you can’t as there no CSS editor tool (I bet someone will make one some day). The point is it’s possible to have these dynamic CSS files. They’re a pain to manage, but if requirements dictate their need, they can be done. A good example is theming: swapping a few foreground and background colors for say an article layout. Not all the CSS is managed this way, just a few lines needed for a unique theme.
Sorry to come in so late into this thread… This is similar in solution AND problem to how we’ve handled this thus far. (In general, site-wide css and js are part of the visual studio solution and untouched by non-developers.) But there are often needs for only page-specific or article series-specific styles and scripts unrelated to the entire site. (Skip a couple of paragraphs down for my dilemma:)
Coming in late to this project at my job, I’ve found our use of the media library for these files very clunky for us. Authors and especially graphic designers have to go through a process of editing a file, uploading the file, publishing it, checking it on the webpage(s), and then repeating the process again and again until it’s correct. Instead of simply editing the text within Sitecore.
So rather than having graphic designers and authors/editors trained on Visual Studio as well, and deal with the extra licenses, using a massive IDE for simple front end dev/verification, etc. I thought we had a solution for editing within Sitecore, but it’s only partially working…
-Have a template that has nothing but text (multi-line text) and MIME type(droplist/text/whatever).
-Make the above template use a blank layout that does nothing except Response.Write out the text and sets the MIME ContentType of the page.
-Items using that template are easy to edit within Sitecore, version-able, and referenced from any webpage.
Problem? Javascript works in all browsers, but CSS only works in IE. Typing in the path for that CSS file/item into the address bar of Chrome or Firefox gets a 404. The code so far is pretty simple in the blanklayout.aspx:
In Page_Load (or PreInit or Init, doesn’t matter)…
Response.Clear();
Response.ContentType = “text/css”; //or “text/javascript” or whatever
Response.Write(currentItem.Fields[“code”].ToString());
Testing this in a simple asp.net website, it works for any MIME type and any browser. It’s when this is in the confines of a Sitecore site that for some reason, CSS either doesn’t get served up or doesn’t get recognized by Chrome/Firefox. And that’s where I’m stuck.
And soon after I posted that, I figured out what may be the solution.
Pairing Response.ContentType with Response.Write should work, but for some reason, it works better for me using Page.ContentType and a literal control. Like litWriteMe.Text = currentItem.Fields[“code”].ToString();
The solution that we use in my shop is we serve out CSS and JS over our Akamai CDN. We still get to manage it internally, but in our code, we just append the Akamaized URL to the beginning and it knows to come grab it from our server so it can cache it until TTL expires.
So instead of pointing to /Styles/main.css we point to
<%=AkamaiPath%>/Styles/main.css
Coming in a little late to comment on this post and it’s funny that I’m thinking along the same lines. Glad to hear the pros and cons of each approach. I think we’re in a similar situation where our creative folks (somewhere between the “Designer” role and the “Developer” role) need the ability to manage portions of CSS for layout purposes.
I appreciate everyones’ insights regarding the pros and cons of the approach.
Can bundling be used on this? the include on bundles dont identify the styles
I suppose you could add a server-side bundler at runtime, right? For example, if you use dotLESS (server-side handler and DLL) and you upload CSS and LESS files, it and combine and minify them for you at runtime.