views:

375

answers:

7

Is there a simple way via CSS or javascript or anything really to take a div and make it not inherit any styles?

I'm creating a bookmarklet which adds a header to a website. It modifies the DOM as follows:

var bodycontent = document.body.innerHTML;
document.body.innerHTML = '';

var header = document.createElement('div');
var bodycontainer = document.createElement('div');
header.setAttribute('id', 'newdiv-header');
bodycontainer.setAttribute('id','newdiv-bodycontainer');

header.innerHTML = "MY STUFF";
bodycontainer.innerHTML = bodycontent;

document.body.appendChild(header);
document.body.appendChild(bodycontainer);

so effectively what we end up with is this:

<html>
 <head> ...original head stuff... </head>
 <body>
  <div id="newdiv-header"> MY CONTENT </div>
  <div id="newdiv-bodycontainer"> ...original content of document.body.innerHTML... </div>
 </body>
</html>

all styled appropriately so that everything is visible, etc. The problem is that the original page's stylesheet affect the look of my header. I'd use frames and/or iframes but this breaks on sites which implement framebusting.

Thank you very much for any ideas!

+4  A: 

My only idea is to set every relevant CSS property to the default (or whatever you need). I don't think there's a way of preventing styles from being applied on a single div.

chris166
i tried using javascript to loop through all of document.getElementById('newdiv-header').style and set everything to '' but it didn't work... do you know of a way to automate your suggestion? I can't really go about trying to do that manually
Mala
Setting it to '' won't reset it to the defaults.
jimyi
+3  A: 

Maybe you could insert an iframe instead of a div.

jhurshman
this might be my only recourse. My hesitation is that it doubles the number of requests that need to happen before anything is displayed - first the script, and then the iframe target
Mala
A: 

Since it has an ID, you can just give whatever values you want using #newdiv-header.

If you're using a CMS or something where you can't effect the order in which stylesheets are applied, you can use !important.

Zack
It's a bookmarklet. http://en.wikipedia.org/wiki/Bookmarklet
jimyi
The issue is that since this needs to be able to be run on any given page, the number of css rules i would need to reset is phenomenally huge
Mala
+2  A: 

A slightly more kosher version of @chris166's suggestion would be to create a special CSS rule which zeroes out the necessary style properties of the target element. This way, you simply add the appropriate class ('zero' in this example) to the element and CSS/browser magic takes care of the rest (in this example we'll reset padding).

// in javascript
foo.className += ' zero'; // multiple classes (space seperated)

/* then in CSS */
.foo.zero { padding: 0px; }

This example uses multiple class CSS selectors to get around specificity problems however if you need IE6 support you may want to use alternative methods (i.e. a regular CSS rule which is more specific than the other rules matching your target elements)

Jaysen Marais
A: 

While this may not be of any direct help, it may be easier to move your code to jQuery - if time and resources permit.

jQuery has much better handling of HTML elements as well as the common functions used to interact with those elements.

For your question at the very least, selecting and unstyling a div in jQuery is a snap. I'm willing to bet that your code would also be reasonably straightforward to implement.

Heck, you could even just run a single snippet of jQuery just to accomplish this task.

EvilChookie
Just looked up jQuery... and it looks glorious. *reads tutorials*
Mala
*sigh* looks like i'm back to this. I've read up on jQuery and it's really quite fantastic - I've migrated most of my code over, and it works better than ever. But regarding this issue in particular, *how* could i run a single snippet of jQuery to accomplish this task?
Mala
http://docs.jquery.com/Attributes/removeClass - This should unstyle the div in the fashion you're looking for. Simply throw the removeClass inside a basic document.ready, and you should be cooking with gas.
EvilChookie
+1  A: 

Let me preface this by saying that all of the following is pure air-code :)

What if you attacked it from the other direction? Instead of resetting all of the styles in your div, modify the existing stylesheet so that all of the selectors target children of #newdiv-bodycontainer.

This site talks about the relevant API: http://www.javascriptkit.com/domref/stylesheet.shtml

Edit: Iterating on this idea, I put together some test code to make sure it works. I've included it below.

I also found the following site useful: http://www.javascriptkit.com/dhtmltutors/externalcss2.shtml

WARNING: This is not production code. It does not handle cross-browser incompatibilities (of which there are many), nor does it deal with compound selectors, nor does it deal with multiple stylesheets.

for (var i = 0; i < document.styleSheets[0].cssRules.length; ++i) {
    var selector = document.styleSheets[0].cssRules[i].selectorText;
    var declaration = document.styleSheets[0].cssRules[i].style.cssText;

    document.styleSheets[0].deleteRule(i);
    document.styleSheets[0].insertRule('.test ' + selector + '{' + declaration + '}', i);
    alert(document.styleSheets[0].cssRules[i].selectorText);
}

This is the HTML used to test it. It runs in Firefox and Chrome, but will require modifications to run in IE:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" > 
<html>
<head>
<title>Test</title>

 <style type="text/css">
  .test {
   background-color:red;
   border: black solid 1px;
  }
 </style>
</head>
<body>
 <div class="test" style="width: 10em;">
  This is some text that is probably long enough to wrap.
  <div class="test test2">Test2</div>
 </div>

 <script language="javascript">
  for (var i = 0; i < document.styleSheets[0].cssRules.length; ++i) {
   var selector = document.styleSheets[0].cssRules[i].selectorText;
   var declaration = document.styleSheets[0].cssRules[i].style.cssText;

   document.styleSheets[0].deleteRule(i);
   document.styleSheets[0].insertRule('.test ' + selector + '{' + declaration + '}', i);
   alert(document.styleSheets[0].cssRules[i].selectorText);
  }
 </script>
</body>
</html>
AaronSieb
it's a bookmarklet, he can't modify the stylesheets of every page that it goes on
geowa4
Why not? I don't mean physically modify the stylesheet file. I mean use JavaScript to dynamically modify it.
AaronSieb
This looks rather promising! I'll try this and let you know how it goes
Mala
A: 

If it has to be able to go on any page, you are either going to have to reset a ton of things or put it in a frame. But since you said frames are not acceptable, You can use Firebug to get a list of the div's computed style in your own sandbox environment.

In Firebug, inspect the element. Go to the right pane, and select the dropdown arrow next to "Style". Then select "Show computed styles". It's a lot of copying sure, but it solves your frame problem.

geowa4