Andy Brudtkuhl
Andy Brudtkuhl

Reputation: 3652

Change Theme / CSS based on user

I am building a product that we are eventually going to white-label. Right now I am trying to figure out the best way to facilitate these requirements programmatically so the user can update the basic design of the site (ie header color, etc) via their profile/settings form.

Requirements:

  1. User can update the logo (this is complete)
  2. User can update basic design elements (based on CSS), ie header color, footer color, sidebar color - all basic CSS overrides

We don't want to use ASP.Net Themes/Skins because that requires storing static themes in the local file system. We would like to use CSS to override the base style and store this in the database.

Our initial plan is to store the CSS in a simple varchar field in the database and write that CSS out to the Master Page on Pre-Init event using "!" to override the base styles. Is this the best solution? If not, what have you done to accomplish this functionality/

Upvotes: 10

Views: 8136

Answers (8)

lbz
lbz

Reputation: 9748

I've been there some months ago. While using dynamic CSS generated by a dedicated handler / servlet has been the first solution, to improve performances a customized CSS is now produced on file overrinding the basic elements of the standard CSS:

<link rel="stylesheet" href="standard.css" />
<link rel="stylesheet" href="<%= customer_code %>/custom_style.css" />
...
<img scr="<%= customer_code %>/logo.png" />

Each custom CSS will have its own URL, so you can make the browser caching them.

This will make you saving for each request the users will make:

  1. traffic from the database to the application layer
  2. traffic from the application layer to the browser
  3. some computing at the application layer

I'll second the idea the user should have to fill out a web-form detailing what customizations they want to make.

Upvotes: 6

Andy Brudtkuhl
Andy Brudtkuhl

Reputation: 3652

I like the idea of using dynamic CSS using an ASP.Net Handler...

<link rel="stylesheet" href="style.ashx" />

style.ashx

<!--WebHandler Language="C#" Class="StyleSheetHandler"-->

StyleSheetHandler.cs

public class StyleSheetHandler : IHttpHandler {
        public void ProcessRequest (HttpContext context)
        {   
            context.Response.ContentType = "text/css";
            context.Response.ContentEncoding = System.Text.Encoding.UTF8;

            string css = BuildCSSString(); //not showing this function

            context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(600));
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Write( css );
        }

        public bool IsReusable
        {
            get { return true; }
        }

}

The BuildCSSString() Function will build the css based on the values stored in the database and return it to override the base style on the master page.

Upvotes: 1

questzen
questzen

Reputation: 3287

If I understood correctly, you want to facilitate color and typography related changes. What about layout? If we safely assume that only color and typography are going to change, we can reuse the same style classes at the end of existing base CSS file and thus override the styles (using !important though a good idea, prevents users from overriding with their custom styles).

These newly created classes can be compressed to a single line string and stored as a varchar, which would then be linked/copied inline while building the page. I can think of the following options

  1. Inline CSS
  2. Create a file partition where you can dump the generated CSS files and let browsers refer to that location (by creating a softlink?)
  3. Use Ajax, retrieve the CSS and modify the DOM

If layout is going to change, we are in a thicker soup, I would avoid this as the complexities involved with scripting/event-handling are way too much.

Upvotes: 0

Mr. Shiny and New 安宇
Mr. Shiny and New 安宇

Reputation: 13908

First, determine which resources can be replaced, and whether or not resources can be added. You will need to store these somewhere; for small resources such as logos the db is probably fine, otherwise you need to worry about the size in the db.

Then you can determine how much functionality you want the user to customize: just colours, or entire styles? If it's just colours, you can define some variables in a CSS file and serve the file dynamically, with data loaded from the db. The CSS file might be called styles.asp and contain code such as this:

.header_area {
  border: 1px solid <%=headerBorderColor%>;
  background-color:  <%=headerBGColor%>;
  foreground-color:  <%=headerFGColor%>;
}

(The syntax I used is JSP syntax, I don't know ASP, but the idea is the same.)

Alternatively, allow the user to specify an entire stylesheet, either replacing the default one or supplementing it. Then store the entire sheet in the DB and serve it using its own URL (don't embed it in the page).

<link rel="stylesheet" href="default_styles.css">
<link rel="stylesheet" href="white_label_css.asp">

Make sure you set the cache headers and content type appropriately on the css file if you serve it using an asp page.

If you are concerned about what kind of content the user can put in the white_label_css file, you can limit it by making a custom tool which generates the css and stores it in the db. For example, instead of allowing the user to upload any file and store it in the db, the user would have to fill out a web-form detailing what customizations they want to make. This way you can ensure that only certain css rules/changes are allowed (but that may not be flexible enough).

Upvotes: 3

Paddy Callaghan
Paddy Callaghan

Reputation: 324

With php for example you can create dynamic css, so this coupled with the user information stored in a db would surely suffice.

Try here or here as an introduction.

Upvotes: 0

Travis Illig
Travis Illig

Reputation: 23924

I think it depends on how savvy your users are about CSS. If they're web developers or have that inclination, having them write CSS is probably fine. If not, you'll either have to generate it statically based on their input and store it in the database OR you can just store the values entered and dynamically generate the CSS using a custom handler.

The custom handler approach would mean you could substitute values right in the middle of the CSS without having to worry about !important or the order in which the items are declared to ensure proper overrides happen.

Upvotes: 0

y0mbo
y0mbo

Reputation: 4602

I would avoid using the !important clause and instead just ensure their values appear in a <style> tag following the import of the regular style sheets.

Otherwise, I would do it the same way.

Upvotes: -1

warren
warren

Reputation: 33453

Your proposed method is how I would go about solving this problem: upload the user-controllable values (maybe just colors and font sizes) into a table linked to the user.

The logo/avatar you want the user to have can be stored in the db or as a file on the fs.

Upvotes: 0

Related Questions