views:

145

answers:

4

I'm creating a web app that user will be accessing in the field, so they'd like to be able to manually toggle the styles from light to dark depending on the ambient lighting. I'm using jQuery.

I added an id attribute to my stylesheet, then created a button using the toggle() event, in which I change the href attribute to the CSS file I want. The CSS file has several @import directives as I split the styles into several files for maintainability.

My problem is only the main CSS file is being applied. I tried using the absolute path in the @import directives, but no luck.

Is there a fix here I'm missing, or do I have to inlcude everything in a single CSS file?

Edit:

Apprently this is only a problem in IE8, works fine in Chrome and Firefox. Unfortunately, my client wants only IE8. Looks like this is a duplicate of this question.

A: 

I don't have a definitive answer, though I suspect the @imports aren't being "run" when you change the URL of the href.

I would take a different approach -- tag the body with a class and change the class when your toggle() event fires.

<body class="LightTheme">

then

document.getElementsByTagName("body")[0].className = "DarkTheme";

This does, unfortunately, mean that all styles for both themes must be available in the CSS, rather than loading one or the other set of CSS files. There are other strategies possible, including forcing a page reload when the style changes, where the server writes one or the other theme name as the class for the body, e.g. <body class="${chosenTheme}">

Stephen P
A: 

In my experience, IE8 doesn't like to recognize certain changes after it initially parses the DOM and applies styles. For instance, I recall having trouble with elements initially set to "display: none" and then trying to alter them via jQuery.

My answer was the same as Stephen's, however.

You mentioned ambient light - I assume you're talking about light hitting the monitor. If the intent is less about stylization than it is about usability, you may want to try a procedural traversal, converting background-color & color tags to HSB, altering brightness, then going back to RBG/hex. Depends on the size of pages, depends on your requirements, depends on intent. You could attach a class to all elements that might receive such alteration. With regard to images, you could preload 2 images overlapping one another, then adjust brightness by switching the opacity (like a slider going between the light copy/dark copy).

dukebag
A: 

I did indeed find the answer in this question, but I had to do a bit more to make it work for me. The toggle is performed on an IMG tag with the id ToggleStyle, so my jQuery code ended up thus:

$( "#ToggleStyle" ).toggle(
    function() {
        $( "link" ).last().remove();
        document.createStyleSheet( "styles/light/master.css" );
        $( this ).attr( "src", "images/light/style.png" );
    },
    function() {
        $( "link" ).last().remove();
        document.createStyleSheet( "styles/dark/master.css" );
        $( this ).attr( "src", "images/dark/style.png" );
    }
);

In response to @dukebag, yes, I meant light hitting the monitor, as this app will be used 24/7 and they wanted a low contrast theme for nighttime. While I like the transversal, the stylesheets are already complete and, like most projects, time dictates the quickest -- er, cheapest -- solution.

Michael Itzoe
A: 

Easy answer, you only need to make a few pointed additions to your stylesheet.

Just as a sidenote, based on my understanding of the requirements I would do the theme setting server side, it is my understanding that the theme would be active for at least a few hours a day.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
  <title>Test Page</title>
  <script src="jquery-1.4.2.min.js" type="text/javascript"></script>
  <style type="text/css">
    * { font-family: "Lucida Grande" , "Lucida Sans Unicode" , Verdana, sans-serif; }
    body { font-size: 0.7em; margin: 0; }    
    div#themeContainer, div#themeContainer div, div#header, div#footer, div#content
    { margin: 0; padding: 0; }    
    div#content
    { text-align: center; }
    div#header
    { height: 103px; background: #88f; }
    div#footer
    { height: 60px; background: #f88; }
    div#content div.centered
    { margin: 0 auto; width: 900px; text-align: left; height: 200px; background: #ddd; }
    div#content div.centered h1
    { margin-top: 0px; }    
    div.dark
    { background: #ccc; }    
    div.dark div#header
    { background: #777; }
    div.dark div#footer
    { background: #777; }    
    div.dark div#content div.centered
    { background: #234; color: #ddd; }
    div.dark h1
    { color: #efe; }
    div.dark a
    { color: #fff; font-weight: bold; }
  </style>
</head>
<body>
  <div id="themeContainer">
    <div id="header">
      <p>
        Header gumpf</p>
    </div>
    <div id="content">
      <div class="centered">
        <div>
          <h1>
            Header</h1>
          <p>
            Some text</p>
          <a id="changeTheme" href="#">Click here to change theme</a>
        </div>
      </div>
    </div>
    <div id="footer">
      <p>
        Footer gumpf</p>
    </div>
  </div>
  <script type="text/javascript">
    $(document).ready(function () {
      $("#changeTheme").click(function () {
        var container = $("#themeContainer");
        if (container.hasClass("dark"))
          container.removeClass("dark")
        else
          container.addClass("dark");
        return false;
      });
    });
  </script>
</body>
</html>
Andre Artus