1-888-365-2779
+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / How to add a CSS stylesheet to a sitefinity page

How to add a CSS stylesheet to a sitefinity page

5 posts, 0 answered
  1. Marko
    Marko avatar
    148 posts
    Registered:
    30 Jul 2008
    09 Mar 2009
    Link to this post
    I needed a way to add a specific set of CSS rules that apply only to a subset of pages on our website (a particular branch of pages, deep in the site structure).  The subset of pages is ALREADY using a particular site template, which is using a particular ASP.NET Theme, which in-turn, is using some CSS already.  So the "extra" CSS needs to be applied on top of that, for every page in this specific branch of pages.

    I searched on the forum and saw few other posts regarding this (or similar), but no real solution, other than few mentions of Telerik intending to provide this functionality in the future.  But I needed this now, so I decided to give it a try.

    The most obvious and tempting choice, at least for me, was to simply make another "template" page and reference a specific stylesheet directly in the master page (or to make a Theme that can be used in a specific page).  Then the specific subset of pages that needed to have this would just inherit the styles from that template and/or Theme.  However, because of how we introduce new content on our website, we would need to do this again and again, and I didn't like the idea of adding to the ever-growing list of templates or themes...  So I implemented a user control which makes use of Sitefinity's own <sf:CssFileLink> control, but provides a way to set some of its attributes through the Sitefinity Page Editor UI.  I don't know if I've done something that's already been solved in ver. 3.6, or if somebody else has solved this differently (better), but I couldn't find a solution from the few quick searches on the forum, and I'm not running 3.6 yet.  So here's what I did:

    1. Make a new user control. I called mine PageSpecificCSS.ascx:
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="PageSpecificCSS.ascx.cs" Inherits="MyUserControls_PageSpecificCSS" %>  
    <%@ Register Assembly="Telerik.Cms.Web.UI" Namespace="Telerik.Cms.Web.UI" TagPrefix="sf" %> 
     
    <sf:CssFileLink ID="CssFileLink1" runat="server" FileName="INSERT CSS FILE PATH HERE" /> 
    The key here is that we are using the <sf:CssFileLink> control, which allows you to reference a CSS stylesheet file from the file system.  The rendered markup code will put the stylesheet reference line in the HEAD element, which is exactly what I needed.

    However, the CssFileLink control is only modified through code, it seems, so I needed to "open up" some of its properties so that they can be set fro the UI.

    Note that the "insert css file path here" is not telling YOU, the developer, to insert something different there in the code of the ASCX file.  You should literally make your ascx code like you see it above, verbatim.  The "insert css file path here" will show up in the UI as the default setting for the CSS file path (coming up).

    2. The code-behind for the user control:
    using System; 
    using System.ComponentModel; 
     
    [DefaultProperty("CSSFile")] 
    public partial class MyUserControls_PageSpecificCSS : System.Web.UI.UserControl 
        #region "Properties" 
     
        [Browsable(true)] 
        [Category("CSS Settings")] 
        [DisplayName("CSS File")] 
        [Description("CSS File path and name (i.e. ~/css/mycssfile.css")] 
        public string CSSFile 
        { 
            get { return CssFileLink1.FileName; } 
            set { CssFileLink1.FileName = value; } 
        } 
     
        [Browsable(true)] 
        [Category("CSS Settings")] 
        [DisplayName("Media")] 
        [Description("CSS Media type(s). Separate by comma, if there are multiple (i.e. Screen, Print)")] 
        public string Media 
        { 
            get { return CssFileLink1.Media; } 
            set { CssFileLink1.Media = value; } 
        } 
        #endregion 
    So I am basically "opening up" the FileName and Media properties of the CssFileLink control, and making them updateable via my own properties through the Sitefinity UI (still coming up).

    3. Make the control accessible in the web.config:
    <add name="Page Specific CSS" section="My Custom Controls" url="~/MyUserControls/PageSpecificCSS.ascx" /> 

    4. Browse to your website and log into Sitefinity UI.  Pull up a specific page that you wish to add some page-specific CSS to, click on EDIT, and add your newly-created user control "Page Specific CSS" to ANY CONTENT REGION on the page (just drag-drop). For example, you can add it to your HEADER content placeholder, or FOOTER, ort whatever.  It really doesn't matter because the sf:CssFileLink control will always render witin HEAD section.

    5. Mouse-over and click "EDIT".  On the list of properties, you should see "CSS File" and "Media."  Here, you should see that afore-mentioned default setting "insert css file path here."  It assumes that you MUST change that.  An example of a valid entry is "~/myStyles/special.css" , where "myStyles/special.css" exists in the file system within your website.  The "media" property can be left blank, or you can enter values such as "Screen" or "Print" or even "Screen, Print" etc. (this is by design of sf:CssFileLink control from Telerik).

    6. Save the user control properties, and save the page.  Open the page in web browser and you should see the specific styles from /myStyles/special.css being applied (depending on what your styles are, of course).  At the very least, you should see the following line in the <HEAD> element of your rendered page (pull up page Source Code from your browser):
    <head> 
       ... 
       ... 
       <link href="/MyStyles/special.css" type="text/css" rel="stylesheet"></link> 
    </head> 

    OR something like this, depending on your specific value in "Media" :

    <head> 
       ... 
       ... 
       <link href="/MyStyles/special.css" type="text/css" media="screen" rel="stylesheet"></link> 
    </head> 


    And there you go.  It's a little clunky, perhaps, and not all-that robust. But it works and it's fairly flexible.  This should work by itself, but I went on to further extend this and make it somewhat more integrated into things on my website:

    (7.) Open up one (or more) of the existing Master pages in App_Master folder, which are being used to generate the Sitefinity template pages.  Add the following content placeholder to the VERY BOTTOM of the master page (but before the form, body, and html closing tags):
       ... 
       <asp:ContentPlaceHolder ID="AdditionalPageStyles" runat="server" /> 
    </form> 
    </body> 
    </html> 

    That way, when you open a page that's using that particular template, you will see a content region at the VERY bottom of the screen called "AdditionalPageStyles" where you can drag-and-drop your "PageSpecificCSS" control.  That way you won't "dirty up" the other placeholders which are meant for regular stuff (header, main content, footer, etc.).  And if you never drop a PageSpecificCSS control in it, it won't render anything else, so you're safe (unless you drop some other Sitefinity controls in it, of course).

    That's it.  I did this just a few days ago, and I haven't had much time to test this out thoroughly.  So don't beat me over the head if I missed some integral thing here, or even if I completely messed up and this solution doesn't work as intended.  It seemed to do its job properly in my dev environment, and I hope it will for others, too.  If nothing, it might provoke an interesting discussion and bring about some new and interesting ideas.  Telerik gurus, feel free to correct anything I may have said incorrectly here, particularly regarding the CssFileLink control.

    Of course, I realize that a response might be "this has been done before."  :-)  Oh well...
  2. Parvan
    Parvan avatar
    151 posts
    Registered:
    24 Sep 2012
    10 Mar 2009
    Link to this post
    Hello Marko,

    Thank you for contacting us.

    Your solution is good. The CssFileLink class can be used to add dynamically css reference.

    Note: There is also a class JsFileLink that can be used to add javascript file references.

    For your case I think there is an easy solution. If you need pages from given template (master page) to have the same css rules, just copy your css files in App_Themes/<your template theme>.
    These css files will be automatically registered.

    I hope this information will help you.

    Kind regards,
    Parvan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  3. Marko
    Marko avatar
    148 posts
    Registered:
    30 Jul 2008
    10 Mar 2009
    Link to this post
    Thanks Parvan.  I didn't know about jsFileLink.  There are few situations where it could have been useful to have that, but I haven't added much javascript to the site yet.

    Regarding the Themes and CSS...  What I needed was NOT just some extra CSS for the pages using a particular template (master page).  I needed to apply certain CSS to ONLY a subset of pages whch are using the template.  But since many other pages are using the same template, I couldn't just add the CSS to the Theme, because the CSS would have been applied elsewhere.  For example,

    ROOT
    -- Page 1
    ------ SubPage 1.1
    ------ SubPage 1.2
    -- Page 2
    ------ SubPage 2.1
    ------ SubPage 2.2
    -- Page 3
    ------ SubPage 3.1
    ------ SubPage 3.2

    Let's say all of those pages are using Template X.  Template X has a Theme attached to it and the CSS is applied throughout the site.  Let's say I want SubPage 3.1, SubPage 3.2, and soon-to-be-added SubPage 3.3 all to have Template X (because that gives the basic page layout, positioning, and font colors), but I ALSO want to apply some drastic changes to the page background, header, footer, etc.  Dropping a user control which in-turn will save properties to the CssFileLink control will ultimately get applied in the HEAD element, effectively overwriting any particular CSS classes I specify.

    Especially if you anticipate needing to do this again and again: let's say next month, I need to add Page 4 with its children SubPage 4.1 and SubPage 4.2, and all of them need to have the same basic CSS applied through the Theme. But I need different CSS positioning and header, etc.  This way I don't have to keep adding CSS to the Theme (nor do I have to keep adding new Themes for specific purposes like these), all I need to do is drop the CSS control on the pages needing the custom CSS.
  4. Parvan
    Parvan avatar
    151 posts
    Registered:
    24 Sep 2012
    11 Mar 2009
    Link to this post
    Hi Marko,

    You can simplify your solution further. You can use directly the CssFileLink control in the toolbox.
    Just add this line to the toolbox section of your site web.config:
    <toolboxControls> 
    ... 
    <add name="Css File Link" section="Most popular" type="Telerik.Cms.Web.UI.CssFileLink, Telerik.Cms.Web.UI" /> 
    </toolboxControls> 

    Then Drag and drop this control(it will be in Most Popular section of the toolbox) on your page.
    Note: When you drag and drop the control for first time it will show error message. After you set the File Link->FileName property in the Advanced tab this error message will disappear.

    You need to add the CssFileLink to every page that needs specific css file.

    There is one solution that can help you to add CssFileLink to every page in this forum post - Page title automatically generated from navigational structure. This solution will allow you to set which css file to be used programmatically.

    You need to put the attached class in your site App_Code folder and change ~/Sitefinity/cmsentrypoint.aspx as described in the forum post.
    protected override void OnPreRender(EventArgs e) 
    base.OnPreRender(e); 
     
     
    if (SiteMap.CurrentNode != null && 
        SiteMap.CurrentNode.ParentNode != null
        string filename = ""
         
        if (SiteMap.CurrentNode.ParentNode.Title == "Page 1"
        { 
            filename = "~/Sitefinity/page1.css"
        } 
        else if (SiteMap.CurrentNode.ParentNode.Title == "Page 2"
        { 
            filename = "~/Sitefinity/page2.css"
        } 
        if (!string.IsNullOrEmpty(filename)) 
        { 
            CssFileLink cssLink = new CssFileLink(); 
            cssLink.FileName = filename; 
            this.Page.Controls.Add(cssLink); 
        } 

    I hope this information will help you.

    All the best,
    Parvan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  5. Marko
    Marko avatar
    148 posts
    Registered:
    30 Jul 2008
    11 Mar 2009
    Link to this post
    Thanks Parvan,

    I didn't even think to throw in CssFileLink control directly into the web.config.  That said, however, I now like the added wrapper layer of a custom user control around CssFileLink because it allows for greater control of the Properties (Description, DisplayName).  Also, that default setting for FileName that I was inserting "insert file path here" eliminates that error message which you mentioned. 

    And the other piece (adding CssFileLInk to every page in a specific subset of pages) sounds very good! 
Register for webinar
5 posts, 0 answered