Cómo hacer que las esquinas redondeadas CSS3 oculten el desbordamiento en Chrome / Opera

147

Necesito esquinas redondeadas en un div padre para enmascarar el contenido de su niño. overflow: hiddenfunciona en situaciones simples, pero se rompe en los navegadores basados ​​en webkit y Opera cuando el padre está posicionado de forma relativa o absoluta.

Esto funciona en Firefox e IE9:

CSS

#wrapper {
  width: 300px;
  height: 300px;
  border-radius: 100px;
  overflow: hidden;
  position: absolute;
}

#box {
  width: 300px;
  height: 300px;
  background-color: #cde;
}

HTML

<div id="wrapper">
  <div id="box"></div>
</div>

Ejemplo en JSFiddle

¡Gracias por la ayuda!

ACTUALIZACIÓN: El error que causa este problema se ha solucionado desde Chrome. Sin embargo, no he vuelto a probar Opera o Safari.

jmotes
fuente

Respuestas:

183

Encontré otra solución para este problema. Esto parece otro error en WebKit (o probablemente Chrome), pero funciona. Todo lo que necesita hacer es agregar una máscara CSS de WebKit al elemento #wrapper. Puede usar una imagen png de un solo píxel e incluso incluirla en el CSS para guardar una solicitud HTTP.

#wrapper {
width: 300px; height: 300px;
border-radius: 100px;
overflow: hidden;
position: absolute; /* this breaks the overflow:hidden in Chrome/Opera */

/* this fixes the overflow:hidden in Chrome */
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
}

#box {
width: 300px; height: 300px;
background-color: #cde;
}​

JSFiddle Ejemplo

Graycrow
fuente
3
gracias por esta solucion ¡Lo probé en safari hoy (v6.0.2) y funcionó para mí allí!
billythetalented
66
Sin embargo, esto romperá cualquier sombra en el elemento.
Jack James
1
Esto también funciona en envoltorios con niños absolutamente posicionados, donde la otra solución aquí no lo hace. ¡Agradable!
Dan Tello
2
usando Chrome 42.0.2311.90 (64 bits), y esta solución aún es necesaria ... ¡gracias!
Simon
2
Sus soluciones eliminan las sombras del elemento padre.
ABDeveloper
106

Agregue un índice z a su elemento de radio de borde y enmascarará las cosas dentro de él.

Jackolai
fuente
@Sifu: simplemente estás equivocado. Por alguna razón, agregar un índice z como se sugirió resolvió este problema exacto para mí (en la versión actual de Chrome), y esta es una solución más simple y más general que la respuesta principal.
Nick F
77
@simon: recuerde que para que el índice z tenga efecto, se deben cumplir ciertas condiciones (por ejemplo, se debe establecer la posición). Ver aquí para más detalles.
Nick F
@NickF: fue un error en Chrome (-ium); -webkit-mask-image: -webkit-radial-gradient(circle, white, black);fue una solución efectiva, pero, afortunadamente, el error se solucionó en la actualización más reciente que recibí en Chrome.
Simon
z-index 1 al contenedor. z-index -1 al elemento absoluto lo resolvió para mí.
aZtraL-EnForceR
Este me funcionó. La solución de envoltura anterior no lo hace.
Ruwen
58

Sin importarles a todos, logré resolver el problema agregando un div adicional entre el contenedor y la caja.

CSS

#wrapper {
    position: absolute;
}

#middle {
    border-radius: 100px;
    overflow: hidden; 
}

#box {
    width: 300px; height: 300px;
    background-color: #cde;
}

HTML

<div id="wrapper">
    <div id="middle">
        <div id="box"></div>
    </div>
</div>

¡Gracias a todos los que ayudaron!

http://jsfiddle.net/5fwjp/

jmotes
fuente
12
Esto funciona porque los elementos posicionados no recortan su contenido a su radio de borde en Webkit. Esta capa adicional simplemente hace que el div con radio de borde NO esté posicionado, y simplemente se sienta dentro de un elemento posicionado.
Daniel Beardsley
9
¿Sabrá por casualidad si se trata de un error / comportamiento previsto?
jmotes
44
+1 voto al error ... Cuando tiene una galería de imágenes que genera automáticamente los divs y establece la posición en absoluta, entonces esta "característica" realmente sux ...
inf3rno
@RunLoop Acabo de probar el jsfiddle en Safari 7.1 y funciona bien. ¿Puedes ser más específico sobre lo que no funciona?
jmotes
1
Nuestro colega el diseñador gráfico realmente "descubrió" esto 20 segundos antes de encontrar esta respuesta: D
Pere
18

opacidad: 0.99; en el contenedor resuelve el error del webkit

flavi1
fuente
2
transform: translateY(0);es una alternativa que logra el mismo resultado sin interferir con la representación visual del objeto (a menos que esté utilizando la perspectiva).
kontur
15

Parece que este funciona:

.wrap {
    -webkit-transform: translateZ(0);
    -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
}

http://jsfiddle.net/qWdf6/82/

nakrill
fuente
44
transform: translateZ(0)es suficiente para mi
kalvn
Tenga en cuenta que esto (en particular translateZ) habilitará implícitamente la aceleración de hardware para sus elementos, lo que abre una nueva lata de gusanos en algunos casos, lamentablemente.
doldt
transform: translateZ(0)También funcionó para mí. En mi caso, no es una mala idea que este artículo sea acelerado por hardware.
Sebastien Lorber
9

Compatible con el último Chrome, Opera y Safari, puedes hacer esto:

-webkit-clip-path: inset(0 0 0 0 round 100px);
clip-path: inset(0 0 0 0 round 100px);

¡Definitivamente deberías consultar la herramienta http://bennettfeely.com/clippy/ !

antoni
fuente
Creo que puede acortar esta ruta de clip aún más : inserción (0%); ... solo tener un camino de clip parece ser el truco :-)
Jakob E
Guau. Es la respuesta perfecta.
Shashank Bhatt
4

cambie la opacidad del elemento primario con el borde y esto reorganizará los elementos apilados. Esto funcionó milagrosamente para mí después de horas de investigación e intentos fallidos. Fue tan simple como agregar una opacidad de 0.99 para reorganizar este proceso de pintura de los navegadores. Echa un vistazo a http://philipwalton.com/articles/what-no-one-told-you-about-z-index/

Rami Awar
fuente
3

En cuanto a mí, ninguna de las soluciones funcionó bien, solo usando:

-webkit-mask-image: -webkit-radial-gradient(circle, white, black);

en el elemento contenedor hizo el trabajo.

Aquí el ejemplo: http://jsfiddle.net/gpawlik/qWdf6/74/

Grzegorz Pawlik
fuente
2

basado en la excelente respuesta de graycrow ...

Aquí hay un ejemplo más real del mundo que tiene dos divs ciculares con algún contenido de relleno. Reemplacé el fondo png codificado con solo un valor hexadecimal, es decir

-=-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);

se reemplaza con

-webkit-mask-image:#fff;

Ver este JSFiddle ... http://jsfiddle.net/hqLkA/

gts101
fuente
1

Aquí mira cómo lo hice; Jsfiddle

Con el Código que puse, logré que funcionara en Webkit (Chrome / Safari) y Firefox. No sé si funciona con la última versión de Opera. Sí, funciona con la última versión de Opera.

#wrapper {
  width: 300px; height: 300px;
  border-radius: 100px;
  overflow: hidden;
  position: absolute; /* this breaks the overflow:hidden in Chrome/Opera */
}

#box {
  width: 300px; height: 300px;
  background-color: #cde;
  border-radius: 100px;
  -webkit-border-radius: 100px;
  -moz-border-radius: 100px;
  -o-border-radius: 100px;
}
Laberinto
fuente
Por qué molestarse en poner el border-radiusenvoltorio en esa situación, obtienes el mismo resultado con solo encenderlo #box. Además, si el #boxradio del borde es solo para arreglar WebKit, podría incluir la -webkit-propiedad allí.
robertc
Laberinto, esto podría funcionar en algunas situaciones, pero en mi caso estoy buscando una solución que no transforme la forma de la caja (y el envoltorio todavía funciona como una máscara). Mi ejemplo fue muy simplificado, pero estoy tratando de usar el contenedor para ocultar la sombra de la caja (usando relleno en el contenedor para hacer visibles solo los bordes de las sombras que quiero).
jmotes
1
Gracias por la ayuda, aunque Maze! Su solución me ayudó a pensar sobre el problema de manera más crítica. Por cierto, puedes ignorar la edición que hice en tu publicación. Tenía la intención de hacerlo por mi cuenta. Lo siento :)
jmotes
@ user480837 No hay problema amigo, me alegro de haber sido de ayuda. :)
Laberinto
1
@Maze Eso no funcionará si se aplica un borde de cualquier tipo: jsfiddle.net/ptW85/228
antitóxico
1

Intenté cada respuesta pero sin éxito. Después de algunas horas de investigación, encontré una solución para este problema. El uso de estas propiedades en su clase no permitirá que los elementos div desborden el contenedor.

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}
Samin
fuente
0

Si está buscando crear una máscara para una imagen y colocar la imagen dentro del contenedor, no establezca el atributo 'position: absolute'. Todo lo que tiene que hacer es cambiar el margen izquierdo y el margen derecho. Chrome / Opera se adherirá al desbordamiento: reglas ocultas y de radio de borde.

// Breaks in Chrome/Opera.
    .container {
        overflow: hidden;
        border-radius: 50%;
        img {
            position: absolute;
            left: 20px;
            right: 20px;
        }
    }

// Works in Chrome/Opera.
    .container {
        overflow: hidden;
        border-radius: 50%;
        img {
            margin-left: 20px;
            margin-right: 20px;
        }
    }
usuario6039997
fuente