【问题标题】:Transparent hollow or cut out circle透明的空心或切出的圆圈
【发布时间】:2012-01-07 08:43:33
【问题描述】:

是否可以仅使用 CSS切出一个空心圆

这是我们都可以做到的:

但是我们可以这样做吗?

圆圈必须是空心透明的。因此,通过在div 上放置一个纯色圆圈并不能解决问题。

【问题讨论】:

  • 通过'only CSS'大概你更喜欢不使用图片/image-masks?
  • 我想这样做,但使用带有背景图像的元素,而不仅仅是纯色。这可能吗?

标签: css svg transparency css-shapes


【解决方案1】:

您可以使用 2 种不同的技术实现透明切割圆

1.SVG

以下示例使用inline svg。第一个 sn-p 使用mask element 切出透明圆,第二个空心圆使用path element。圆圈由 2 arc commands 组成:

带遮罩元素:

body{background:url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
<svg viewbox="0 0 100 50" width="100%">
  <defs>
    <mask id="mask" x="0" y="0" width="80" height="30">
      <rect x="5" y="5" width="90" height="40" fill="#fff"/>
      <circle cx="50" cy="25" r="15" />
    </mask>
  </defs>
  <rect x="0" y="0" width="100" height="50" mask="url(#mask)" fill-opacity="0.7"/>    
</svg>

只有一个路径元素:

body{background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
svg{
  display:block;
  width:70%;
  height:auto;
  margin:0 auto;
}
path{
  transition:fill .5s;
  fill:#E3DFD2;
}
path:hover{
  fill:pink;
}
<svg viewbox="-10 -1 30 12">
  <path d="M-10 -1 H30 V12 H-10z M 5 5 m -5, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0z"/>
</svg>

在这种情况下使用 SVG 的主要优点是:

  • 更短的代码
  • 您可以轻松地使用图像或渐变来填充圆形蒙版
  • 保持形状的边界并仅在与蒙版相关的填充上触发鼠标事件(悬停在示例中的透明剪切圆

2。 CSS 仅使用 BOX-SHADOWS

使用overflow:hidden; 创建一个div,并在其中创建一个带有border-radius 的圆形伪元素。给它一个巨大的盒子阴影并且没有背景:

div{
    position:relative;
    width:500px; height:200px;
    margin:0 auto;
    overflow:hidden;
}
div:after{
    content:'';
    position:absolute;
    left:175px; top:25px;
    border-radius:100%;
    width:150px; height:150px;
    box-shadow: 0px 0px 0px 2000px #E3DFD2;
}

body{background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
&lt;div&gt;&lt;/div&gt;

对 box-shadows 的浏览器支持是 IE9+,请参阅 canIuse

同样的方法是使用边框而不是框阴影。如果您需要支持不支持像 IE8 这样的 box-shadows 的浏览器,这很有趣。技术是一样的,但是你需要用 top 和 left 值来补偿,以使圆保持在 div 的中心:

body{
    background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');
    background-size:cover;
}
div{
    position:relative;
    width:500px; height:200px;
    margin:0 auto;
    overflow:hidden;
}
div:after{
    content:'';
    position:absolute;
    left:-325px; top:-475px;
    border-radius:100%;
    width:150px; height:150px;
    border:500px solid #E3DFD2;
}
&lt;div&gt;&lt;/div&gt;

【讨论】:

  • 非常感谢你的 box-shadow,天哪,我怎么没想到那个! :/我知道可以使用一些超出边界的圆圈来完成。但你成功了!
  • 注意如果在 Safari 中使用 box-shadow .. 它们是不可见的,但边框是可见的。请改用它们。
【解决方案2】:

可以使用radial gradient 背景和指针事件来完成(允许鼠标通过圆圈层进行交互,例如文本选择)。这是a demo page 和截图:

这就是它的代码:

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<style type="text/css" media="screen">
body {
  margin: 0;
  padding: 0;
}

.underneath {
  padding: 0;
  margin: 265px 0 0 0;
  width: 600px;
}

.overlay {
  top: 0;
  left: 0;
  position: absolute;
  width: 600px;
  height: 600px;
  background: -moz-radial-gradient(transparent 150px, rgba(0,0,0,1) 150px);
  background: -webkit-radial-gradient(transparent 150px, rgba(0,0,0,1) 150px);
  background: -ms-radial-gradient(transparent 150px, rgba(0,0,0,1) 150px);
  background: -o-radial-gradient(transparent 150px, rgba(0,0,0,1) 150px);
  pointer-events: none; /* send mouse events beneath this layer */
}
</style>
</head>
<body>

<p class="underneath">
  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
  incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
  nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
  Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
  eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt
  in culpa qui officia deserunt mollit anim id est laborum.
</p>

<div class="overlay"></div>

</body>
</html>

【讨论】:

【解决方案3】:

参考 web-tiki 的回答,我想补充一点,您始终可以使用 translate(-50%,-50%) 将 div 居中,因此使用 border-property 没有问题,它具有更好的浏览器支持。

div{
    position:relative;
    width:500px; 
    height:200px;
    margin:0 auto;
    overflow:hidden;
}
div:after{
    content:'';
    position:absolute;
    left:50%;
    top: 50%;
    transform: translate(-50%,-50%);
    border-radius:50%;
    width:150px; height:150px;
    border: 1000px solid rebeccapurple;
}

body{background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
&lt;div&gt;&lt;/div&gt;

您可以通过这种技术获得真正的创意:

document.addEventListener( "DOMContentLoaded", function(){ 
	setInterval(function(){
		if(document.getElementById("moving").style.height === "500px"){
			document.getElementById("moving").style.height = "0px";
		} else {		
			document.getElementById("moving").style.height = "500px";
		}
	}, 2000);
});
#container {
	width: 500px;
	margin: 0 auto;
	border: 1px solid black;
	overflow:hidden;
	position: relative;
}


#circle{
    position:relative;
    height:150px;
    margin:0 auto;
	clear:left;
	overflow:hidden;
}
#circle::before, #circle::after {
    content:'';
    border-radius:50%;
	position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}
#circle::before {
    height: 140px;
    width: 140px;
    background: rebeccapurple;
}
#circle::after{
    width:150px; 
	height:150px;
    border: 2000px solid rebeccapurple;
}

#line {
	margin: 0 auto;
	width: 6px;
	height: 200px;
	position: relative;
}
#line::before, #line::after {
	content: " ";
	background-color: rebeccapurple;
    height: 200px;
	width:2000px;
	position:absolute;
}
#line::before {
	right: 100%;
}
#line::after { 
	left: 100%;
}

#moving {
	height: 0px;
    width: 100%;
    background: blue;
    transition: 2s height;
    position: absolute;
    top: 0px;
    z-index: -1;
}
body{
	background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;
}
<div id="container">
	<div id="circle"></div>
	<div id="line"></div> 
    <div id="circle"></div>
    <div id="moving"></div>
</div>

【讨论】:

  • 对于像我这样挣扎的人 - div:after 需要 box-sizing: content-box;有时由 css 框架设置为边框。
【解决方案4】:

关于“Pius Nyakoojo”中的“方法 1”,稍作改进(见下文)它会起作用。我个人认为这是最简单的解决方案:

<html>
<!-- Assuming the stuff to mask is a 100 pixel square -->
<style>
.mask {
    position: absolute;
    top: -50px;                     /* minus half the div size */
    left: -50px;                    /* minus half the div size */
    width: 100px;                   /* the div size */
    height: 100px;                  /* the div size */
    background-color: transparent;
    border-radius: 100px;           /* the div size */
    border: 50px solid white;       /* half the div size */
    pointer-events: none;           /* send mouse events beneath this layer */
}

.stuff {
    position: absolute;
    width: 100px;                   /* the div size */
    height: 100px;                  /* the div size */
    overflow: hidden;               /* hide the excess of the mask border */
    background-color: #CCC;
}
</style>
<body>
    <div class="stuff">
        <div class="mask"></div>
        blah blah blah blah blah
        blah blah blah blah blah
        blah blah blah blah blah
    </div>
</body>
</html>

【讨论】:

    【解决方案5】:

    方法1- 首选

    <div class="circle"></div>
    
    $radius: 50px;
    $thickness: 5px;
    
    .circle {
        width: $radius;
        height: $radius;
        background-color: transparent;
        border-radius: $radius;
        border: $thickness solid gray;
    }
    

    方法二

    <div class="circle"></div>
    
    $radius: 50px;
    $thickness: 5px;
    
    .circle {
      width: $radius;
      height: $radius;
    }
    
    .circle::before, .circle::after {
      margin: -2px 0;
    }
    .circle::before {
        content: '';
        display: inline-block;
        width: $radius;
        height: calc(#{$radius} / 2);
        background-color: transparent;
        border-top-left-radius: calc(#{$radius} / 2);
        border-top-right-radius: calc(#{$radius} / 2);
        border: $thickness solid gray;
        border-bottom: 0;
    
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
    }
    
    .circle::after {
      content: '';
      display: inline-block;
      width: $radius;
      height: calc(#{$radius} / 2);
      background-color: transparent;
      border-bottom-left-radius: calc(#{$radius} / 2);
      border-bottom-right-radius: calc(#{$radius} / 2);
      border: $thickness solid gray;
      border-top: 0;
    
      -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
      box-sizing: border-box;
    }
    

    【讨论】:

    • 方法1不只是创建一个边框吗?圆圈外的整个区域都应该涂上颜色。不仅仅是边界。
    【解决方案6】:

    您可以使用 css 蒙版和额外的 svg 图片来做到这一点。
    Although browser support is weak

    body {
      background: url(https://data.whicdn.com/images/50959200/original.jpg);
      background-size: cover;
      background-position: center;
    }
    
    .circle {
      width: 150px;
      height: 150px;
      background: black;
      border-radius: 50%;
      -webkit-mask: url(https://svgshare.com/i/GLf.svg);
      -webkit-mask-size: 125%; /* change it */
      -webkit-mask-position: center;
      margin: 20px auto;
    }
    &lt;div class="circle"&gt;&lt;/div&gt;

    【讨论】:

      【解决方案7】:

      我们可以使用radial-gradientmask 来做到这一点。使用单个 div,没有伪元素。

      * {
        box-sizing: border-box;
      }
      
      html,
      body {
        height: 100%;
      }
      
      body {
        margin: 0;
        background-image: url(https://picsum.photos/id/1060/720/1280);
        background-size: cover;
      }
      
      .a {
        /* this is flexible. you can change */
        --circle-radius: 100px;
        height: 100%;
        width: 100%;
        --mask: radial-gradient(circle farthest-side at center center, transparent var(--circle-radius), #000 calc(var(--circle-radius) + 2px) 100%) 50% 50%/100% 100% no-repeat;
        -webkit-mask: var(--mask);
                mask: var(--mask);
        background: #000;
      }
      &lt;div class="a"&gt;&lt;/div&gt;

      圆半径也可以是百分比值:

      * {
        box-sizing: border-box;
      }
      
      html,
      body {
        height: 100%;
      }
      
      body {
        margin: 0;
        padding: 30px;
        background-image: url(https://picsum.photos/id/1060/720/1280);
        background-size: cover;
      }
      
      .a {
        --circle-radius: 20%; /* changed as percent value */
        
        height: 100%;
        width: 100%;
        --mask: radial-gradient(circle farthest-side at center center, transparent var(--circle-radius), #000 calc(var(--circle-radius) + 2px) 100%) 50% 50%/100% 100% no-repeat;
        -webkit-mask: var(--mask);
                mask: var(--mask);
        background: rgba(0, 0, 0, .8);
      }
      &lt;div class="a"&gt;&lt;/div&gt;

      另一个想法:

      * {
        box-sizing: border-box;
      }
      
      html,
      body {
        height: 100%;
      }
      
      body {
        margin: 0;
        background-image: url(https://picsum.photos/id/1060/720/1280);
        background-size: cover;
      }
      
      .a {
        --circle-radius: 100px;
        --border-width: 30px;
        
        height: 100%;
        width: 100%;
        --mask: radial-gradient(circle farthest-side at center center, transparent var(--circle-radius), #000 calc(var(--circle-radius) + 2px) calc(var(--circle-radius) + 2px + var(--border-width)), transparent calc(var(--circle-radius) + 2px + var(--border-width) + 2px) 100%) 50% 50%/100% 100% no-repeat;
        -webkit-mask: var(--mask);
                mask: var(--mask);
        background: #000;
      }
      &lt;div class="a"&gt;&lt;/div&gt;

      反向:

      * {
        box-sizing: border-box;
      }
      
      html,
      body {
        height: 100%;
      }
      
      body {
        margin: 0;
        background-image: url(https://picsum.photos/id/1060/720/1280);
        background-size: cover;
      }
      
      .a {
        --circle-radius: 100px;
        --border-width: 30px;
        
        height: 100%;
        width: 100%;
        --mask: radial-gradient(circle farthest-side at center center, #000 var(--circle-radius), transparent calc(var(--circle-radius) + 2px) calc(var(--circle-radius) + 2px + var(--border-width)), #000 calc(var(--circle-radius) + 2px + var(--border-width) + 2px) 100%) 50% 50%/100% 100% no-repeat;
        -webkit-mask: var(--mask);
                mask: var(--mask);
        background: #000;
      }
      &lt;div class="a"&gt;&lt;/div&gt;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-26
        • 2017-04-20
        • 2016-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多