【问题标题】:Violate z-index, and force element to front anyway (or fake it)违反 z-index,并强制元素放在前面(或伪造它)
【发布时间】:2015-11-11 12:43:36
【问题描述】:

我将在我的问题开始前说,我并没有专门与这里的“z”解决方案结婚,但我不确定还有什么可以工作。

任务:在页面顶部附加一个遮罩元素(固定、不透明度 0.5 等...),然后定位页面中的单个元素并强制它显示在那个面具的顶部。这样做的目的是突出显示集成到页面中的特定元素以进行演示。

限制:没有提前定义强制置顶的元素,页面上的任何元素都应该是可行的目标。

目标元素的父元素将有几个可能的 z-index 值,所有这些值都将低于掩码的 z,并且都不能更改。递归循环遍历所有父级并设置临时 css 样式是行不通的,因为它会破坏过程中的许多其他内容。

最好只使用 Css 的解决方案,虽然需要一点 js 就可以了。

想法:我最有希望的想法是使用 translateZ(或其他 3dTransform 类型样式)将单个元素强制置于所有未转换内容(包括蒙版)的顶部,但到目前为止还没有让它工作。

我还考虑克隆目标元素,从目标中收集位置和样式值,然后将克隆渲染到蒙版顶部。这似乎有点笨拙(而且有点恶心),我不确定它的防弹性如何。


到目前为止,我读过的所有其他解决方案都涉及重新排序 dom、更正父级上的位置或 z-index 样式,或者只是向目标添加缺少的位置样式……这些都不是此处适用的解决方案。

【问题讨论】:

  • z-index 和 z 变换(例如translateZ)是不相关的。增加z-index 可以工作。提供示例代码。
  • 需要 Javascript:克隆您的元素,将其添加为遮罩叠加层的子元素,然后将其在页面上的位置设置为与原始元素的位置相同。
  • +1 两次。克隆它...或在发送到顶部的元素的父元素上管理临时 z-index-es(存储它们的当前状态 - 位置和 z-index - 然后给他们所需的 z-index 并使它们恢复到原始状态,某事那样)。如果克隆,还要注意可访问性:元素是否可聚焦,页面是否仍然可以通过键盘仅以元素的自然顺序使用,还是需要像模态一样对待?

标签: css dom z-index css-transforms


【解决方案1】:

我会非常害怕克隆节点必须暴露,因为可能会损坏 CSS 选择器或事件处理程序。当然,如果您了解您的环境并且确定没有任何东西可以刹车,那么这可能是一个好方法。

但如果您感兴趣的元素恰好是普通矩形,您可以使用由四个较小矩形组成的叠加层来非常安全地模糊其周围环境。我做了一个快速的 VanillaJS 概念验证(点击周围):

function Obscurer() {
  this.cont = document.createElement('div')
  this.e1 = this.cont.appendChild(this.cont.cloneNode())
  this.e1.className = 'cover'
  this.e2 = this.cont.appendChild(this.e1.cloneNode())
  this.e3 = this.cont.appendChild(this.e1.cloneNode())
  this.e4 = this.cont.appendChild(this.e1.cloneNode())
}
Obscurer.prototype.obscureSurroundingsOf = function(el) {
  if (el.parentNode === this.cont) {
    document.body.removeChild(this.cont)
    return
  }
  var b = el.getBoundingClientRect()
  this.e1.style.width = b.left + b.width + 'px'
  this.e1.style.height = b.top + 'px'
  this.e2.style.left = this.e1.style.width
  this.e2.style.height = b.top + b.height + 'px'
  this.e3.style.top = this.e2.style.height
  this.e3.style.left = b.left + 'px'
  this.e4.style.top = b.top + 'px'
  this.e4.style.width = b.left + 'px'
  document.body.appendChild(this.cont)
}

var o = new Obscurer()

document.addEventListener('click', function(ev) {
  o.obscureSurroundingsOf(ev.target)
})
.cover {
  position: absolute;
  background-color: #000;
  opacity: 0.5;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}
<p>foo baz</p>
<p>baz <b>gazonk</b> <i>something</i></p>
<p>anything</p>

【讨论】:

  • 我很欣赏这个解决方案。我有几个形状不规则的区域更适合克隆解决方案,但我也有一些矩形区域需要保留它们的功能,所以我最终使用了两个解决方案和一个可选参数来在两者之间切换。
【解决方案2】:

我选择了克隆选项,并有一个解决方案,我对此不冷不热,但似乎可以正常工作。这是我用来创建和定位克隆的方法:

var renderClonedEl = function($el, childrenToCopy) {
    var $clone = $($el[0].cloneNode(true)),
        offset = $el.offset(),
        styles = window.getComputedStyle($el[0], null).cssText,
        correction = {
            left: parseInt($el.css('margin-left')) + parseInt($el.css('border-left-width')),
            top: parseInt($el.css('margin-top')) + parseInt($el.css('border-top-width'))
        },
        $child, $cloneChild;

    childrenToCopy = childrenToCopy || []; // Use array of selector strings to copy addional styles between children elements
    $clone[0].style.cssText = styles;

    for (var i = 0; i < childrenToCopy.length; i++) {
        $child = $el.find(childrenToCopy[i]);
        $cloneChild = $clone.find(childrenToCopy[i]);

        _.each($cloneChild, function(item) {
            item.style.cssText = window.getComputedStyle($child[0], null).cssText;
        });
    };

    $clone.addClass('el-clone').appendTo('body').css({
        top: offset.top - correction.top,
        left: offset.left - correction.left
    });

    return $clone;
}

...克隆的其他辅助样式:

.el-clone {
    position: absolute;
    z-index: 9999;
    pointer-events: none;
}

像这样调用方法...

var $newClone = renderClonedEl($('.el-to-clone'), ['.header > .title', '.header .btn']);

我将原始 el 作为 jQuery 选择传递(因为我可以使用 jQuery)。 .offset() 方法不考虑边距/填充/边框宽度,所以我正在调整。

childrenToCopy 是一个选择字符串数组,我可以传递它以另外将计算样式从子元素复制到克隆(当克隆具有大量子元素的复杂 el 时,其中一些会丢失样式)。

我还将返回克隆,以便启动代码在我们完成后正确销毁它。

我在一些普通的东西中加入了一点 jQuery 和下划线......我恰好有两个库可供我用于这个项目。

【讨论】:

    猜你喜欢
    • 2011-12-10
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 2014-12-14
    • 2012-09-09
    • 2015-11-10
    相关资源
    最近更新 更多