views:

90

answers:

2

I am working on an embeddable javascript which inserts HTML elements onto unknown pages. I have no control of the stylesheets of the pages I'll be inserting HTML into. The problem is that the HTML I insert will mistakenly stylized by the page, and I want to prevent that.

What's the least verbose and/or resource intensive to go about ensuring the elements I insert are exactly as I'd like them to be? Is there an easy way to clear all styling for a given HTML element and children? In firebug, for instance, you can remove all styling. I feel like there must, and the very least should, be a native way to exempt certain HTML elements from stylesheet rules?

Example:

var myHTML = $("<div>my html in here</div>");
myHTML.resetAllStyles();   //<--- what would this function do?
myHTML.appendTo("body");

I really want to avoid explicitly stating the attributes I want for each element I insert...

PS: I have a lot of experience with JS and CSS, so you can assume that I'll understand pretty much anything you're going to tell me.

+2  A: 

You cannot prevent an element inheriting CSS styles from parent nodes. All you can do is overwriting all styles that has been inherited.

Kau-Boy
Awful. Who are the short sighted idiots that came up with this spec?
Sambo
@Sambo - There are mechanisms to do this, if you want a frame, use a frame, an `<iframe>`.
Nick Craver
They were very clever creating CSS. But some programmers have to learn that they can not reinvent a programming lanuage for their needs :)
Kau-Boy
@Nick, unfortunately iframe is not an option I have.
Sambo
@Sambo - Why not? an `<iframe>` doesn't have to be another document or URL. CSS does *exactly* what it's name says, it cascades :)
Nick Craver
@Kau-Boy - CSS may be clever, yes, but how could they have overlooked something like: "style=none" or "inherit=false"
Sambo
@Sambo - [Definition for cascade](http://www.google.com/search?q=define:cascade) :)
Nick Craver
@sambo: because that makes no sense at all. Which style would a element have if it also doesn't inherit the browser default style. The way it works is just fine. You just have to learn how it works and why :)
Kau-Boy
@Nick - The content I am inserting will be overlayed above the top of the page, and will have mouseover menu items coming down. If I use an iframe, I'll have to size it very largely and it will interfere with the rest of the page. Do iframes support being transparent?
Sambo
If you would use an iframe, the JS in the frame can not interact with the document because of security reasons. So that might not work at all for you.
Kau-Boy
@Kau - Then there should be "style=default", or at the very least, a "default" option for **all** attributes, e.g: font-size: default;
Sambo
If you are talking about a widget some users can have on their pages, I would recommend to use inline-stylesheets only. Or you can add an additional link tag with you custom CSS using JavaScript on the page you integrating your element. That technique is used by many widgets. As in your code you insert it into the body tag, you only have to overwrite the body CSS values and typically a web designer assigns the main CSS propertied to a div called container, content etc.
Kau-Boy
Kau-Boy - The trouble is that my inline stylesheets would need to define every possible attribute that may already have been defined by the parent page.
Sambo
@Kau-Boy - That only applies if the `<iframe>` is pointed to a URL on a different domain, look at the [same-origin policy](http://en.wikipedia.org/wiki/Same_origin_policy) for more info. You can use an `<iframe>` however you want...for example this is how most rich text editors work. @Sambo - Can you not create a "default" class that sets what you need?
Nick Craver
What are we talking about you want to integrate in webpages? If it's really a widget and your CSS is destroey by a bad CSS implementation of a user, it's really his job to take back the styles himself. I never style many things within the body tag. Only reset all margins and padding because of IEs box-model and some font attirbutes.
Kau-Boy
@Nick - I believe that I'd need a "default" class for every type of element I'm going to use, then I'd have to apply that class programmatically to each element I create.
Sambo
@Nick: If the script creates the iframe you are absolutely right. In this case using an iframe might be the best solution.
Kau-Boy
@Sambo - Also stop and think if you *should* be doing this, what properties are interfering? Shouldn't you just set those, and *let* the user/page define the rest so it fits with the overall theme?
Nick Craver
@Kau - Do you suggest I ask my users not to define styles for any number of elements which may be present in my inserted HTML code? If not, then you are suggesting I explicitly define all attributes for all elements that I'm going to insert. This is the essence of my original question.
Sambo
“how could they have overlooked something like: "style=none" or "inherit=false"” - How could they have failed to cater for the exact edge case you’re currently experiencing??? Inexplicable!
Paul D. Waite
@Nick - Firstly, thanks a lot for discussing this with me. My widget is actually a bookmarklet, which means it is the browser user, not the website, which does the JS embedding. Some website's CSS actually breaks the functionality of the widget, while others just make it look a little off. Currently, I test my bookmarklet on a variety of sites and when I find something off, I go into firebug and find the culprit attribute and add it to an ever expanding list of CSS to overwrite. I was hoping to find a native/faster method.
Sambo
@Paul - This isn't too much of an edge case. It's a case that pretty much everybody deals with by simply overwriting and overwriting and overwriting. To me, it seems not only more elegant, but quite obvious to allow CSS to be turned "off" on certain elements.
Sambo
@Sambo: I absolutely agree that sometimes it would be nice to have a CSS property to turn CSS off. But nobody stops you making talking to the W3C guys to include that to CSS4 :) Until than I fear that you have to overwrite or use an iframe if that works. What does your bookmarklet do? Anything you can offer to the community? And btw. I am impressed how many comments are attached to my answer :)
Kau-Boy
@Kau - My bookmarklet is a customizable menu of shortcuts to various other webpages. For example, I open my bookmarklet on this page, and can easily determine the Alexa rating of this page, google any highlited text, search within this website via google, translate this page, etc. I'm also impressed by this ongoing conversation :)
Sambo
@Sambo - I don't get it. (Maybe I missed it.) Couldn't you just use javascript to slip in a new stylesheet that provides CSS reset and styling for your `myHTML` element?
patrick dw
We also had that, but he actually wanted to know how to "disable" CSS for an element which is not possible. And as he mentioned it's a bookmarklet and adding a custom CSS would probably blow up the boomarklet.
Kau-Boy
@Kau - I see. I would think that a good CSS reset, pared down to only the necessary elements, would be a great solution. Something like the YUI Reset. http://yui.yahooapis.com/3.1.1/build/cssreset/reset-min.css
patrick dw
@Patrick - I've looked into CSS reset stylesheets. They won't work for me because they assume you're using them on a clean slated page. This isn't the case for me -- any attribute on any element could be specified and I need to reset that. For instance, the page owner could specify a 10px pink border around all divs, and I'd have to be sure to specify "border: none;" for all divs that I'd insert.
Sambo
@Sambo - Ah, I get it. Makes sense.
patrick dw
@Sambo: “This isn't too much of an edge case. It's a case that pretty much everybody deals with by simply overwriting and overwriting and overwriting.” — Really? Maybe you’re making your CSS too general to begin with. If inheritance didn’t exist, I think you’d end up having to specify a lot more than you do now.
Paul D. Waite
@Paul - Perhaps you misunderstood my comments. I am not saying inheritance should be disabled across all stylesheets. Rather, I am saying that there should be an option to disable inheritance for certain elements, or at the very least provide "default" values for attributes.
Sambo
@Sambo: oh, no, I get that. I’m just saying that I don’t generally find myself needing to do that.
Paul D. Waite
+2  A: 

I'm going to throw this out there as a possibility. How about custom tags for your bookmarklet? Requires a little more tinkering with a custom xml namespace because of IE, but may be workable for you.

jQuery doesn't seem to mind either.

http://jsfiddle.net/uvfAf/1/

jQuery:

$('#tester').animate({opacity: .3},1000);

HTML:

   // Not the main HTML tags. These are embedded in the body as the root
   //   of the bookmarklet. Scary? Perhaps.
<html xmlns:customtag>
    <style> 
        @media all {  
          customtag\:someElement { 
            width:100px; 
            height: 100px; 
            background: blue; 
            display: block; 
          } 
          customtag\:someOtherElement { 
            width: 50px; 
            height: 50px; 
            background: red; 
            display: block; 
          }
        }
    </style>
    <customtag:someElement id='tester'>test</customtag:someElement>
    <customtag:someOtherElement>test</customtag:someOtherElement>
</html>​

I used this page to figure out how to do custom tags in IE:

http://happyworm.com/blog/tag/custom-tags/

EDIT:

Looks like IE wants the xmlns to be defined in HTML tags, so I changed the container to <html>. Not sure of the ramifications overall, but seems to work.

I updated the example and the jsFiddle.

patrick dw
This is an awesome approach! I'll give this a shot, though I suspect I'm in for a world of hurt when it comes to cross browser compatibility.
Sambo
In Chrome/Safari/Firefox, you wouldn't have to go to the trouble of all the funky XML namespace tags. You could just assign whatever tag you want `<mycustomtag></mycustomtag>` and it would work. IE is the problem, hence the xml namespacing. Seems to work just fine cross-browser.
patrick dw
@Sambo - Be sure to let me know how it turns out for you.
patrick dw