42 votos

¿Es posible crear esta forma (dos círculos parciales se unieron) con CSS?

Yo estaba tratando de lograr esta frontera para dos divs con CSS:

Desired result

He intentado usando sólo border-radius, pero los dos parciales círculos no son presionadas juntas: http://jsfiddle.net/uwz6L79w/

 .left {
   position: absolute;
   left: 0;
   top: 0;
   width: 100px;
   height: 100px;
   border-width: 4px;
   border-color: black white black black;
   border-style: solid;
   border-radius: 60px
 }
 .right {
   position: absolute;
   left: 104px;
   top: 0;
   width: 100px;
   height: 100px;
   border-width: 4px;
   border-color: black black black white;
   border-style: solid;
   border-radius: 60px;
 }
<div class="left"></div>
<div class="right"></div>

Yo sólo podía aprietan más, pero me gustaría tener un div se superponen la una a la otra como esta: http://jsfiddle.net/uwz6L79w/1/.

.left {
  position: absolute;
  left: 0;
  top: 0;
  width: 100px;
  height: 100px;
  border-width: 4px;
  border-color: black white black black;
  border-style: solid;
  border-radius: 60px
}
.right {
  position: absolute;
  left: 70px;
  top: 0;
  width: 100px;
  height: 100px;
  border-width: 4px;
  border-color: black black black white;
  border-style: solid;
  border-radius: 60px;
  background: #f2f2f2;
}
<div class="left"></div>
<div class="right"></div>

¿Alguien sabe cómo puedo lograr esto sin la necesidad de los divs se superponen?

46voto

Stewartside Puntos 6787

SVG

Esto también es posible el uso de SVG.

La versión SVG es muy corta, ya que principalmente sólo requiere de un Arco de comando para el control de su forma, tamaño y posición.

<svg width="50%" viewbox="0 0 100 50">
  <path d="M50,35 
           a20,20 0 1,0 0,-20 
           a20,20 0 1,0 0,20z" 
        fill="white" 
        stroke="black">
  </path>
</svg>

SVG stands para Gráficos Vectoriales Escalables. El navegador web vistas como una imagen, pero usted puede añadir el texto y HTML normal de los elementos dentro de un SVG.

Es bien soportado en todos los navegadores como se ve aquí: CanIUse

41voto

Harry Puntos 10265

El Uso De Fronteras: Recomendado

Usted puede hacerlo de la misma manera como en el segundo fragmento y utilizar el posicionamiento como en el siguiente fragmento de código para evitar los dos div elementos de la superposición. Aquí los círculos son producidos por los pseudo-elementos y la superposición de la parte es cortar con overflow: hidden de sus padres.

Una cosa a tener en cuenta aquí es que cualquier efecto de hover debe ser añadido en la pseudo-elementos y no el de los padres de los elementos. Esto es porque si el :hover está conectado a los padres, a continuación, se pondrían en marcha, incluso cuando se pasa el mouse fuera del círculo (porque el padre está siendo un cuadrado).

De las tres soluciones proporcionadas en esta respuesta, este es el que tiene el mejor navegador de apoyo y de trabajar incluso en IE8. Por lo tanto, esta es la recomendada.

.left, .right {
  position: relative;
  float: left;
  height: 200px;
  width: 200px;
  /* border: 1px solid; uncomment to see that they aren't overlapped */
  overflow: hidden;
}
.left:after, .right:after {
  position: absolute;
  content: '';
  height: calc(100% - 12px); /* 12px because of 6px border on either side */
  width: calc(100% - 12px); /* 12px because of 6px border on either side */
  border-radius: 50%;
  border: 6px solid gray;
}
.left:after { right: -20px; }
.right:after { left: -20px; }
<div class='left'></div>
<div class='right'></div>

El Uso De Gradientes Radiales:

Si usted no desea utilizar el pseudo-elementos y un overflow: hidden sobre el padre entonces también se puede hacer uso de radial-gradient imágenes de fondo para producir el círculo y la posición, de tal modo que terminan produciendo el efecto deseado. A continuación es un fragmento del ejemplo de este enfoque.

La desventaja de este enfoque es la baja compatibilidad del navegador con la radial-gradient. No iba a funcionar en IE9 y menor. Además, los círculos producido por gradientes radiales son generalmente irregulares (aristas) y cuando queremos modificar el color de posiciones de parada para hacerla más suave, da un poco borrosa la apariencia.

.left, .right {
  float: left;
  height: 200px;
  width: 200px;
  /*border: 1px solid;  uncomment to see that they aren't overlapped */
}

/* generally the below code should be enough to produce 6px thick circular border
.left {
  background: radial-gradient(circle at 70% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px));
}
.right {
  background: radial-gradient(circle at 30% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px));
}
*/

/* but it produces jagged edges and so we can change the color stops a bit like below
   this produces smoother circles but the disadvantage is that they'd look a bit blurred */
.left {
  background: radial-gradient(circle at 70% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px));
}
.right {
  background: radial-gradient(circle at 30% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='left'></div>
<div class='right'></div>

El uso de Rutas de Clip (CSS/SVG):

Otro enfoque que podría ser utilizado es el uso de clip-path. La ventaja de este enfoque es que el hover efectos se activa sólo cuando el cursor se encuentra dentro del círculo (como puede verse en el fragmento). Esto es debido a que las partes innecesarias se recortan.

La desventaja es, nuevamente, la pobre compatibilidad del navegador. Versión de CSS de clip-path sólo se admite en Webkit, pero no en Firefox, IE, mientras que la versión SVG (usando inline SVG) es compatible en Webkit, Firefox pero no en IE.

.left, .right {
  float: left;
  height: 200px;
  width: 200px;
  border-radius: 50%;
  border: 6px solid gray;
}

/* CSS Clip Path - not supported by FF and IE */
.left.css-clip {
  clip-path: polygon(0% 0%, 80% 0%, 80% 100%, 0% 100%);
}
.right.css-clip {
  margin-left: -86px;  /* 20% width * 2 (which is the clipped space) - border width */
  clip-path: polygon(20% 0%, 100% 0%, 100% 100%, 20% 100%);
}

/* SVG Clip Path - supported by Webkit, FF but not IE */
.left.svg-clip {
  clip-path: url(#clipper-left);
}
.right.svg-clip {
  margin-left: -86px;  /* 20% width * 2 (which is the clipped space) - border width */
  clip-path: url(#clipper-right);
}

/* Just for demo */

h3{ clear: both; }
.left:hover, .right:hover{ background: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<h3>CSS Clip Path</h3>
<div class='left css-clip'></div>
<div class='right css-clip'></div>

<h3>SVG Clip Path</h3>
<div class='left svg-clip'></div>
<div class='right svg-clip'></div>

<!-- Inline SVG for SVG Clip Path -->
<svg width='0' height='0'>
  <defs>
    <clipPath id='clipper-left' clipPathUnits='objectBoundingBox'>
      <path d='M0,0 .8,0 .8,1 0,1z' />
      </clipPath>
    <clipPath id='clipper-right' clipPathUnits='objectBoundingBox'>
      <path d='M.2,0 1,0 1,1 .2,1z' />
      </clipPath>
    </defs>
  </svg>

12voto

Rounin Puntos 4260

He aquí una solución con un solo <div>.

  1. .shape es un círculo transparente con un 10px borde rojo.
  2. .shape::before es un blanco opaco círculo con un 10px borde rojo.
  3. .shape::after es un blanco opaco círculo (sin borde).

.shape {
margin: 6px auto;
}

.shape, .shape::before, .shape::after {
display: block;
position: relative;
width: 160px;
height: 160px;
border-radius: 160px;
}

.shape, .shape::before {
border: 10px solid #f00;
}

.shape::before, .shape::after {
content: "";
background-color: rgba(255, 255, 255, 1);
}

.shape::before {
top: -10px;
left: -150px;
}

.shape::after {
top: -180px;
}
<div class="shape">
</div>

8voto

Jeff Batterton Puntos 81

Aquí está un pequeño ejemplo que me ocurrió. No lo he probado en diferentes navegadores pero debe ser bastante bien soportado.

HTML:

<div class="one"></div>
<div class="two"></div>

CSS:

div {
  background: #fff;
  border-radius: 50%;
  float: left;
  height: 100px;
  position: relative;
  width: 100px;
}

.one:after,
.two:after{
  /* adjust this to set the border color */
  background: #666;
  border-radius: 50%;
  content: "";
  position: absolute;
  z-index: -1;
  /* adjust these to set the border width */
  top: -5px;
  right: -5px;
  bottom: -5px;
  left: -5px;
}

.two {
  /* adjust this to set the overlap of the circles */
  margin-left: -20px;
}

Demostración en vivo

2voto

Rounin Puntos 4260

Estoy volviendo a esta pregunta (después de 6 semanas), simplemente porque la parte superior de votación de respuesta que despertó mi curiosidad académica en svg, que rara vez he encontrado y nunca se toman el tiempo para aprender.

Desde ahora estoy aprendiendo svg, esta pregunta (que me envió en mi búsqueda para aprender en primer lugar), me pareció el ideal desafío contra el que probar algunas nuevas habilidades.

Así que aquí es una alternativa svg solución, el equivalente de mi sola <div> css solución anterior:

svg {
width: 310px;
height: 180px;
}

svg circle {
stroke: rgb(255,0,0);
stroke-width: 10;
fill: rgb(255,255,255);
}

svg circle:nth-of-type(3) {
stroke: rgb(255,255,255);
}
<svg viewbox="0 0 310 180">
<circle cx="90" cy="90" r="80" />
<circle cx="220" cy="90" r="80" />
<circle cx="90" cy="90" r="70" />
</svg>

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X