web-dev-qa-db-fra.com

Cercle creux ou découpé transparent

Est-il possible de découper un cercle creux en utilisant uniquement [~ # ~] css [~ # ~] ?

Nous pouvons tous le faire:

normal CSS circle

Mais pouvons-nous faire cela?

transparent hollow circle in a div

Le le cercle doit être creux et transparent. Ainsi, le problème n'est pas résolu en plaçant un cercle de couleur unie sur un div.

52
chris

Vous pouvez réaliser un cercle de découpe transparent avec 2 techniques différentes:

1.SVG

Les exemples suivants utilisent un svg en ligne . Le premier extrait utilise le élément de masque pour découper le cercle transparent et le deuxième cercle creux est fait avec un élément de chemin . Le cercle est fait avec 2 commandes d'arc :

Avec l'élément mask:

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>

Avec un élément de chemin:

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>

Les principaux avantages de l'utilisation de SVG dans ce cas sont:

  • Code abrégé
  • Vous pouvez facilement utiliser une image ou un dégradé pour remplir le masque de cercle
  • maintenir les limites de la forme et déclencher des envies de souris uniquement sur le remplissage en respectant le masque ( survoler le cercle transparent découpé dans l'exemple)

transparent cut out circle

2. CSS utilisant uniquement BOX-SHADOWS

Créez un div avec overflow:hidden; et un pseudo-élément rond à l'intérieur avec border-radius. Donnez-lui une énorme boîte-ombre et aucun fond:

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;}
<div></div>

La prise en charge du navigateur pour les zones d'ombres est IE9 + voir canIuse

La même approche consisterait à utiliser la bordure au lieu des ombres en boîte. Il est intéressant si vous devez prendre en charge des borowsers qui ne prennent pas en charge les ombres de boîte comme IE8. La technique est la même, mais vous devez compenser avec les valeurs supérieure et gauche pour garder le cercle au centre de la division:

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;
}
<div></div>
58
web-tiki

Cela peut être fait en utilisant un gradient radial arrière-plan et des événements de pointeur (pour permettre l'interaction de la souris derrière à travers la couche de cercle, par exemple la sélection de texte). Voici une page de démonstration et une capture d'écran:

enter image description here

Et ce serait le code pour cela:

<!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>
25
Ionuț G. Stan

En référence à la réponse de web-tiki, je voudrais ajouter que vous pouvez toujours centrer un div avec translate(-50%,-50%), donc ce ne serait pas un problème d'utiliser la propriété border-, qui a mieux prise en charge du navigateur.

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;}
<div></div>

Vous pouvez devenir vraiment créatif avec cette technique:

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>
15
doABarrelRoll721

En ce qui concerne la "Méthode 1" de "Pius Nyakoojo", avec une amélioration mineure (voir ci-dessous), cela fonctionnerait. Je pense personnellement que c'est la solution la plus simple:

screenshot

<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
Andrew

Méthode 1- préférée

<div class="circle"></div>
$radius: 50px;
$thickness: 5px;

.circle {
    width: $radius;
    height: $radius;
    background-color: transparent;
    border-radius: $radius;
    border: $thickness solid gray;
}

Méthode 2

<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
Pius Nyakoojo