web-dev-qa-db-fra.com

parent et enfant avec position fixe, débordement du parent: bogue caché

Je ne sais pas s'il y a un problème, mais je me demandais pourquoi le overflow:hidden _ ne fonctionne pas sur l'élément fixed parent/enfants.

Voici un exemple:

CSS et HTML:

.parent{
  position:fixed;
  overflow:hidden;
  width:300px;
  height:300px;
  background:#555;
}
.children{
  position:fixed;
  top:200px;
  left:200px;
  width:150px;
  height:150px;
  background:#333;
}
<div class="parent">
  <div class="children">
  </div>
</div>

Démonstration en direct: jsFiddle

49
kirkas

Parce qu'un élément de position fixe est fixe par rapport à la fenêtre d'affichage, pas un autre élément. Par conséquent, puisque la fenêtre d'affichage n'est pas coupée, le débordement devient inutile.

Alors que la position et les dimensions d'un élément avec position: absolute sont relatives au bloc conteneur, la position et les dimensions d'un élément avec position: fixed sont toujours relatives au bloc conteneur initial. C’est normalement la fenêtre: la fenêtre du navigateur ou la boîte de la page du papier.

ref: http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning#Fixed_positioning

43
j08691

Vous pouvez envisager d'utiliser CSS clip: rect(top, right, bottom, left); pour couper un élément positionné fixe sur un parent. Voir la démo sur http://jsfiddle.net/lmeurs/jf3t0fmf/ .

Attention, à utiliser avec précaution !

Bien que le style de clip soit largement pris en charge, les principaux inconvénients sont les suivants:

  1. La position du parent ne peut être ni statique ni relative (on peut utiliser un parent en position absolue dans un conteneur relativement positionné);
  2. Les coordonnées rectes ne prennent pas en charge les pourcentages, bien que la valeur auto soit égale à 100%, C'est-à-dire. clip: rect(auto, auto, auto, auto);;
  3. Les possibilités avec des éléments enfants sont limitées au moins dans IE11 et Chrome34, c.-à-d. nous ne pouvons pas définir la position des éléments enfants sur relative ou absolue, ni utiliser la transformation CSS3 comme une échelle.

Voir http://tympanus.net/codrops/2013/01/16/understanding-the-css-clip-property/ pour plus d'informations.

EDIT: Chrome semble mieux gérer le positionnement de CSS3 et sa transformation sur les éléments enfants lors de l’application de visibilité de la face arrière , aussi, pour être sûr que nous avons ajouté:

-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;

à l'élément enfant principal.

Notez également qu'il n'est pas entièrement pris en charge par les anciens navigateurs/mobiles ou qu'il peut nécessiter des efforts supplémentaires. Voir notre implémentation pour le menu à bellafuchsia.com .

  1. IE8 montre bien le menu, mais les liens de menu ne sont pas cliquables;
  2. IE9 ne montre pas le menu sous le pli;
  3. iOS Safari <5 ne montre pas bien le menu;
  4. iOS Safari 5+ repeint le contenu coupé en défilement après le défilement;
  5. FF (au moins 13+), IE10 +, Chrome et Chrome pour Android semblent jouer à Nice.

EDIT 2014-11-02: L'URL de la démonstration a été mise à jour.

79
lmeurs

Mise à jour 2016:

Vous pouvez créer un nouveau contexte d'empilement, comme indiqué sur Coderwall :

<div style="transform: translate3d(0,0,0);overflow:hidden">
   <img style="position:fixed; ..." />
</div>

Qui fait référence à http://dev.w3.org/csswg/css-transforms/#transform-rendering

Pour les éléments dont la présentation est régie par le modèle de boîte CSS, toute valeur autre que aucune pour la transformation entraîne la création d'un contexte d'empilement et d'un bloc contenant. L'objet agit comme un bloc conteneur pour les descendants à positions fixes.

24
Hugo H

Au lieu d'utiliser clip, vous pouvez également utiliser {border-radius: 0.0001px} sur un élément parent. Cela fonctionne non seulement avec des éléments positionnés absolus/fixes.

8
ZhenyaUsenko

Si vous souhaitez masquer le débordement sur des éléments à position fixe, la méthode la plus simple que j'ai trouvée consiste à placer l'élément dans un élément conteneur et à appliquer position:fixed et overflow:hidden à cet élément à la place de l'élément contenu (vous devez supprimer position:fixed de l'élément contenu pour que cela fonctionne). Le contenu du conteneur fixe doit alors être découpé comme prévu.

Dans mon cas, j'avais du mal à utiliser object-fit:cover sur un élément à position fixe (il débordait du corps de la page, indépendamment de overflow:hidden). Le placer dans un conteneur fixe avec overflow:hidden sur le conteneur a résolu le problème.

3
Nick F

J'ai eu un problème similaire, assez complexe avec une disposition fluide, où la colonne de droite avait une largeur fixe et la colonne de gauche avait une largeur flexible. Mon conteneur fixe doit avoir la même largeur que la colonne flexible. Voici ma solution:

[~ # ~] html [~ # ~]

<div id="wrapper">
    <div id="col1">
    <div id="fixed-outer">
        <div id="fixed-inner">inner</div>
    </div>
    COL1<br />Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    </div>
    <div id="col2">COL2</div>
</div>

[~ # ~] css [~ # ~]

    #wrapper {
    padding-left: 20px;
}

#col1 {
    background-color: grey;
    float: left;
    margin-right: -200px; /* #col2 width */
    width: 100%;
}

#col2 {
    background-color: #ddd;
    float: left;
    height: 400px;
    width: 200px;
}

#fixed-outer {
    background: yellow;
    border-right: 2px solid red;
    height: 30px;
    margin-left: -420px; /* 2x #col2 width + #wrapper padding-left */
    overflow: hidden;
    padding-right: 200px; /* #col2 width */
    position: fixed;
    width: 100%;
}

#fixed-inner {
    background: orange;
    border-left: 2px solid blue;
    border-top: 2px solid blue;
    height: 30px;
    margin-left: 420px; /* 2x #col2 width + #wrapper padding-left */
    position: absolute;
    width: 100%;
}

Démonstration en direct : http://jsfiddle.net/hWCub/

0
Katja Deutschmann