CSS Independent Content: Difference between revisions

From GreaseSpot Wiki
Jump to navigationJump to search
Henrik (talk | contribs)
Now with working code :p
m Reverted edits by Ashok323 (talk) to last revision by Arantius
 
(16 intermediate revisions by 9 users not shown)
Line 1: Line 1:
Any HTML you inject into a site is subject to the CSS rules of that site. For many modifications, this is what you want: the elements you inject will fit in nicely. But if you inject something – perhaps a configuration panel – that should look the same across an entire site where styles can vary wildly (e.g. MySpace, eBay) or across multiple sites, you may find that you want it exempt from the site CSS.
Any HTML you inject into a site is subject to the CSS rules of that site.
This is often what you want: the elements you inject will fit in nicely.
But if you inject something – perhaps a configuration panel – that should look the same in pages where styles can vary wildly (e.g. MySpace, eBay) or across multiple sites (e.g. @include *), you may find that you want it exempt from the site CSS.


The solution is to add your code inside an iframe. This is a bit tricky. Example code:
The solution is to add your panel inside an iframe.
Example code:


// position:fixed means it scrolls along with the page. The z-index is necessary on sites
<pre class='sample'>
// like Wikipedia and GreaseSpot. The border is just a border. The rest of the CSS centers
// position:fixed means stay fixed even when the page scrolls. z-index keeps your iframe on top.
// the iframe horizontally and vertically.
// The remainder of the line smacks the panel into the bottom left corner, out of your way.
var css = 'position:fixed; top:50%; left:50%; width:30em; height:20em; margin-left:-15em;' +  
// Overflow (in combination with the setTimeout) ensures the iframe fits your entire panel.
          'margin-top:-10em; border:1px solid #000; z-index:9999';
var css = 'position:fixed; z-index:9999; bottom:0px; left:0px; border:0; margin:0; padding:0; ' +
          'overflow:hidden;'
var iframe = document.createElement('iframe');
 
iframe.setAttribute('style', css);
var iframe = document.createElement('iframe');
iframe.setAttribute('style', css);
// The about:blank page becomes a blank(!) canvas to modify
 
iframe.setAttribute('src', 'about:blank');
// The about:blank page becomes a blank(!) canvas to modify
iframe.src = 'about:blank';
document.body.appendChild(iframe);
 
document.body.appendChild(iframe);
var iframeWindow = unsafeWindow.frames[unsafeWindow.frames.length-1];
 
// Make sure Firefox initializes the DOM before we try to use it.
// The timeout ensures this code is not run until Firefox has created the new DOM
iframe.addEventListener("load", function() {
setTimeout(function() {
    var doc = iframe.contentDocument;
    doc.body.style.background = 'red';
    var doc = iframeWindow.document;
    doc.body.innerHTML = 'Test.';
    doc.body.style.background = 'red';
    // It seems Firefox (at least 3.6) has a bug. It will report offsetWidth less than clientWidth.
    doc.body.innerHTML = 'Test.';
    // So try clientWidth and clientHeight instead of offsetWidth and offsetHeight
    iframe.style.width = doc.body.offsetWidth + "px";
}, 0);
    iframe.style.height = doc.body.offsetHeight + "px";
}, false);
</pre>
 
The above code will result in a minimal panel always-on-top in the bottom left corner, that does not grows to contain its contents because iframe.style.height has fixed value.
For a more intrusive lightbox-style panel mid-screen, just drop the two <code>iframe.style</code> lines and change the CSS to e.g.:
 
<pre class='sample'>
// Margin, top, left, width and height center the iframe horizontally and vertically:
var css = 'position:fixed; z-index:9999; border:1px solid black; ' +
          'top:50%; left:50%; width:30em; margin:-15em 0 0 -10em; height:20em;';
</pre>
 
As Firefox's iframe handling is [https://bugzilla.mozilla.org/show_bug.cgi?id=295813 rather] [https://bugzilla.mozilla.org/show_bug.cgi?id=388714 buggy], you may want to spare yourself much pain by @require'ing [http://ecmanaut.googlecode.com/svn/trunk/lib/make-iframe.js this handy library] for roughly the above, and use code like this instead:
 
<pre class='sample'>
makeFrame(gotFrame);
 
function gotFrame(iframe, win, doc) {
  iframe.height = "50";
  iframe.style.position = "fixed";
  iframe.style.bottom = iframe.style.left = "0";
  doc.body.innerHTML = "Hello world!";
}
</pre>
 
[[Category:Coding Tips]]
[[Category:@require Library]]

Latest revision as of 22:21, 14 August 2013

Any HTML you inject into a site is subject to the CSS rules of that site. This is often what you want: the elements you inject will fit in nicely. But if you inject something – perhaps a configuration panel – that should look the same in pages where styles can vary wildly (e.g. MySpace, eBay) or across multiple sites (e.g. @include *), you may find that you want it exempt from the site CSS.

The solution is to add your panel inside an iframe. Example code:

// position:fixed means stay fixed even when the page scrolls. z-index keeps your iframe on top.
// The remainder of the line smacks the panel into the bottom left corner, out of your way.
// Overflow (in combination with the setTimeout) ensures the iframe fits your entire panel.
var css = 'position:fixed; z-index:9999; bottom:0px; left:0px; border:0; margin:0; padding:0; ' +
          'overflow:hidden;'

var iframe = document.createElement('iframe');
iframe.setAttribute('style', css);

// The about:blank page becomes a blank(!) canvas to modify
iframe.src = 'about:blank';

document.body.appendChild(iframe);

// Make sure Firefox initializes the DOM before we try to use it.
iframe.addEventListener("load", function() {
    var doc = iframe.contentDocument;
    doc.body.style.background = 'red';
    doc.body.innerHTML = 'Test.';
    // It seems Firefox (at least 3.6) has a bug. It will report offsetWidth less than clientWidth.
    // So try clientWidth and clientHeight instead of offsetWidth and offsetHeight
    iframe.style.width = doc.body.offsetWidth + "px";
    iframe.style.height = doc.body.offsetHeight + "px";
}, false);

The above code will result in a minimal panel always-on-top in the bottom left corner, that does not grows to contain its contents because iframe.style.height has fixed value. For a more intrusive lightbox-style panel mid-screen, just drop the two iframe.style lines and change the CSS to e.g.:

// Margin, top, left, width and height center the iframe horizontally and vertically:
var css = 'position:fixed; z-index:9999; border:1px solid black; ' +
          'top:50%; left:50%; width:30em; margin:-15em 0 0 -10em; height:20em;';

As Firefox's iframe handling is rather buggy, you may want to spare yourself much pain by @require'ing this handy library for roughly the above, and use code like this instead:

makeFrame(gotFrame);

function gotFrame(iframe, win, doc) {
  iframe.height = "50";
  iframe.style.position = "fixed";
  iframe.style.bottom = iframe.style.left = "0";
  doc.body.innerHTML = "Hello world!";
}