Comment faire en sorte que les coins arrondis CSS3 masquent le débordement dans Chrome / Opera

147

J'ai besoin de coins arrondis sur un div parent pour masquer le contenu de ses enfants. overflow: hiddenfonctionne dans des situations simples, mais se casse dans les navigateurs basés sur le Webkit et dans Opera lorsque le parent est positionné de manière relativement ou absolue.

Cela fonctionne dans Firefox et 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>

Exemple sur JSFiddle

Merci pour l'aide!

MISE À JOUR: le bogue à l'origine de ce problème a été résolu depuis dans Chrome. Je n'ai cependant pas retesté Opera ou Safari.

jmotes
la source

Réponses:

183

J'ai trouvé une autre solution à ce problème. Cela ressemble à un autre bogue dans WebKit (ou probablement dans Chrome), mais cela fonctionne. Tout ce que vous avez à faire est d'ajouter un masque CSS WebKit à l'élément #wrapper. Vous pouvez utiliser une image png d'un seul pixel et même l'inclure dans le CSS pour enregistrer une requête 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;
}​

Exemple JSFiddle

Graycrow
la source
3
merci pour ce correctif. Je l'ai essayé en safari aujourd'hui (v6.0.2) et j'ai travaillé pour moi là-bas!
billythetalented
6
cela brisera cependant les ombres sur l'élément.
Jack James
1
Cela fonctionne également sur les wrappers avec des enfants positionnés de manière absolue, contrairement à l'autre solution ici. Agréable!
Dan Tello
2
en utilisant Chrome 42.0.2311.90 (64 bits), et ce correctif est toujours nécessaire ... merci!
simon
2
vos solutions suppriment les ombres de l'élément parent.
ABDeveloper
107

Ajoutez un z-index à votre élément à rayon de bordure, et il masquera les choses à l'intérieur.

Jackolai
la source
@Sifu: vous avez tout simplement tort. Pour une raison quelconque, l'ajout d'un z-index comme suggéré a résolu ce problème exact pour moi (dans la version actuelle de Chrome), et c'est une solution plus simple et plus générale que la réponse principale.
Nick F
7
@simon: rappelez-vous que pour que z-index ait un effet, certaines conditions doivent être remplies (par exemple, la position doit être définie). Voir ici pour les détails.
Nick F
@NickF - c'était un bogue dans Chrome (-ium); -webkit-mask-image: -webkit-radial-gradient(circle, white, black);était une solution de contournement efficace, mais, heureusement, le bogue est corrigé dans la dernière mise à jour que j'ai reçue pour Chrome.
simon
z-index 1 au conteneur. z-index -1 à l'élément absolu l'a résolu pour moi.
aZtraL-EnForceR
Celui-ci a fonctionné pour moi. La solution wrapper ci-dessus ne le fait pas.
Ruwen
58

Peu importe tout le monde, j'ai réussi à résoudre le problème en ajoutant un div supplémentaire entre le wrapper et la boîte.

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>

Merci à tous ceux qui ont aidé!

http://jsfiddle.net/5fwjp/

jmotes
la source
12
Cela fonctionne car les éléments positionnés ne coupent pas leur contenu à leur rayon de bordure dans Webkit. Cette couche supplémentaire permet simplement que le div avec le rayon de bordure ne soit PAS positionné, et se trouve simplement à l'intérieur d'un élément positionné.
Daniel Beardsley
9
Sauriez-vous par hasard s'il s'agit d'un bug / d'un comportement intentionnel?
jmotes
4
+1 vote pour bug ... Lorsque vous avez une galerie d'images qui génère automatiquement les divs et définit la position sur absolue, alors cette "fonctionnalité" vraiment sux ...
inf3rno
@RunLoop Je viens de tester le jsfiddle dans Safari 7.1 et fonctionne très bien. Pouvez-vous être plus précis sur ce qui ne fonctionne pas?
jmotes
1
Notre collègue le graphiste a en fait "découvert" ces 20 secondes avant de trouver cette réponse: D
Pere
18

opacité: 0,99; sur le wrapper résoudre le bogue du kit Web

flavi1
la source
2
transform: translateY(0);est une alternative qui permet d'obtenir le même résultat sans interférer avec la représentation visuelle de l'objet (sauf si vous utilisez la perspective).
kontur le
15

Il semble que celui-ci fonctionne:

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

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

nakrill
la source
4
transform: translateZ(0)me suffit.
kalvn
Notez que cela (en particulier translateZ) activera implicitement l'accélération matérielle pour vos éléments, ce qui ouvre malheureusement une toute nouvelle boîte de vers dans certains cas.
doldt
transform: translateZ(0)a également travaillé pour moi. Dans mon cas, ce n'est pas une mauvaise idée que cet élément soit accéléré par le matériel.
Sebastien Lorber
9

Pris en charge dans les derniers chrome, opéra et safari, vous pouvez le faire:

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

Vous devriez certainement consulter l'outil http://bennettfeely.com/clippy/ !

Antoni
la source
Je pense que vous pouvez raccourcir encore plus ce clip-path: insert (0%); ... le simple fait d'avoir un chemin de clip semble faire l'affaire :-)
Jakob E
Sensationnel. C'est la réponse parfaite.
Shashank Bhatt le
4

changez l'opacité de l'élément parent avec la bordure et cela réorganisera les éléments empilés. Cela a fonctionné miraculeusement pour moi après des heures de recherche et des tentatives infructueuses. C'était aussi simple que d'ajouter une opacité de 0,99 pour réorganiser ce processus de peinture des navigateurs. Consultez http://philipwalton.com/articles/what-no-one-told-you-about-z-index/

Rami Awar
la source
3

Quant à moi, aucune des solutions n'a bien fonctionné, en utilisant uniquement:

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

sur l'élément wrapper a fait le travail.

Voici l'exemple: http://jsfiddle.net/gpawlik/qWdf6/74/

Grzegorz Pawlik
la source
2

basé sur l'excellente réponse de Graycrow ...

Voici un exemple plus réel du monde qui a deux divs ciculaires avec du contenu de remplissage. J'ai remplacé l'arrière-plan png codé en dur par juste une valeur hexadécimale, c'est-à-dire

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

est remplacé par

-webkit-mask-image:#fff;

Voir ce JSFiddle ... http://jsfiddle.net/hqLkA/

gts101
la source
1

Regardez ici comment je l'ai fait; Jsfiddle

Avec le code que j'ai mis, j'ai réussi à le faire fonctionner sur Webkit (Chrome / Safari) et Firefox. Je ne sais pas si cela fonctionne avec la dernière version d'Opera. Oui, cela fonctionne sous la dernière version d'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;
}
Labyrinthe
la source
Pourquoi se donner la peine de mettre border-radiusle wrapper on dans cette situation, vous obtenez le même résultat en l'activant simplement #box. De plus, si le #boxrayon de la bordure sert uniquement à corriger WebKit, vous pouvez simplement y inclure la -webkit-propriété.
robertc
Maze, cela peut fonctionner dans certaines situations, mais dans mon cas, je recherche une solution qui ne transforme pas la forme de la boîte (et l'emballage fonctionne toujours comme un masque). Mon exemple a été très simplifié mais j'essaie d'utiliser le wrapper pour masquer les ombres de la boîte (en utilisant un rembourrage sur le wrapper pour ne rendre visibles que les bords de l'ombre que je veux).
jmotes
1
Merci pour l'aide via Maze! Votre solution m'a aidé à réfléchir au problème de manière plus critique. Btw, vous pouvez ignorer la modification que j'ai apportée à votre message. Je voulais arriver à moi-même. Désolé :)
jmotes
@ user480837 Pas de problème, mon ami, heureux d'avoir été utile. :)
Maze
1
@Maze Cela ne fonctionnera pas si une bordure quelconque est appliquée: jsfiddle.net/ptW85/228
antitoxique
1

J'ai essayé toutes les réponses mais sans succès. Après quelques heures d'enquête, j'ai trouvé une solution à ce problème. L'utilisation de ces propriétés dans votre classe ne permettra pas aux éléments div de déborder du conteneur.

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

Si vous cherchez à créer un masque pour une image et à positionner l'image à l'intérieur du conteneur, ne définissez pas l'attribut 'position: absolute'. Tout ce que vous avez à faire est de changer la marge gauche et la marge droite. Chrome / Opera respectera les règles de débordement: masqué et bord-rayon.

// 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
la source