首页 > 解决方案 > CSS 剪辑路径在元素堆栈顺序之前中断伪 ::before

问题描述

我正在尝试在非矩形元素上创建磨砂玻璃效果,但没有成功。我遇到了一个奇怪的问题,我似乎无法解决问题......

毛玻璃效果很容易实现,方法是在文档主体上设置一个固定的背景图像,为元素添加部分透明的背景颜色,并创建一个具有相同固定背景图像的 ::before 伪元素并应用模糊过滤器。像这样:

  body {
    background: url(bg-lanterns.jpg) 0 / cover fixed;
  }

  main {
    position: relative;
    margin: 1rem auto;
    padding: 1rem;
    height: 600px;
    width: 800px;
    background: rgba(255,255,255,0.7);
  }

  main::before {
    content: '';
    z-index: -1;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: url(bg-lanterns.jpg) 0 / cover fixed;
    filter: blur(10px);
  }

磨砂玻璃效果

clip-path使用这样的方法也很容易创建非矩形元素:

  main {
    position: relative;
    margin: 1rem auto;
    padding: 1rem;
    height: 600px;
    width: 800px;
    background: rgba(255,255,255,0.7);
    clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
  }

非矩形元素

但是尝试结合这两种效果会破坏堆叠顺序并导致 ::before 元素出现在白色背景之上。

破碎的

我在 Chrome 和 Firefox 中得到了相同的结果,所以我想知道这是否是预期的行为,我只是做错了什么......有人可以解释这里发生的事情吗?

这是一个现场演示:

      body {
        background: url(https://i.imgur.com/y1TH8fR.jpg) 0 / cover fixed;
      }
      
      main {
        position: relative;
        margin: 1rem auto;
        padding: 1rem;
        height: 600px;
        width: 800px;
        background: rgba(255,255,255,0.7);
        clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
      }
      
      main::before {
        content: '';
        z-index: -1;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        padding: 1rem;
        background: url(https://i.imgur.com/y1TH8fR.jpg) 0 / cover fixed;
        filter: blur(10px);
      }
<main></main>

标签: csspseudo-elementclip-path

解决方案


根据规范clip-path

计算值不是 none 会导致创建堆叠上下文 [CSS21],就像 CSS opacity [CSS3COLOR] 对 1 以外的值所做的一样。

通过将白色添加到 ::after 伪元素并剪切两个伪元素而不是元素本身,我设法达到了预期的效果。

      body {
        background: url(https://i.imgur.com/y1TH8fR.jpg) 0 / cover fixed;
      }
      
      main {
        position: relative;
        margin: 1rem auto;
        height: 600px;
        width: 800px;
        display: flex;
        flex-flow: column nowrap;
        align-content: center;
        align-items: center;
        justify-content: center;
      }

      main::before,
      main::after {
        content: '';
        z-index: -1;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
      }
      
      main::before {
        background: url(https://i.imgur.com/y1TH8fR.jpg) 0 / cover fixed;
        filter: blur(10px);
      }
      
      main::after {
        background: rgba(255,255,255,0.7);
      }
<main> <span> test </span> </main>


推荐阅读