Great overlapping HTML element?

Is it possible to write a JavaScript function that defines any HTML element (visible on the screen), it creates another HTML element to drain over it (to cover it)? And then, if I resize the page, it moves just like the component that it spans.

(So, for example, if I used getBoundingClientRect, this will not work if the source component has a width expressed as a percentage)

The function should handle any case whether the element (at the input) has fields, paddings, borders, whether its display is block or inline, etc.

I tried to add a position: relative to the parent component, and then create a position: absolute for the cover component. This did not work because it does not handle cases such as padding or fields.

Note: no jQuery. Clean 'cross browser' JavaScript, if possible

+7
source share
10 answers

I suggest you attach the element to the element that you want to "cover", indicate the position of the parent element: relative and assign the attached position of the element: absolute; top: 0; From left to right: 0; bottom: 0; right: 0;

Example...

Markup:

... <div id="content"> <div class="cover"></div> <div></div> </div> ... 

CSS

 .cover { position: relative; } .cover .mask { position: absolute; top:0; left:0; bottom: 0; right: 0; } 

JQuery

 $(function(){ $('.cover').append('<div class="mask" />'); }); 

this method will allow you to ignore what happens with any resize ...

===========================

Feedback Improvement ...

Shoudl indents will be sorted by absolute position, for the border and the field you will need to use some js and set the negative margins for the masking element. The demo link I included concerns only padding / margin items that are homogeneous - if you have items with different paddings / margins on each side, then you will have to do a bit more parsing.

Additional javascript will look something like this:

 var $hideme = $('.cover'); $('.mask',$hideme).css("margin", "-="+$hideme.css('border-width')); $('.mask',$hideme).css("margin", "-="+$hideme.css('margin')); 

Demo

+2
source

written below, a cover function using jQuery, try if this helps you

Hi, I have updated code that meets your needs ...

 function coverDiv(sourceId, targetId){ var source = document.getElementById(sourceId); var sourceComputed = window.getComputedStyle(source); var target = document.getElementById(targetId); var positioningProps = ["float","width","height","left","top","marginLeft","marginTop","paddingLeft","paddingTop"]; var cssText = ""; for(var i in positioningProps){ cProp = positioningProps[i]; if(source.style[cProp] == "" || source.style[cProp] == null) target.style[cProp] = sourceComputed[cProp]; else target.style[cProp] = source.style[cProp]; } source.style['position'] = "absolute"; source.style['zIndex'] = "1"; target.style['position'] = "absolute"; target.style['zIndex'] = "999"; } 

Try the demo here :: http://jsfiddle.net/tushhtrivedi/RDFRm/10/

+2
source

Adding a position: relative to the parent component and position: the absolute on the cover sounds functional, in fact, as long as you take into account the indents, margins and border. Set the top to -1 * (padding-top + margin-top + border-width-top) and so on for the other sides. Do this without setting the width or height, and it will resize itself to stick the edges where you place them. This, however, will not work on components that cannot contain divs.

Develop:

The problem you are facing is that if you try to cover an element with a width of: 100px; upholstery: 10px; border: 1px solid black, the cover is only 100 pixels wide and does not cover 10 pixels of the pad or 1 pixel border. You can compensate for this by setting left and right to -11px instead of 0. You will have to do this in the javascript function, which adds a cover if everything that interests you in the coverage has the same margins, margins.

+1
source
 function addCover(id) { var element = document.getElementById(id); var wrapper = document.createElement('div'); var cover = document.createElement('div'); wrapper.setAttribute('style', 'position: relative;'); cover.setAttribute('style','position:absolute; top: 0; bottom:0; right: 0; left: 0; width: 100%; height: 100%; z-index:10;') element.parentElement.replaceChild(wrapper, element); wrapper.appendChild(element); wrapper.appendChild(cover); } 
+1
source

So, one element should completely hide the other element? To what? Is this the time when it is hidden to display an item below it?

Why don't you just replace the item with a new one until you see the visible item? This will solve the scroll problem.

And much easier to do with pure JavaScript.

If you do not replace the elements on the frame site that you should not do in the first place, IMHO.

+1
source

Here is a version that works even for fixed or absolute positioned elements and that does not interrupt when scrolling or rewinding changes the position or size of an element:

 function cover(el, filling) { var c = document.createElement('div'); c.style.background = filling; var els = window.getComputedStyle(el) c.style.position = els.position=='fixed' ? 'fixed':'absolute'; c.style.zIndex = parseInt(els.zIndex)+1; document.body.appendChild(c); var place = function() { c.style.width = el.offsetWidth+'px'; c.style.height = el.offsetHeight+'px'; c.style.left = el.offsetLeft+'px'; c.style.top = el.offsetTop+'px'; }; place(); window.addEventListener('resize', place); } 

You call it this way:

 cover(myElement, 'black'); 

Demonstration

There are two limitations:

  • it does not work correctly for some multi-line embedded blocks.
  • as it includes a script that responds to a resize event, possibly with quick resizing, to temporarily see the element behind
0
source

Assuming I understand you correctly, an easy (and best) way to do this is to nest the element inside the element you want to cover. The outer element must have a relative position, and the nested element must have absolute positioning (the value 0 is set on each side). Usng z-index for each element, you can stack them on top of each other, regardless of filling or field.

 <style> .layer-1 { width: 100px; height: 100px; background: red; position: relative; z-index: 1; } .layer-2 { background: blue; position: absolute; z-index:2; top: 0; bottom: 0; left: 0; right: 0; } </style> <div class="layer-1"> <span class="layer-2"></span> </div> 

Live example with a few lines of code, CSS / HTML only: http://jsfiddle.net/3hBsZ/

EDIT: After re-reading the question, I misunderstood it. You are looking for a javascript solution, not CSS based. However, this CSS solution would be more efficient and cross-browser than javascript based. Just my opinion ...

0
source

Hope this is what you want

 ///questions/11599/retrieve-the-position-xy-of-an-html-element/80441#80441 function getOffset(el) { var _x = 0; var _y = 0; while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) { _x += el.offsetLeft - el.scrollLeft; _y += el.offsetTop - el.scrollTop; el = el.offsetParent; } return { top: _y, left: _x }; } function overlap(element) { this.element = element; this.overlapper = document.createElement("Div"); this.__constructor = function () { var left = getOffset(this.element).left; var top = getOffset(this.element).top; var width = this.element.offsetWidth; var height = this.element.offsetHeight; this.overlapper.style.position = "absolute"; this.overlapper.style.width = width + "px"; this.overlapper.style.height = height + "px"; this.overlapper.style.left = left + "px"; this.overlapper.style.top = top + "px"; this.overlapper.style.background = "black"; this.overlapper.style.zIndex = 999; document.body.appendChild(this.overlapper); } this.update = function () { var left = getOffset(this.element).left; var top = getOffset(this.element).top; var width = this.element.offsetWidth; var height = this.element.offsetHeight; this.overlapper.style.top = top + "px"; this.overlapper.style.left = left + "px"; this.overlapper.style.width = width + "px"; this.overlapper.style.height = height + "px"; } this.__constructor(); } 

the offset of the function element was obtained on this post

I made a violin as an example

http://jsfiddle.net/takedownbig/ASuEJ/

it will get the actual position on the element’s screen to update the element, you should initiate the function of updating the object, I recommend using it as my example. Works on ie9 + I would like to have this work on ie8 too: /

@edit: the function does not have all the update methods, but if you find them, you can simply run the update function to correct the actual position and width.

0
source

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/

0
source

Just stumbled upon this old thread, while googling for something else.

If all you want to do is select the element that needs to be covered and put some text in the overlay, then you can do it without any javascript, just using CSS: after (the element to be tackled requires the position: relative, though).

 div#source { position: relative; } div#source:after { content: "Covered"; background: purple; position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 

http://jsfiddle.net/kfdmta7w/

0
source

All Articles