How often, this is a problem that seems a lot simpler than it turns out when you start trying to solve it. I let him go, and although I still do not like it, I will share with you my results.
Firstly, I should note that jQuery is an absolutely correct JavaScript browser, so I cannot come up with any good reason not to use it. Definitely, if you download it from a Google CDN or similar, it will probably already be in your users cache. So I went ahead and wrote a little jQuery plugin (my javascript for the old school is just a rusty way to be honest).
First code:
// jQuery plugin to create overlays // apply to any container that contains DOM elements to be overlayed $.fn.overlayDiv = function() { // remove any old overlays (could be there on resize) $(this).find('.overlay').remove(); // loop trough the remaining children $(this).find('*').each(function() { // cache some variables var $el = $(this); var $parent = $el.parent(); // make the parent relative, if not yet absolute or fixed, for easy positioning if ($parent.css('position') !== 'fixed' && $parent.css('position') !== 'absolute') { $parent.css('position', 'relative'); } // prepare the css var css = {}; css.zIndex = $el.css('z-index'); css.position = $el.css('position') == 'fixed' ? 'fixed' : 'absolute'; css.display = 'block'; // check if inline or block, and calculate settings appropriately if ($el.css('display') == 'inline') { // -- inline // clone the element and render it on one line var $clone = $el.clone(); $clone.css({ width: 'auto', display: 'block', whiteSpace: 'nowrap' }); $clone.insertAfter($el); // compare height of element and clone if ($el.outerHeight(true) == $clone.outerHeight(true)) { // if the $el is on a single line css.width = $el.outerWidth(true); css.height = $el.outerHeight(true); css.top = $el.position().top; css.left = $el.position().left; // apply the styling to an overlay div and include it in the DOM $('<div class="overlay"></div>').css(css).insertAfter($el); } else { // if the $el is on multiple lines (we need up to 3 divs to overlay) // -- this part of the code needs improving -- var lineHeight = $clone.outerHeight(); var totalWidth = $clone.outerWidth(); var lines = $el.outerHeight() / lineHeight; var maxWidth = $parent.width(); // top overlay css.width = maxWidth - $el.position().left; css.height = lineHeight; css.top = $el.position().top; css.left = $el.position().left; $('<div class="overlay top"></div>').css(css).insertAfter($el); // bottom overlay css.width = totalWidth - css.width - ((lines-2) * maxWidth); css.top = css.top + (lineHeight*lines); css.left = 0; $('<div class="overlay bottom"></div>').css(css).insertAfter($el); // center overlay css.width = maxWidth; css.height = (lines- 2) * lineHeight; // -- /needs improving -- // } $clone.remove(); } else { // -- block css.width = $el.outerWidth(true); css.left = $el.position().left; // -- height and top might need to improved if you want collapsing margins taken into account css.height = $el.outerHeight(true); css.top = $el.position().top; // apply the styling to an overlay div and include it in the DOM $('<div class="overlay"></div>').css(css).insertAfter($el); } }); } // when the window is loaded or resized (not just ready, the images need to be there to copy their position and size) $(window).on('load resize', function() { // apply the overlay plugin to the body to cover all elements, or recalculate their positioning $('body').overlayDiv(); });
There are many comments here, so I think this should be clear, but feel free to ask if you want any clarifications.
You can see the code in action: http://jsfiddle.net/pP96f/7/
About the two remaining issues:
- The biggest problem is inline elements that span multiple lines. If you want to cover only the text inside the element, you will need up to three separate overlays for this. I was struggling with sizes (especially with the width of the bottom div), and in the end I gave up. Any input would be appreciated!
- A smaller problem is one of the collapsing fields. It should not be difficult to solve, but I was not sure how you wanted it to be handled. (And I already spend a lot of time on this question ...)
Hope my input can be helpful!
change
For the version that allows you to select the specific elements that you want to overlay, rather than just select the parent and have all the children (recursively) superimposed, look at this slightly modified version of the code: http://jsfiddle.net/ARWBD/2/
Pevara
source share