CSS Independent Content: Difference between revisions
I think the more common use case is a panel that doesn't cover center screen. |
|||
(14 intermediate revisions by 8 users not shown) | |||
Line 1: | Line 1: | ||
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 | 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: | The solution is to add your panel inside an iframe. | ||
Example code: | |||
<pre class='sample'> | |||
// 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); | |||
</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!"; }