【问题标题】:Hole in overlay with CSS用 CSS 覆盖的孔
【发布时间】:2013-11-27 12:41:09
【问题描述】:

如何在覆盖层中创建一个洞,以便您可以看到实际的网站?

#underground {
  background-color: #725;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

#overlay {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  overflow: hidden;
}

#overlay #center {
  width: 400px;
  height: 200px;
  background-color: #ABD;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -100px;
  margin-left: -200px;
  border-width: 100%;
  border-color: #FFF;
  border-style: solid;
}
<div id="underground"></div>
<div id="overlay">
  <div id="center"></div>
</div>

我希望&lt;div id="center"&gt; 是透明的,以便您可以看到&lt;div id="underground"&gt;。是否可以仅使用 CSS 来执行此操作,还是必须使用一些 JavaScript?

【问题讨论】:

  • 我通过添加outlineoutline-width: 9999pxbackground-color: transparent 解决了这个问题

标签: css overlay


【解决方案1】:

是的,这个效果是可能的。

我会使用传播半径非常大的 css box-shadow。

box-shadow: 0 0 0 9999px rgba(0, 0, 255, 0.2);

.hole {
  position: absolute;
  top: 20px;
  left: 20px;
  width: 200px;
  height: 150px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 255, 0.2);
}
<p>Lorem ipsum dolor sit amet, ocurreret tincidunt philosophia in sea, at pro postea ullamcorper. Mea ei aeque feugiat, cum ut utinam conceptam, in pro partem veritus molestiae. Omnis efficiantur an eum, te mel quot perpetua. Ad duo autem dolore, vocent lucilius te cum, ut duo quem singulis.</p>
<p>Has ex idque repudiandae, an mei munere philosophia. Sale molestie id eos, eam ne blandit adipisci. Ei eam ipsum dissentiunt. Ei vel accusam dolores efficiantur.</p>

<div class="hole"></div>

【讨论】:

  • 这是一个非常优雅的解决方案,imo。希望这是公认的答案。
  • 太棒了!如果必须将阴影限制为某个父元素,只需为该元素添加overflow: hidden
  • 技术太棒了!!应该是正确答案
  • 这很好,但问题是你只能这样做一次。如果您想拥有其中的多个,则顶层将覆盖其他。有没有办法对多个项目做到这一点?
  • 将 box-shadow 属性替换为 outline: 9999px solid rgba(0,0,255,0.2) 具有相同的效果,并且可以说稍微干净一些
【解决方案2】:

感谢 CSS clip-path,现在可以钻取覆盖层的任何内容及其背景图像/背景过滤器甚至指针事件。

为此,我们需要定义一个路径,该路径由第一个覆盖所有视口的矩形组成,然后是一个代表我们孔的内部形状。感谢even-odd 填充规则,只有我们的内部形状实际上是剪切区域的一部分。

path()<basic-shape>应该很容易画出任何形状,但不幸的是,只有Firefox支持clip-path,所以我们必须使用polygon()函数来回退,这意味着我们必须定义每个点都是向量。

虽然对于简单的方孔仍然可读:

.hole {
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0px;
  left: 0px;
  --rect-size: 75px;
  clip-path: polygon( evenodd,
    /* outer rect */
    0 0, /* top - left */
    100% 0, /* top - right */
    100% 100%, /* bottom - right */
    0% 100%, /* bottom - left */
    0 0, /* and top - left again */
    /* do the same with inner rect */
    calc(50% - var(--rect-size) / 2) calc(50% - var(--rect-size) / 2),
    calc(50% + var(--rect-size) / 2) calc(50% - var(--rect-size) / 2),
    calc(50% + var(--rect-size) / 2) calc(50% + var(--rect-size) / 2),
    calc(50% - var(--rect-size) / 2) calc(50% + var(--rect-size) / 2),
    calc(50% - var(--rect-size) / 2) calc(50% - var(--rect-size) / 2)
  );
  /* can cut through all this */
  background-color: rgba(10, 161, 232, 0.3);
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png);
  background-size: 40px;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: center;
}
.hole > p {
  align-self: center;
  font-size: 18px;
  font-weight: bold;
}
.hole-text {
  font-size: 100px;
}
body { color: black; }
<p>Lorem ipsum dolor sit amet, ocurreret tincidunt philosophia in sea, at pro postea ullamcorper. Mea ei aeque feugiat, cum ut utinam conceptam, in pro partem veritus molestiae. Omnis efficiantur an eum, te mel quot perpetua. Ad duo autem dolore, vocent
  lucilius te cum, ut duo quem singulis.</p>
<p>Has ex idque repudiandae, an mei munere philosophia. Sale molestie id eos, eam ne blandit adipisci. Ei eam ipsum dissentiunt. Ei vel accusam dolores efficiantur.</p>

<div class="hole">
  <p>There is an <span class="hole-text">HOLE</span> here</p>
</div>

例如,拥有一个圆的所有点会形成一个更大的规则,所以如果您不需要切穿指针事件,那么mask-image solution by Ed Hinchliffe 可能应该是首选。

无论如何,这里有一个圆的 JS 生成器(如果需要,生成的规则仍然可以硬编码在 CSS 文件中)。

function makeCircleHoleClipPathRule( radius ) {

  const inner_path = [];
  const circumference = Math.PI * radius;
  const step = Math.PI * 2 / circumference;
  // we are coming from top-left corner
  const start_step = circumference * (5 / 8);
  for( let i = start_step; i < circumference + start_step; i++ ) {
    const angle = step * i;
    const x = radius * Math.cos( angle );
    const y = radius * Math.sin( angle );
    const str = `calc( 50% + ${ x }px ) calc( 50% + ${ y }px )`;
    inner_path.push( str );
  }
  // avoid rounding issues
  inner_path.push( inner_path[ 0 ] );

  return `polygon( evenodd,
    /* outer rect */
    0 0,       /* top - left */
    100% 0,    /* top - right */
    100% 100%, /* bottom - right */
    0% 100%,   /* bottom - left */
    0 0,       /* and top - left again */
    ${ inner_path.join( "," ) }
   )`;

}

const hole_elem = document.querySelector( ".hole" );
// set the clip-path rule
hole_elem.style.clipPath = makeCircleHoleClipPathRule( 50 );
.hole {
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0px;
  left: 0px;
  /* clip-path is set by JS */  
  
  background-color: rgba(10, 161, 232, 0.3);
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png);
  background-size: 40px;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: center;
}
.hole > p {
  align-self: center;
  font-size: 18px;
  font-weight: bold;
}
.hole-text {
  font-size: 100px;
}
body { color: black; }
<p>Lorem ipsum dolor sit amet, ocurreret tincidunt philosophia in sea, at pro postea ullamcorper. Mea ei aeque feugiat, cum ut utinam conceptam, in pro partem veritus molestiae. Omnis efficiantur an eum, te mel quot perpetua. Ad duo autem dolore, vocent
  lucilius te cum, ut duo quem singulis.</p>
<p>Has ex idque repudiandae, an mei munere philosophia. Sale molestie id eos, eam ne blandit adipisci. Ei eam ipsum dissentiunt. Ei vel accusam dolores efficiantur.</p>

<div class="hole">
  <p>There is an <span class="hole-text">HOLE</span> here</p>
</div>

对于其他形状,我会让读者自己处理 ;-)

【讨论】:

  • 太棒了!伙计,这个解决方案值得提出自己的问题!
  • 嘿kaiido,我正在尝试设置圆的直径,但calc(10000vw / 25vh) 似乎没有返回任何内容?
  • @oldboy 很不清楚您如何尝试设置此值以及您的期望。对于圆圈,您必须将不同的 radius 值传递给函数。然而这个函数只适用于px 中的半径,因为我们需要确定圆的周长。您可以轻松地使其适用于vhvw 单位(只需将该值乘以innerHeight 或innerWidth 以取回px 中的值),但对于% 甚至em 这样的单位,我们会需要传入目标元素才能计算px 中的正确值。可行,但对于这个简单的演示来说太多了。
  • 嗯,我认为视口单位在幕后转换为 px。我想在没有 JS 的情况下以纯 CSS 的方式来做 :( 无论如何谢谢
  • @oldboy JS 仅用于生成规则,因此您可以仅在 CSS 中生成。但是,对于相对单位,您需要定义您的圆将由多少个点组成。如果您希望可以使用在大多数情况下都可以使用的大数字,我的生成器会尝试使其尽可能优化,但我可以这样做,因为我确实设置了约束(使用px)。跨度>
【解决方案3】:

这在一定程度上是可能的。

选项1:用半透明边框覆盖元素

body, html{
    height:100%;
    width:100%;
    padding:0;
    margin:0;
    background:blue;
}
#overlay{
    height:100%;
    width:100%;
    position:fixed;
    border:50px solid rgba(255,255,255,.3);
    box-sizing:border-box;
    top:0;
    left:0;
}
<div id='overlay'></div>

content content content contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent

选项 2:3x3 网格,中心元素完全透明

body,
html {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  position: fixed;
  background: blue;
}
#overlay {
  display: table;
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
.row {
  display: table-row;
}
.cell {
  display: table-cell;
  opacity: 0.9;
  background: grey;
}
.row:nth-child(2) .cell:nth-child(2) {
  opacity: 0;
}
<div id='overlay'>
  <div class='row'>
    <div class='cell'></div>
    <div class='cell'></div>
    <div class='cell'></div>
  </div>
  <div class='row'>
    <div class='cell'>&nbsp;</div>
    <div class='cell'>&nbsp;</div>
    <div class='cell'>&nbsp;</div>
  </div>
  <div class='row'>
    <div class='cell'></div>
    <div class='cell'></div>
    <div class='cell'></div>
  </div>
</div>

content content content contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent
contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent
contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent

【讨论】:

  • 感谢您的代码,它几乎看起来像我的想法,唯一的问题是整个第二行是透明的,而不仅仅是中间的单元格......
  • 那你为什么不把两边的另外两个单元格也变成透明的呢?
【解决方案4】:

您现在可以在使用 css 剪辑的新 webkit 浏览器中通过相对较好的支持来实现这一点(请参阅here 了解兼容性)。

例如,以下代码将在元素中心(边缘略微羽化)切割一个半径为 100 像素(即 200 像素宽)的孔。

-webkit-mask-image radial-gradient(100px at 50% 50% , transparent 95%, black 100%)

这里有一个codepen 来演示。

【讨论】:

  • 谢谢,这就是我要找的。我怎样才能把“洞”变成正方形?
【解决方案5】:

没有。这是不可能的,在大多数浏览器中都没有。

CSS 屏蔽

如果您只对新浏览器感兴趣,可以使用masking
规格:http://www.w3.org/TR/css-masking/
兼容性:http://caniuse.com/css-masks

边框/轮廓

如果您想创建模拟效果并将它们的颜色设置为transparent,那么您也可以使用borderoutline css 属性,使其看起来很相似。

绝对位置

你也可以使用位置:

<div z-index:20></div>
<div z-index:10>
    <div z-index:30> // top div is over child of this one
</div>

透明度和元素

http://css-tricks.com/non-transparent-elements-inside-transparent-elements/
http://css-tricks.com/examples/NonTransparentOverTransparent/
-- 这不是你想要的,但它可以帮助你:)

【讨论】:

  • 谢谢,我会试试 CSS 掩码,看看能不能让它工作!
【解决方案6】:

这是不可能的。 但无论如何,您可以使用边框技巧:#overlay 本身是透明的,但边框不是。见小提琴:http://jsfiddle.net/qaXRp/2/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 2019-11-22
    • 2021-09-21
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多