Como fazer com que os cantos arredondados CSS3 ocultem o estouro no Chrome / Opera

147

Preciso de cantos arredondados em uma div pai para mascarar o conteúdo de seus filhos. overflow: hiddenfunciona em situações simples, mas interrompe os navegadores baseados no webkit e o Opera quando o pai está posicionado relativamente ou absolutamente.

Isso funciona no 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>

Exemplo no JSFiddle

Obrigado pela ajuda!

ATUALIZAÇÃO: O bug que causou esse problema foi corrigido no Chrome. No entanto, não testei novamente o Opera ou o Safari.

jmotes
fonte

Respostas:

183

Encontrei outra solução para esse problema. Parece outro bug no WebKit (ou provavelmente Chrome), mas funciona. Tudo que você precisa fazer - é adicionar uma máscara CSS do WebKit ao elemento #wrapper. Você pode usar uma imagem png de pixel único e até incluí-la no CSS para salvar uma solicitação 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;
}​

Exemplo JSFiddle

Graycrow
fonte
3
obrigado por esta correção. tentei no safari hoje (v6.0.2) e funcionou para mim lá!
billythetalented
6
isso quebrará qualquer sombra no elemento no entanto.
Jack James
1
Isso funciona também em invólucros com crianças absolutamente posicionadas, onde a outra solução aqui não funciona. Agradável!
Dan Tello
2
usando o Chrome 42.0.2311.90 (64 bits) e essa correção ainda é necessária ... obrigado!
19615 Simon
2
suas soluções remove sombras do elemento pai.
ABDeveloper
105

Adicione um índice z ao seu item com raio de borda e ele ocultará as coisas dentro dele.

Jackolai
fonte
@Sifu: você está simplesmente errado. Por qualquer motivo, a adição de um índice z, conforme sugerido, resolveu esse problema exato para mim (na versão atual do Chrome), e essa é uma solução mais simples e geral do que a resposta principal.
Nick F
7
@ Simon: lembre-se de que, para o z-index ter efeito, certas condições precisam ser atendidas (por exemplo, a posição precisa ser definida). Veja aqui os detalhes.
Nick F
@ NickF - foi um bug no Chrome (-ium); -webkit-mask-image: -webkit-radial-gradient(circle, white, black);foi uma solução eficaz, mas, felizmente, o bug foi corrigido na atualização mais recente que recebi no Chrome.
Simon
z-index 1 para contêiner. O z-index -1 para o elemento absoluto resolveu isso para mim.
aZtraL-EnForceR 08/07/2015
Este funcionou para mim. A solução de invólucro acima não.
Ruwen 17/07/2015
58

Deixa pra lá, consegui resolver o problema adicionando uma div adicional entre o wrapper e a caixa.

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>

Obrigado a todos que ajudaram!

http://jsfiddle.net/5fwjp/

jmotes
fonte
12
Isso funciona porque os elementos posicionados não cortam seu conteúdo no raio da borda no Webkit. Essa camada extra simplesmente faz com que a div com raio da borda NÃO seja posicionada e simplesmente fica dentro de um elemento posicionado.
Daniel Beardsley
9
Por acaso, você saberia se esse é um erro / comportamento pretendido?
jmotes
4
+1 voto a bug ... Quando você tem uma galeria de imagens que gera automaticamente os divs e define a posição para então este "recurso" absoluto, realmente é uma droga ...
inf3rno
@ RunLoop Acabei de testar o jsfiddle no Safari 7.1 e funciona bem. Você pode ser mais específico sobre o que não está funcionando?
jmotes
1
Nosso colega, o designer gráfico, na verdade "descobriu" esses 20 segundos antes de encontrar esta resposta: D
Pere
18

opacidade: 0,99; no wrapper resolver bug do webkit

flavi1
fonte
2
transform: translateY(0);é uma alternativa que alcança o mesmo resultado sem interferir na representação visual do objeto (a menos que você esteja usando a perspectiva).
21817 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
fonte
4
transform: translateZ(0)é o suficiente para mim.
kalvn
Observe que isso (em particular translateZ) ativará implicitamente a aceleração de hardware para seus elementos, o que abre uma nova lata de worms em alguns casos, infelizmente.
22816 doldt
transform: translateZ(0)também funcionou para mim. No meu caso, não é uma má idéia que este item seja acelerado por hardware.
Sebastien Lorber
9

Suportado no Chrome, Opera e Safari mais recentes, você pode fazer o seguinte:

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

Você definitivamente deveria conferir a ferramenta http://bennettfeely.com/clippy/ !

antoni
fonte
Eu acho que você pode encurtar esse caminho ainda mais : inserir (0%); ... basta ter um trajeto do grampo parece fazer o truque :-)
Jakob E
Uau. É a resposta perfeita.
Shashank Bhatt 03/04
4

altere a opacidade do elemento pai com a borda e isso reorganizará os elementos empilhados. Isso funcionou milagrosamente para mim depois de horas de pesquisa e tentativas fracassadas. Era tão simples quanto adicionar uma opacidade de 0,99 para reorganizar esse processo de pintura dos navegadores. Confira http://philipwalton.com/articles/what-no-one-told-you-about-z-index/

Rami Awar
fonte
3

Quanto a mim, nenhuma das soluções funcionou bem, apenas usando:

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

no elemento wrapper fez o trabalho.

Aqui está o exemplo: http://jsfiddle.net/gpawlik/qWdf6/74/

Grzegorz Pawlik
fonte
2

com base na excelente resposta de graycrow ...

Aqui está um exemplo mais real do mundo que possui duas divs particulares com algum conteúdo de preenchimento. Substituí o fundo png codificado por apenas um valor hexadecimal, ou seja,

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

é substituído por

-webkit-mask-image:#fff;

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

gts101
fonte
1

Aqui veja como eu fiz isso; Jsfiddle

Com o código que inseri, consegui fazê-lo funcionar no Webkit (Chrome / Safari) e Firefox. Não sei se funciona com a versão mais recente do Opera. Sim, funciona com a versão mais recente do 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;
}
Labirinto
fonte
Por que se incomodar em colocar o border-radiusinvólucro nessa situação, você obtém o mesmo resultado apenas configurando-o #box. Além disso, se o #boxraio da borda for apenas para corrigir o WebKit, você poderá incluir a -webkit-propriedade lá.
robertc
Labirinto, isso pode funcionar em algumas situações, mas no meu caso, estou procurando uma solução que não transforme a forma da caixa (e o invólucro ainda funciona como uma máscara). Meu exemplo foi muito simplificado, mas estou tentando usar o invólucro para ocultar a sombra da caixa (usando preenchimento no invólucro para tornar apenas as bordas da sombra que eu quero visíveis).
jmotes
1
Obrigado pela ajuda, porém, labirinto! Sua solução me ajudou a pensar sobre o problema de forma mais crítica. Aliás, você pode ignorar a edição que fiz na sua postagem. Eu pretendia fazer isso sozinho. Desculpe :)
jmotes
@ user480837 Sem problemas, companheiro, feliz por ter sido útil. :)
Maze
1
@Maze Isso não vai funcionar se uma borda de qualquer tipo é aplicado: jsfiddle.net/ptW85/228
antitoxic
1

Eu tentei todas as respostas, mas sem sucesso. Após algumas horas de investigação, encontrei a solução para este problema. O uso dessas propriedades em sua classe não permitirá que elementos div excedam o contêiner.

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

Se você deseja criar uma máscara para uma imagem e posicionar a imagem dentro do contêiner, não defina o atributo 'position: absolute'. Tudo o que você precisa fazer é alterar a margem esquerda e a margem direita. O Chrome / Opera aderirá ao excesso: regras de raio oculto e de borda.

// 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;
        }
    }
user6039997
fonte