views:

2355

answers:

9

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: - User can update the logo (this is complete) - 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/

A: 

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.

warren
yea at this point we are storing the logo in the db as binary
A: 

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.

y0mbo
why wouldn't you avoid using !important? That way we are explicitly overriding the base even though we are adding this style after our base.
I see !important as a hack when you are unable to determine the source of a given style. I see it as a tool of last resort. If your style is after the base, it should override automatically. That's the whole point of *cascading* style sheets.
y0mbo
A: 

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.

Travis Illig
We won't have the users write CSS. They'll have a form to change header color and we'll write the CSS for them and store it
A: 

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.

+3  A: 

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).

Mr. Shiny and New
The user will be filling out a basic form to input their styles. We want to avoid storing them in the filesystem. Your idea is great but we will still need a default style (some users may not have their own style)
A: 

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.

questzen
no layout changes are needed (at least not yet). Mostly just color overrides. I am leaning toward the idea of inline CSS added on Pre-Init of the Master Page. Seems the least intrusive.
+1  A: 

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.

+3  A: 

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.

Luca
A: 

Hola

estoy tratando de hacer lo siguiente :

<link rel="stylesheet" href='<%= myCss; %>/estilo.css' type="text/css"/>

y en el page load asigno valor a la variable myCss

myCSS = "css";

y a la hora de correr mi pagna, no pasa nada, Qué estoy haciendo mal?

Alguien me podría auxiliar?

Saludos cordiales

Mayra