HTML元素的完美重叠?

时间:2013-04-05 15:43:23

标签: javascript html css

是否可以编写一个给出任何HTML元素的JavaScript函数 (在屏幕上可见)它创建了另一个HTML元素堆叠在它上面(以便覆盖它)?然后,如果我调整页面大小,它就会像它所覆盖的组件一样移动。

(例如,如果我使用的是getBoundingClientRect,如果原始组件的宽度以百分比表示,它将无效)

该函数应该处理任何情况,无论元素(在输入中)是否有边距,填充,边框,它的显示是块还是内联等等。

我尝试添加一个位置:相对于父组件,然后在" cover"上创建一个位置:absolute;零件。这不起作用,因为它不处理填充或边距等情况。

注意:没有jQuery。纯粹的跨浏览器' JavaScript,如果可能的话

11 个答案:

答案 0 :(得分:2)

我建议你将元素添加到你想要“覆盖”的元素,给父元素位置:relative,并给出附加元素位置:absolute;顶部:0;左:0;底部:0;右:0;

...示例

标记:

...
<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" />');
});

这种方法可以让你忽略任何调整大小......

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

基于反馈的改进......

填充shoudl按位置绝对排序,对于边框和边距,您需要使用一些js并在遮罩元素上设置负边距。我所包含的演示链接只处理带有填充/边距均匀的元素 - 如果你的每边都有不同填充/边距的元素,那么你将不得不做更多的解析。

额外的javascript看起来像:

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

Demo

答案 1 :(得分:2)

下面写的封面功能使用jQuery请试试,如果这项工作为你

您好我已经更新了满足您需求的代码......

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";
}

在这里尝试演示:: http://jsfiddle.net/tushhtrivedi/RDFRm/10/

答案 2 :(得分:1)

添加位置:相对于父组件和位置:封面上的绝对听起来可行,实际上,只要考虑填充,边距和边框。设置顶部等于-1 *(填充顶部+边缘顶部+边框宽度顶部),依此类推另一侧。在没有设置宽度或高度的情况下执行此操作,并且它会自行调整大小以将其边缘粘在您放置它们的位置。但是,这将无法处理不能包含div的组件。

详细说明:

您使用此方法遇到的问题是,如果您尝试覆盖宽度为100px的元素;填充:10px的;边框:1px纯黑色,封面仅100像素宽,不覆盖10个像素的填充或1像素边框。您可以通过向左和向右设置为-11px而不是0来对此进行补偿。除非您感兴趣的所有内容都具有相同的填充,边框和边距,否则您必须在添加封面的javascript函数中对此进行补偿。

答案 3 :(得分:1)

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);    

}

答案 4 :(得分:1)

那么,一个元素应该完全隐藏另一个元素?直到什么?隐藏的给定时间是否显示其下方的元素?

为什么不用 替换 元素,直到您希望原始元素可见?这将解决滚动问题。

使用纯JavaScript更容易。

除非您要更换框架网站上的元素,否则您首先不应该这样做,恕我直言。

答案 5 :(得分:0)

这是一个适用于固定或绝对定位元素的版本,当滚动或重排改变元素的位置或大小时,它不会中断:

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);
}

你这样称呼它:

cover(myElement, 'black');

<强> Demonstration

有两个限制:

  • 对于某些多行内联块
  • ,它无法正常工作
  • 因为它涉及一个脚本对resize事件做出反应,所以可能会通过快速调整大小来临时看到背后的元素

答案 6 :(得分:0)

假设我理解正确,最简单(最好)的方法是在要覆盖的元素中嵌入一个元素。外部元素应具有相对位置,嵌套元素应具有绝对定位(每边设置为0)。对每个元素使用ung z-index,无论填充或边距如何,都可以将它们叠加在一起。

<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>

仅包含几行代码的实例,仅限CSS / HTML:http://jsfiddle.net/3hBsZ/

编辑:重新阅读问题后,我确实误解了它。您正在寻找一个JavaScript解决方案,而不是基于CSS的解决方案。但是,这个CSS解决方案比基于javascript的解决方案更有效和跨浏览器。只是我的意见......

答案 7 :(得分:0)

我希望这就是你想要的

//https://stackoverflow.com/a/442474/1989562
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();
}

元素函数的偏移量来自此帖子 https://stackoverflow.com/a/442474/1989562

我做了一个小提琴作为例子

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

它将获得元素的屏幕上的实际位置,为了使元素更新你必须触发对象的更新功能,我建议像我的例子一样使用。 适用于ie9 +我想在ie8上也有这个工作:/

@edit:该功能没有所有更新方式,但如果你找到它们,你可以简单地触发更新功能来修复实际的位置和宽度。

答案 8 :(得分:0)

通常情况下,这是一个看起来更简单的问题,然后当你开始尝试解决这个问题时。我试了一下,虽然还不是我喜欢的100%,但我会和你分享我的成果。

首先我应该注意jQuery是完全有效的跨浏览器JavaScript,所以我想不出任何有理由不使用它。当然,如果您从Google CDN或类似设备加载它,它可能已经在您的用户缓存中。所以我继续编写了一个小的jQuery插件(老实说,JavaScript只是生锈的方式)。

首先是代码:

// 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();
});

那里有很多评论,所以我认为这应该是可以理解的,但随时可以询问你是否需要澄清。

您可以在此处查看代码: http://jsfiddle.net/pP96f/7/

关于剩下的2个问题:

  • 最大的问题是内联元素跨越多个 线。如果您只想覆盖元素内的文本,那么 将需要最多三个单独的叠加来实现这一目标。我曾是 与尺寸(特别是底部div的宽度)挣扎,最终我放弃了。任何输入 我将不胜感激!
  • 一个较小的问题是崩溃的边缘之一。这不应该难以解决,但我不确定你是如何处理的。 (我已经花了很多时间在这个问题上......)

希望我的意见有所帮助!

修改

对于允许您选择要覆盖的特定元素的版本,而不仅仅是选择一个父级并让所有子级(递归)重叠,请查看这个略微更改的代码版本:{{3 }}

答案 9 :(得分:0)

在google搜索其他内容时,遇到了这个旧帖子。

如果您要做的只是突出显示要覆盖的元素并在叠加层中放置一些文本,那么您可以在没有任何javascript的情况下执行此操作,只需使用CSS:after(要覆盖的元素需要位置) :相对虽然)。

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/

答案 10 :(得分:0)

使用jquery用户界面position尝试一下:

 _overlapTwoElements(topElement, baseElement) {
       if(baseElement.length && topElement.length) {
          topElement.width(baseElement.width());
          topElement.height(baseElement.height());
          topElement.position({ my: "left bottom", at: "left bottom", of: baseElement });
       }
    }