Desbordamiento: oculto con radio de borde que no funciona en Safari

5 minutos de lectura

Tengo que hacer un botón con un ::before oculto que se muestra en :hover. Esta animación funciona muy bien en Chrome, IE y Firefox, pero tengo un problema extraño en Safari.

Overflow:hidden funciona pero sin el radio del borde.

Debe ejecutar el violín en safari para ver este problema.

Gracias !

.btn{
  border-radius: 3rem;
  cursor: pointer;
  display: inline-block;
  font-size: 15px;
  font-weight: 400;
  font-family: arial;
  overflow: hidden;
  position: relative;
  padding: 0.8rem 2.5rem;
  text-decoration: none;
  }

.btn-primary{
  background-color: blue;
  border-color: blue;
  color: white;
}

.btn-primary::before{
  background-color: deeppink;
  border-radius: 50%;
  content: '';
  color: white;
  height: 100%;
  left: 100%;
  margin: 0;
  position: absolute;
  top: 0;
  transform-origin: 100% 50%;
  transform: scale3d(1, 1.4, 1);
  transition: all 300ms cubic-bezier(0.7,0,0.9,1);
  width: 20%;
}

.btn-primary:hover::before{
  transform: scale3d(1, 5, 1);
  width: 110%;
  left: -2%;
  z-index: 0;
}

.btn-primary span{
  position: relative;
  z-index: 1;
}
<a href="#" class="btn btn-primary">
  <span>Button primary</span>
</a>

  • ¿Has probado esto en Safari en un sistema Mac o Windows? Mi experiencia con Safari para Windows es que tiene errores excepcionales.

    – Johannes Piontkowitz

    2 de marzo de 2018 a las 9:41

  • Intenté esto en una Mac

    – Víctor Allegret

    2 de marzo de 2018 a las 9:42

  • ¿Obtiene el mismo resultado al agregar etiquetas -webkit- a su css como aquí?

    – Johannes Piontkowitz

    2 de marzo de 2018 a las 9:44


  • Estoy usando autoprefixer en mi proyecto, por lo que agrega automáticamente todas las etiquetas de webkit que necesito

    – Víctor Allegret

    2 de marzo de 2018 a las 9:47

avatar de usuario
desesperación ciega

La respuesta aceptada funciona, pero de hecho elimina la sombra del cuadro. Un comentario que vi en este publicación de github dice que también se puede solucionar creando un nuevo contexto de apilamiento (una especie de mover un elemento a una nueva capa de pintura). Eso se puede lograr con un pequeño truco como

transform: translateZ(0)

En mi caso, tanto overflow como box-shadow funcionan con esta solución. Espero que ayude a alguien más también.

UPD: tal como sugirió Jad Haidar en los comentarios isolation es una propiedad específicamente para trabajar con el contexto de apilamiento:

isolation: isolate;

  • Muchísimas gracias.

    – usuario3587412

    17 de agosto de 2020 a las 15:24

  • ¡Muchas gracias, me tomó semanas encontrar una solución adecuada!

    – señor moe

    22 de septiembre de 2020 a las 21:03

  • salvavidas! Exactamente lo que necesitaba.

    – Jaime

    19 mayo 2021 a las 15:43

  • Otra forma de crear un nuevo contexto de apilamiento es usando isolation: isolate; No es compatible con IE, pero técnicamente es más correcto. developer.mozilla.org/en-US/docs/Web/CSS/isolation

    – Jad Haidar

    28 oct 2021 a las 20:47

  • ¿A qué elemento le estás agregando este estilo?

    – Cully

    13 ene a las 17:30

Así que encontré un pequeño truco para solucionar este problema en https://gist.github.com/ayamflow/b602ab436ac9f05660d9c15190f4fd7b

Simplemente agregue esta línea a su elemento con desbordamiento:

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

Avíseme si alguien encuentra otra solución 🙂

.btn{

  /* Add this line */
  -webkit-mask-image: -webkit-radial-gradient(white, black);

  border-radius: 3rem;
  cursor: pointer;
  display: inline-block;
  font-size: 15px;
  font-weight: 400;
  font-family: arial;
  overflow: hidden;
  position: relative;
  padding: 0.8rem 2.5rem;
  text-decoration: none;
  }

.btn-primary{
  background-color: blue;
  border-color: blue;
  color: white;
}

.btn-primary::before{
  background-color: deeppink;
  border-radius: 50%;
  content: '';
  color: white;
  height: 100%;
  left: 100%;
  margin: 0;
  position: absolute;
  top: 0;
  transform-origin: 100% 50%;
  transform: scale3d(1, 1.4, 1);
  transition: all 300ms cubic-bezier(0.7,0,0.9,1);
  width: 20%;
}

.btn-primary:hover::before{
  transform: scale3d(1, 5, 1);
  width: 110%;
  left: -2%;
  z-index: 0;
}

.btn-primary span{
  position: relative;
  z-index: 1;
}
<a href="#" class="btn btn-primary">
  <span>Button primary</span>
</a>

  • Funcionó como un encanto para mí, ¡gracias! El único inconveniente fue que tuve que mover mi box-shadow a otro div, pero puedo vivir con eso;)

    –Jan Heinzle

    29 oct 2018 a las 15:58


  • Fantástica respuesta.

    – ojsglobal

    22 de mayo de 2019 a las 9:36

  • Gracias. Estoy muy confundido / curioso por qué esto soluciona el problema

    – zyrup

    23 de septiembre de 2019 a las 15:01

  • ¡Gracias por la solución! Este error de desbordamiento en iOS me estaba volviendo loco.

    – Artanis

    6 de marzo de 2020 a las 18:16

will-change: transform; en elemento con overflow: hidden; problema resuelto para mí

  • Sin embargo, cuidado, la propiedad will-change no es compatible con IE ni con las versiones anteriores de Edge.

    – Alex

    19 de febrero de 2020 a las 15:17


  • Si bien este código puede resolver la pregunta, incluyendo una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación y probablemente resulte en más votos a favor. Recuerda que estás respondiendo la pregunta para lectores en el futuro, no solo para la persona que pregunta ahora. Edite su respuesta para agregar explicaciones y dar una indicación de las limitaciones y suposiciones que se aplican.

    – doble pitido

    19 de febrero de 2020 a las 15:31

  • Creo que el quid de todas estas respuestas es que colocan el div en una nueva capa (es decir, transform: translateZ(0)) y por alguna razón eso logra el efecto deseado en Safari

    – Dmitri Minkovski

    29 de febrero de 2020 a las 15:06

avatar de usuario
Dmitri Minkovski

Esto se debe a uno de varios errores no resueltos en WebKit, el motor de renderizado utilizado por Safari:

Como escribe Simon Fraser en el segundo enlace:

Puede solucionarlo en compilaciones recientes haciendo que el elemento con desbordamiento: oculto en un contexto de apilamiento (por ejemplo, posición: relativa, índice z: 0).

Esta es probablemente la solución más simple ya que, a diferencia de algunas de las otras respuestas aquí, no innecesariamente introducir capas de renderizado.

Para mí, agregar un alto z-index ajuste al elemento con el border-radiusfue suficiente para solucionar el problema.

  • ¡Esto también me ayudó! Nunca lo pensé. ¡Gracias!

    – Fabian

    8 abr 2021 a las 8:40

  • Encontré esa configuración z-index: 0 es suficiente, y no debe tener consecuencias.

    – roydukkey

    1 de febrero a las 19:06

  • ¡Esto también me ayudó! Nunca lo pensé. ¡Gracias!

    – Fabian

    8 abr 2021 a las 8:40

  • Encontré esa configuración z-index: 0 es suficiente, y no debe tener consecuencias.

    – roydukkey

    1 de febrero a las 19:06

¿Ha sido útil esta solución?