Position fixe mais relative au conteneur

j'essaie de corriger un div pour qu'il colle toujours en haut de l'écran, en utilisant:

position: fixed;
top: 0px;
right: 0px;

toutefois, le div se trouve à l'intérieur d'un conteneur centré. Quand j'utilise position:fixed il fixe le div relatif à la fenêtre du navigateur, comme il est contre le côté droit du navigateur. Au lieu de cela, il devrait être fixé par rapport au conteneur.

je sais que position:absolute peut être utilisé pour fixer un élément relatif à la div , mais quand vous faites défiler la page vers le bas l'élément disparaît et ne colle pas au dessus comme avec position:fixed .

y a-t-il un piratage ou une solution pour y parvenir?

521
demandé sur Peter Mortensen 2011-07-22 21:47:00

21 réponses

réponse Courte: pas de. (c'est maintenant possible avec CSS transform. Voir l'édition ci-dessous)

réponse Longue: Le problème avec l'utilisation de "fixe" le positionnement est qu'il faut de l'élément de flux . ainsi, il ne peut pas être repositionné par rapport à son parent parce qu'il est comme s'il n'en avait pas. Si, par contre, le conteneur est d'une largeur fixe et connue, vous pouvez utiliser quelque chose comme:

#fixedContainer {
  position: fixed;
  width: 600px;
  height: 200px;
  left: 50%;
  top: 0%;
  margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1 /

Modifier (03/2015):

cette information est périmée. Il est maintenant possible de centrer le contenu d'une taille dynamique (horizontalement et verticalement) à l'aide de la magie de CSS3 transform. Le même principe s'applique, mais au lieu d'utiliser une marge pour compenser votre conteneur, vous pouvez utiliser translateX(-50%) . Cela ne fonctionne pas avec le truc de marge ci-dessus parce que vous ne savez pas combien pour le compenser sauf si la largeur est fixe et que vous ne pouvez pas utiliser de valeurs relatives (comme 50% ) parce qu'elle sera relative au parent et non à l'élément auquel elle est appliquée. transform se comporte différemment. Ses valeurs sont relatives à l'élément auquel elles s'appliquent. Ainsi, 50% pour transform signifie la moitié de la largeur de l'élément, tandis que 50% pour la marge est la moitié de la largeur du parent. Il s'agit d'une IE9+ solution

utilisant un code similaire à dans l'exemple ci-dessus, j'ai recréé le même scénario en utilisant la largeur et la hauteur complètement dynamiques:

.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 0%;
    transform: translateX(-50%);
}

Si vous voulez qu'il soit centré, vous pouvez le faire aussi:

.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

démos:

jsFiddle: centré horizontalement seulement

jsfiddle: centré à la fois horizontalement et verticalement

le crédit Original va à l'utilisateur aaronk6 pour m'en avoir parlé dans cette réponse

351
répondu Joseph Marikle 2017-05-23 11:47:31

en fait, c'est possible et la réponse acceptée ne concerne que la centralisation, ce qui est assez simple. De plus, vous n'avez vraiment pas besoin d'utiliser JavaScript.

Cela vous permettra de faire face à n'importe quel scénario:

tout mettre en place comme vous le feriez si vous voulez positionner: absolute à l'intérieur d'une position: conteneur relatif, puis créer une nouvelle position fixe div à l'intérieur de la div avec position: absolute , mais ne pas et propriétés de gauche. Il sera alors fixé là où vous le voulez, par rapport au conteneur.

par exemple:

/* Main site body */
.wrapper {
    width: 940px;
    margin: 0 auto;
    position: relative; /* Ensure absolute positioned child elements are relative to this*/
}

/* Absolute positioned wrapper for the element you want to fix position */
.fixed-wrapper {
    width: 220px;
    position: absolute;
    top: 0;
    left: -240px; /* Move this out to the left of the site body, leaving a 20px gutter */
}

/* The element you want to fix the position of */
.fixed {
    width: 220px;
    position: fixed;
    /* Do not set top / left! */
}
<div class="wrapper">
    <div class="fixed-wrapper">
        <div class="fixed">
            Content in here will be fixed position, but 240px to the left of the site body.
        </div>
    </div>
</div>

malheureusement, j'espérais que ce fil pourrait résoudre mon problème avec le WebKit d'Android rendant les pixels de flou d'ombre comme les marges sur les éléments de position fixe, mais il semble que ce soit un bug.

quoi qu'il en soit, j'espère que cela aidera!

154
répondu Graeme Blackwood 2017-10-12 15:18:21

Oui, selon les spécifications, il ya un moyen.

bien que je convienne que Graeme Blackwood devrait être la réponse acceptée, parce qu'elle résout pratiquement la question, il convient de noter qu'un élément fixe can doit être placé relativement à son contenant.

j'ai remarqué par accident que lors de l'application

-webkit-transform: translateZ(0);

au corps, il a fait un enfant fixe par rapport à (au lieu de la fenêtre d'affichage). Ainsi mes propriétés fixes left et top étaient maintenant relatives au conteneur.

donc j'ai fait quelques recherches, et j'ai constaté que la question était déjà couverte par Eric Meyer et même si elle se sentait comme un "truc", s'avère que cela fait partie du cahier des charges:

pour les éléments dont la disposition est régie par le modèle de boîte CSS, toute valeur d'autres que aucun pour la transformation des résultats de la création d'un le contexte d'empilage et un bloc contenant. L'objet agit comme un contenant le bloc pour les descendants positionnés fixes.

http://www.w3.org/TR/css3-transforms /

ainsi, si vous appliquez n'importe quelle transformation à un élément parent, il deviendra le bloc contenant.

mais...

Le problème est que la mise en œuvre semble buggy / créatif, parce que les éléments cessent également de se comporter comme fixe (même si ce bit ne semble pas faire partie de la spécification).

Le même comportement sera trouvé dans Safari, Chrome et Firefox, mais pas dans IE11 (où l'élément fixe restera fixe).

une autre chose intéressante (non documentée) est que lorsqu'un élément fixe est contenu dans un élément transformé, alors que ses propriétés top et left seront en ce qui concerne le conteneur, en ce qui concerne la propriété box-sizing , son contexte défilant s'étendra au-delà de la frontière de l'élément, comme si le format de la boîte était fixé à border-box . Pour certains créatifs là-bas, ce qui pourrait éventuellement devenir un jouet :)

TEST

118
répondu Francesco Frapporti 2014-09-29 11:40:09

la réponse est oui, tant que vous ne mettez pas left: 0 ou right: 0 après avoir mis la position div à fixe.

http://jsfiddle.net/T2PL5/85 /

check-out the sidebar div. Il est fixe, mais lié au parent, pas au point de vue de la fenêtre.

body { background: #ccc; }

.wrapper {
    margin: 0 auto;
    height: 1400px;
    width: 650px;
    background: green;
}

.sidebar {
    background-color: #ddd;
    float: left;
    width: 300px;
    height: 100px;
    position: fixed;
}

.main {
    float: right;
    background-color: yellow;
    width: 300px;
    height: 1400px;
}

<div class="wrapper">wrapper
    <div class="sidebar">sidebar</div>
    <div class="main">main</div>
</div>
54
répondu Shadow_boi 2015-09-27 12:21:44

Vous avez position: sticky c'est une nouvelle façon de positionner les éléments et est conceptuellement similaire à position: fixed . La différence est qu'un élément avec position: sticky se comporte comme position: relative dans son parent, jusqu'à ce qu'un seuil d'offset donné soit atteint dans le viewport.

dans Chrome 56 (actuellement bêta en décembre 2016, stable en janvier 2017) position: sticky is now back.

https://developers.google.com/web/updates/2016/12/position-sticky

Plus de détails dans Coller votre débarquements! position: sticky lands dans WebKit .

19
répondu PoseLab 2016-12-19 11:04:10

j'ai créé ce plugin jQuery pour résoudre un problème similaire que j'avais là où j'avais un conteneur centré (données tabulaires), et je voulais que l'en-tête se fixe en haut de la page quand la liste était scrollée, mais je voulais qu'il soit ancré aux données tabulaires afin qu'il soit partout où je mets le conteneur (centré, gauche, droite) et aussi lui permettre de se déplacer à gauche et à droite avec la page quand scrollé.

voici le lien vers ce plugin jQuery qui pourrait résoudre ce problème:

https://github.com/bigspotteddog/ScrollToFixed

la description de ce plugin est la suivante:"

ce plugin est utilisé pour fixer des éléments vers le haut de la page, si l'élément s'est déroulé verticalement hors de vue; cependant, il permet à l'élément de continuer à se déplacer à gauche ou à droite avec le rouleau horizontal.

avec une option marginTop, l'élément va arrêter de se déplacer verticalement vers le haut une fois que le rouleau vertical a atteint la position cible; mais, l'élément se déplacera toujours horizontalement que la page est laminée à gauche ou à droite. Une fois que la page a été scrollée vers le bas en passant la position cible, l'élément sera restauré à sa position originale sur la page.

ce plugin a été testé dans Firefox 3/4, Google Chrome 10/11, Safari 5, et Internet Explorer 8/9.

Usage pour votre cas particulier:

<script src="scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery-scrolltofixed-min.js" type="text/javascript"></script>

$(document).ready(function() {
    $('#mydiv').scrollToFixed();
});
18
répondu bigspotteddog 2015-09-27 11:40:36

il suffit de prendre les styles supérieur et gauche de la div position fixe. Voici un exemple

<div id='body' style='height:200%; position: absolute; width: 100%; '>
    <div id='parent' style='display: block; margin: 0px auto; width: 200px;'>
        <div id='content' style='position: fixed;'>content</div>
    </div>
</div> 

la div # content sera assise partout où la div mère sera assise, mais elle y sera fixée.

17
répondu hobberwickey 2012-03-28 14:23:40

j'ai dû le faire avec une annonce que mon client voulait s'asseoir à l'extérieur de la zone de contenu. J'ai simplement fait ce qui suit et ça a fonctionné comme un charme!

<div id="content" style="position:relative; width:750px; margin:0 auto;">
  <div id="leftOutsideAd" style="position:absolute; top:0; left:-150px;">
    <a href="#" style="position:fixed;"><img src="###" /></a>
  </div>
</div>
12
répondu Eric K 2012-04-30 13:55:25

Deux éléments HTML et pure CSS (les navigateurs modernes)

voir cet exemple de jsFiddle. redimensionnez et voyez comment les éléments fixes bougent avec les éléments flottants qu'ils contiennent. Utilisez la barre de défilement la plus interne pour voir comment le défilement fonctionnerait sur un site (éléments fixes restant fixes).

comme beaucoup ici ont déclaré, une clé n'est pas de définir des paramètres de Position sur l'élément fixed (Non top , right , bottom , ou left ).

plutôt, nous mettons tous les éléments fixes (notez comment la dernière boîte a quatre d'entre eux) en premier dans la boîte ils doivent être positionnés hors, comme ainsi:

<div class="reference">
  <div class="fixed">Test</div>
  Some other content in.
</div>

puis nous utilisons margin-top et margin-left pour les" déplacer "par rapport à leur conteneur, quelque chose comme ce CSS fait:

.fixed {
    position: fixed;
    margin-top: 200px; /* Push/pull it up/down */
    margin-left: 200px; /* Push/pull it right/left */
}

noter que parce que fixed éléments ignorez tous les autres éléments de disposition, le conteneur final dans notre violon peut avoir plusieurs fixed éléments, et ont encore tous les éléments liés au coin supérieur gauche. Mais cela n'est vrai que s'ils sont tous placés en premier dans le conteneur, car cette comparaison montre que si dispersé dans le contenu du conteneur, le positionnement devient peu fiable .

si l'emballage est statique , relative , ou absolue en positionnement, cela n'a pas d'importance.

7
répondu ScottS 2015-09-27 12:30:12

vous pouvez utiliser la propriété position: sticky .

voici un exemple CODEPEN démontrant l'usage et aussi comment il diffère de position: fixed .

son comportement est expliqué ci-dessous:

  1. un élément avec une position collante est positionné en fonction de la position de défilement de l'utilisateur. Il agit essentiellement comme position: relative jusqu'à ce qu'un élément soit laminé au-delà d'un déport spécifique, en dans quel cas il se transforme en position: fixe. Lorsqu'elle est enrayée, elle retourne à sa position (relative) précédente.

  2. il affecte le flux d'autres éléments dans la page ie occupe un espace spécifique sur la page(tout comme position: relative ).

  3. s'il est défini à l'intérieur d'un conteneur, il est placé par rapport à ce conteneur. Si le conteneur a quelques débordement(défilement), en fonction du défilement offset il se transforme en position:fixe.

donc si vous voulez atteindre la fonctionnalité fixe mais à l'intérieur d'un conteneur, utilisez sticky.

6
répondu Pransh Tiwari 2018-07-10 08:59:59

Vous pouvez donner un essai à mon plugin jQuery, FixTo .

Utilisation:

$('#mydiv').fixTo('#centeredContainer');
3
répondu Burak 2015-09-27 12:20:08

une autre solution étrange pour atteindre une position fixe relative est de convertir votre conteneur en iframe, de cette façon votre élément fixe peut être fixé à son viewport de conteneur et non la page entière.

2
répondu Beto Aveiga 2012-07-24 21:46:37

avec CSS pur vous ne pouvez pas réussir à le faire; au moins je n'ai pas. Cependant, vous pouvez le faire avec jQuery très simplement. Je vais vous expliquer mon problème, et avec un peu de changement, vous pouvez l'utiliser.

Donc, pour commencer, je voulais que mon élément fixe en haut (du haut de la fenêtre), et un élément gauche à hériter de l'élément parent (parce que l'élément parent est centré). Pour définir l'élément gauche, il suffit de mettre votre élément dans le parent et l'ensemble position:relative pour le parent élément.

ensuite, vous devez savoir combien de la partie supérieure de votre élément est lorsque la barre de défilement est sur le dessus (y zéro défilement); il ya deux options à nouveau. La première est statique (un certain nombre) ou vous devez lire à partir de l'élément parent.

dans mon cas, c'est à 150 pixels de Top static. Donc quand vous voyez 150 c'est combien est l'élément du haut quand nous n'avons pas filé.

CSS

#parent-element{position:relative;}
#promo{position:absolute;}

jquery

$(document).ready(function() { //This check window scroll bar location on start
    wtop=parseInt($(window).scrollTop());
    $("#promo").css('top',150+wtop+'px');

});
$(window).scroll(function () { //This is when the window is scrolling
    wtop=parseInt($(window).scrollTop());
    $("#promo").css('top',150+wtop+'px');
});
2
répondu Mr Br 2015-09-27 12:26:59

C'est facile (selon HTML ci-dessous)

le truc est de ne pas utiliser le haut ou à gauche sur l'élément (div) avec"position: fixe;". Si ceux-ci ne sont pas spécifiés, L'élément "fixed content" apparaîtra par rapport à l'élément qui l'entoure (la div avec "position:relative;") au lieu de par rapport à la fenêtre du navigateur!!!

<div id="divTermsOfUse" style="width:870px; z-index: 20; overflow:auto;">
    <div id="divCloser" style="position:relative; left: 852px;">
        <div style="position:fixed; z-index:22;">
            <a href="javascript:hideDiv('divTermsOfUse');">
                <span style="font-size:18pt; font-weight:bold;">X</span>
            </a>
        </div>
    </div>
    <div>  <!-- container for... -->
         lots of Text To Be Scrolled vertically...
         bhah! blah! blah!
    </div>
</div>

ci-dessus m'a permis de localiser un bouton de fermeture "X" en haut d'un lot de texte dans une div avec défilement vertical. Le "X" est en place (ne se déplace pas avec du texte défilant et pourtant il se déplace à gauche ou à droite avec le conteneur divosing lorsque l'utilisateur redimensionne la largeur de la fenêtre du navigateur! Il est donc" fixe " verticalement, mais placé horizontalement par rapport à l'élément qui l'entoure!

avant que je fasse ce travail le "X" défilait vers le haut et hors de vue quand je défilais le contenu du texte vers le bas.

excuses pour ne pas avoir fourni ma fonction javascript hideDiv (), mais il serait inutilement de faire ce post plus. J'ai opté pour le garder le plus court possible.

1
répondu Bruce Allen 2014-07-02 21:29:06

j'ai créé un jsfiddle pour démontrer comment cela fonctionne avec transform.

HTML

<div class="left">
    Content
</div>
<div class="right">
<div class="fixedContainer">
    X
</div>
    Side bar
</div>

CSS

body {
  margin: 0;
}
.left {
  width: 77%;
  background: teal;
  height: 2000px;
}
.right {
  width: 23%;
  background: yellow;
  height: 100vh;
  position: fixed;
  right: 0;
  top: 0;
}
.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    //right: 0;
    top: 0%;
    transform: translateX(-100px);
}

jQuery

$('.fixedContainer').on('click', function() {
    $('.right').animate({'width': '0px'});
  $('.left').animate({'width': '100%'});
});

https://jsfiddle.net/bx6ktwnn/1 /

1
répondu Wen 2016-08-09 21:07:45

j'ai le même problème, un des membres de notre équipe me donne une solution. Pour permettre la position de fixation de div et par rapport à d'autres div, notre solution est d'utiliser un père récipient envelopper la div fixer et faire défiler div.

<div class="container">
  <div class="scroll"></div>
  <div class="fix"></div>
</div>

css

.container {
  position: relative;
  flex:1;
  display:flex;
}

.fix {
  prosition:absolute;
}
1
répondu Jay0Lu 2017-02-21 21:52:16

j'ai fait quelque chose comme ça il y a quelque temps. J'étais assez nouveau à JavaScript, donc je suis sûr que vous pouvez faire mieux, Mais voici un point de départ:

function fixxedtext() {
    if (navigator.appName.indexOf("Microsoft") != -1) {
        if (document.body.offsetWidth > 960) {
            var width = document.body.offsetWidth - 960;
            width = width / 2;
            document.getElementById("side").style.marginRight = width + "px";
        }
        if (document.body.offsetWidth < 960) {
            var width = 960 - document.body.offsetWidth;
            document.getElementById("side").style.marginRight = "-" + width + "px";
        }
    }
    else {
        if (window.innerWidth > 960) {
            var width = window.innerWidth - 960;
            width = width / 2;
            document.getElementById("side").style.marginRight = width + "px";
        }
        if (window.innerWidth < 960) {
            var width = 960 - window.innerWidth;
            document.getElementById("side").style.marginRight = "-" + width + "px";
        }
    }
    window.setTimeout("fixxedtext()", 2500)
}

vous aurez besoin de définir votre largeur, puis il obtient la largeur de la fenêtre et change la marge toutes les quelques secondes. Je sais que c'est lourd, mais il fonctionne.

0
répondu webLacky3rdClass 2015-09-27 11:33:19

c'est possible si vous utilisez JavaScript. Dans ce cas, le plugin jQuery Sticky-Kit :

0
répondu Paz Aricha 2015-09-27 12:31:46

mon projet est .NET ASP Core 2 MVC Angular 4 modèle avec Bootstrap 4. Ajouter "sticky-top" dans le composant principal de l'application html (c.-à-d. app.composant.html) sur la première ligne travaillée, comme suit:

<div class='row sticky-top'>
    <div class='col-sm-12'>
        <nav-menu-top></nav-menu-top>
    </div>
</div>
<div class="row">
    <div class='col-sm-3'>
        <nav-menu></nav-menu>
    </div>
    <div class='col-sm-9 body-content'>
        <router-outlet></router-outlet>
    </div>
</div>

est-ce que c'est la convention ou est-ce que je l'ai trop simplifié?

0
répondu Adam Cox 2017-11-02 19:16:15
/* html */

/* this div exists purely for the purpose of positioning the fixed div it contains */
<div class="fix-my-fixed-div-to-its-parent-not-the-body">

     <div class="im-fixed-within-my-container-div-zone">
          my fixed content
     </div>

</div>



/* css */

/* wraps fixed div to get desired fixed outcome */
.fix-my-fixed-div-to-its-parent-not-the-body 
{
    float: right;
}

.im-fixed-within-my-container-div-zone
{
    position: fixed;
    transform: translate(-100%);
}
0
répondu Carol McKay 2018-09-14 03:06:52

Vérifiez ceci:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
    </head>
    <body style="width: 1000px !important;margin-left: auto;margin-right: auto">
        <div style="width: 100px; height: 100px; background-color: #ccc; position:fixed;">
        </div>
        <div id="1" style="width: 100%; height: 600px; background-color: #800000">
        </div>
        <div id="2" style="width: 100%; height: 600px; background-color: #100000">
        </div>
        <div id="3" style="width: 100%; height: 600px; background-color: #400000">
        </div>
    </body>
</html>
-1
répondu Kunal 2015-09-27 11:41:25