You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Overlay上制作镂空区域以显示下层视频内容?

实现带镂空区域的全屏视频遮罩

需求:全屏黑色遮罩覆盖屏幕,遮罩上显示白色文字,在.video-gap所在位置将遮罩镂空,露出下方视频。询问仅用CSS或CSS+JS的实现方案。

效果示意图

原始代码示例

HTML

<div class="video-container">
  <video autoplay muted playsinline loop >
            <source src="./video/video.mp4" />
        </video>

  <div class="video-overlay">
    <div class="text-container">
      <h1 class="text-line">We're here <div class="video-gap"></div> to make</h1>
      <h1 class="text-line">healthy <div class="video-gap"></div> living effortless,</h1>
      <h1 class="text-line">so you can <div class="video-gap"></div> live longer</h1>
      <h1 class="text-line">and happier <div class="video-gap"></div>
      </h1>
    </div>
  </div>

</div>

CSS

.video-container {
  height: 100vh;
  width: 100%;
}

.video-container video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-overlay {
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  place-items: center;
  place-content: center;
  background-color: rgb(4, 4, 4);
  z-index: 1;
}

.text-container {
  width: 100%;
  height: 100%;
  z-index: 2;
}

.text-line {
  width: 100%;
  max-height: 120px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  color: white;
  font-size: 100px;
}

.video-gap {
  position: relative;
  width: max-content;
  background-color: transparent;
  flex-grow: 1;
  border: 1px solid red;
}

推荐实现方案:CSS+JS(适配动态场景)

该方案通过JS动态计算.video-gap的位置,配合CSS的mask属性实现精准镂空,兼容所有现代浏览器,支持窗口缩放、文字换行等动态场景。

修改后的完整代码

HTML(无需改动)

同原始HTML代码

CSS

.video-container {
  height: 100vh;
  width: 100%;
  position: relative; /* 让内部绝对定位元素基于此容器 */
  overflow: hidden;
}

.video-container video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgb(4, 4, 4);
  /* 初始遮罩为全显示,后续JS动态修改 */
  mask: rect(0 100% 100% 0);
  -webkit-mask: rect(0 100% 100% 0);
}

.text-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 2rem;
  position: relative;
  z-index: 1; /* 确保白色文字在遮罩上方可见 */
}

.text-line {
  width: 100%;
  max-height: 120px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  color: white;
  font-size: clamp(2rem, 8vw, 6.25rem); /* 响应式字体,适配不同屏幕 */
  margin: 0.5rem 0;
}

.video-gap {
  flex-grow: 1;
  height: 100%;
  /* 仅用于占位,移除原始红色边框 */
}

JS

function updateOverlayMask() {
  const overlay = document.querySelector('.video-overlay');
  const gaps = document.querySelectorAll('.video-gap');
  const maskRects = [];

  gaps.forEach(gap => {
    const rect = gap.getBoundingClientRect();
    const overlayRect = overlay.getBoundingClientRect();
    // 计算镂空区域相对于遮罩层的坐标
    const x = rect.left - overlayRect.left;
    const y = rect.top - overlayRect.top;
    const width = rect.width;
    const height = rect.height;
    // 生成mask所需的rect参数格式:y1 x2 y2 x1
    maskRects.push(`rect(${y}px ${x + width}px ${y + height}px ${x}px)`);
  });

  if (maskRects.length) {
    // 设置遮罩:保留全屏区域,排除所有镂空区域
    overlay.style.mask = `rect(0 100% 100% 0), ${maskRects.join(', ')}`;
    overlay.style.maskComposite = 'exclude';
    // 兼容webkit内核浏览器(如Chrome、Safari)
    overlay.style.webkitMask = `rect(0 100% 100% 0), ${maskRects.join(', ')}`;
    overlay.style.webkitMaskComposite = 'xor';
  }
}

// 页面加载和窗口缩放时更新遮罩
window.addEventListener('load', updateOverlayMask);
window.addEventListener('resize', updateOverlayMask);

核心原理

  1. 遮罩层基础:.video-overlay作为全屏黑色遮罩,初始mask设置为全显示状态。
  2. 文字层级:.text-container设置z-index:1,确保白色文字始终在遮罩上方,不会被遮罩影响。
  3. 动态计算:JS通过getBoundingClientRect()获取每个.video-gap的位置和尺寸,转换为遮罩层的相对坐标。
  4. 遮罩生成:将多个镂空区域的rect参数组合到mask属性中,通过mask-composite: exclude排除这些区域,露出下方视频。

纯CSS替代方案(仅适用于固定布局)

如果.video-gap的位置和尺寸是固定不变的,可以直接在CSS中写死mask参数,无需JS:

.video-overlay {
  /* 示例:4个固定位置的镂空区域,根据实际需求修改坐标 */
  mask: rect(0 100% 100% 0), rect(100px 600px 220px 300px), rect(250px 700px 370px 400px), rect(400px 650px 520px 350px), rect(550px 600px 670px 300px);
  mask-composite: exclude;
  -webkit-mask: rect(0 100% 100% 0), rect(100px 600px 220px 300px), rect(250px 700px 370px 400px), rect(400px 650px 520px 350px), rect(550px 600px 670px 300px);
  -webkit-mask-composite: xor;
}

注意:该方案灵活性差,无法适配窗口缩放、文字换行等动态场景,仅适合静态固定布局。


内容的提问来源于stack exchange,提问作者Vladimiro Antipin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 08:29:57