Position fixe mais relative au conteneur

J’essaie de réparer un div afin qu’il colle toujours en haut de l’écran, en utilisant:

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

Cependant, le div est à l’intérieur d’un conteneur centré. Lorsque j’utilise position:fixed il corrige le div rapport à la fenêtre du navigateur, comme s’il se trouvait à droite du navigateur. Au lieu de cela, il devrait être fixe par rapport au conteneur.

Je connais cette position:absolute peut être utilisé pour fixer un élément par rapport à la div , mais lorsque vous faites défiler la page, l’élément disparaît et ne colle pas au sumt comme avec la position:fixed .

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

Réponse courte: non. (C’est maintenant possible avec la transformation CSS. Voir la modification ci-dessous)

Réponse longue: Le problème avec le positionnement “fixe” est qu’il élimine l’élément. il ne peut donc pas être repositionné par rapport à son parent car c’est comme s’il n’en avait pas. Si, toutefois, le conteneur a 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/

Edit (03/2015):

Ce sont des informations obsolètes. Il est désormais possible de centrer le contenu d’une taille dynamic (horizontalement et verticalement) à l’aide de la magie de la transformation CSS3. Le même principe s’applique, mais au lieu d’utiliser la marge pour décaler votre conteneur, vous pouvez utiliser translateX(-50%) . Cela ne fonctionne pas avec l’astuce de marge ci-dessus, car vous ne savez pas à quel point le compenser à moins que la largeur soit fixe et que vous ne pouvez pas utiliser des valeurs relatives (comme 50% ) élément auquel il est appliqué. transform se comporte différemment. Ses valeurs sont relatives à l’élément auquel elles sont appliquées. Ainsi, 50% pour la 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. Ceci est une solution IE9 +

En utilisant un code similaire à l’exemple ci-dessus, j’ai recréé le même scénario en utilisant une largeur et une hauteur complètement dynamics:

 .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é horizontalement et verticalement
Le crédit original va à l’utilisateur aaronk6 pour m’avoir signalé dans cette réponse

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

Cela vous permettra de gérer n’importe quel scénario:

Mettez tout en place comme vous le souhaitez si vous souhaitez positionner: absolu dans une position: conteneur relatif, puis créez une nouvelle position fixe div dans la div avec position: absolute , mais ne définissez pas ses propriétés top et left. Il sera alors corrigé 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! */ } 
 
Content in here will be fixed position, but 240px to the left of the site body.

Oui, selon les spécifications, il y a un moyen.

Bien que je convienne que la réponse de Graeme Blackwood devrait être acceptée, car elle résout pratiquement le problème, il convient de noter qu’un élément fixe peut être positionné par rapport à son contenant.

J’ai remarqué par accident que lors de l’application

 -webkit-transform: translateZ(0); 

au corps, il en a fait un enfant fixe (au lieu de la fenêtre d’affichage). Donc, mes éléments fixes à left et top propriétés top étaient maintenant relatives au conteneur.

J’ai donc fait des recherches et constaté que le problème avait déjà été traité par Eric Meyer et même si cela semblait être un “truc”, il s’avère que cela fait partie des spécifications:

Pour les éléments dont la disposition est régie par le modèle de boîte CSS, toute valeur autre que none pour la transformation entraîne la création à la fois d’un contexte d’emstackment et d’un bloc conteneur. L’object agit comme un bloc contenant pour les descendants à position fixe.

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

Donc, si vous appliquez une transformation à un élément parent, il deviendra le bloc contenant.

Mais…

Le problème est que l’implémentation semble buggée / créative, car les éléments cessent également de se comporter comme fixes (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 restra 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 vont maintenant être liées au conteneur, en respectant la propriété de box-sizing , son contexte de défilement s’étendra au-dessus de la bordure du element, comme si la taille des boîtes était définie sur border-box . Pour certains créatifs, cela pourrait devenir un jouet 🙂

TESTER

La réponse est oui, tant que vous ne définissez pas à left: 0 ou à right: 0 après avoir défini la position div sur fixe.

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

Vérifiez la div de la barre latérale. Il est corrigé, mais lié au parent, pas au sharepoint 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; } 
wrapper
main

J’ai créé ce plugin jQuery pour résoudre un problème similaire que je rencontrais où j’avais un conteneur centré (données tabulaires), et je voulais que l’en-tête se positionne en haut de la page lorsque la liste était défilée. les données tabulaires donc ce serait là où je mets le conteneur (centré, gauche, droite) et lui permettent également de se déplacer à gauche et à droite avec la page quand défiler horizontalement.

Voici le lien vers ce plugin jQuery qui peut résoudre ce problème:

https://github.com/bigspotteddog/ScrollToFixed

La description de ce plugin est la suivante:

Ce plugin permet de fixer des éléments en haut de la page, si l’élément aurait défilé verticalement; Cependant, cela permet à l’élément de continuer à se déplacer à gauche ou à droite avec le défilement horizontal.

Étant donné une option marginTop, l’élément cessera de se déplacer verticalement une fois que le défilement vertical aura atteint la position cible; mais l’élément se déplace toujours horizontalement au fur et à mesure que la page défile vers la gauche ou vers la droite. Une fois que la page a été défilée, elle a dépassé la position cible, l’élément sera restauré à sa position d’origine sur la page.

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

Usage pour votre cas particulier:

   $(document).ready(function() { $('#mydiv').scrollToFixed(); }); 

Il suffit de prendre les styles haut et gauche en dehors de la position fixe div. Voici un exemple

 
content

Le div #content sera assis là où se trouve le div parent, mais sera fixé là.

Vous avez la position: sticky qui est une nouvelle façon de positionner les éléments et conceptuellement similaire à la position: fixed . La différence est qu’un élément avec position: sticky se comporte comme la position: relative dans son parent, jusqu’à ce qu’un seuil de décalage donné soit atteint dans la fenêtre d’affichage.

Dans Chrome 56 (actuellement en version bêta en décembre 2016, stable en janvier 2017), la position: sticky est de retour.

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

Plus de détails sont dans Stick vos atterrissages! position: sticky atterrit dans WebKit .

Je devais le faire avec une publicité que mon client voulait placer en dehors de la zone de contenu. J’ai simplement fait ce qui suit et cela a fonctionné comme un charme!

 

Deux éléments HTML et CSS pur (navigateurs modernes)

Voir cet exemple jsFiddle. Redimensionnez et voyez comment les éléments fixes se déplacent avec les éléments flottants dans lesquels ils se trouvent. Utilisez la barre de défilement interne pour voir comment le défilement fonctionnerait sur un site (les éléments fixes restnt fixes).

Comme beaucoup d’entre eux l’ont déclaré, une des clés n’est pas de définir des parameters de position sur l’élément fixed (pas de valeurs top , right , bottom ou left ).

Au lieu de cela, nous mettons tous les éléments fixes (notez la façon dont la dernière boîte en contient quatre) en premier dans la boîte où ils doivent être positionnés, comme ceci:

 
Test
Some other content in.

Ensuite, nous utilisons margin-top et margin-left pour les “déplacer” par rapport à leur conteneur, comme le fait ce CSS:

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

Notez que comme fixed éléments fixed ignorent tous les autres éléments de disposition, le dernier conteneur de notre violon peut avoir plusieurs éléments fixed et tous les éléments restnt liés au coin supérieur gauche. Mais cela n’est vrai que si elles sont toutes placées en premier dans le conteneur, car ce violon de comparaison montre que si elles sont dispersées dans le contenu du conteneur, le positionnement devient peu fiable .

Que le wrapper soit statique , relatif ou absolu dans le positionnement, peu importe.

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

Voici un exemple de CODEPEN démontrant l’utilisation et comment elle diffère de la position: fixed .

Comment cela se comporte 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 la position: relative jusqu’à ce qu’un élément défile au-delà d’un décalage spécifique, auquel cas il se transforme en position: fixe. En remontant, il revient à sa position précédente (relative).

  2. Il affecte le stream des autres éléments de la page, c’est-à-dire qu’il occupe un espace spécifique sur la page (tout comme la position: relative ).

  3. S’il est défini dans un conteneur, il est positionné par rapport à ce conteneur. Si le conteneur a un débordement (scroll), en fonction du décalage de défilement, il se transforme en position: fixed.

Donc, si vous souhaitez obtenir la fonctionnalité fixe, mais à l’intérieur d’un conteneur, utilisez du sticky.

Vous pouvez essayer mon plugin jQuery, FixTo .

Usage:

 $('#mydiv').fixTo('#centeredContainer'); 

Une autre solution étrange pour obtenir une position relative relative consiste à convertir votre conteneur en iframe, de sorte que votre élément fixe puisse être fixé à la fenêtre de son conteneur et non à la page entière.

Avec du CSS pur, vous ne parvenez pas à le faire. au moins je n’ai pas. Cependant, vous pouvez le faire très simplement avec jQuery. Je vais expliquer mon problème, et avec un petit changement, vous pouvez l’utiliser.

Donc, pour commencer, je voulais que mon élément ait un sumt fixe (du haut de la fenêtre) et un composant gauche pour hériter de l’élément parent (parce que l’élément parent est centré). Pour définir le composant gauche, placez simplement votre élément dans le parent et définissez la position:relative pour l’élément parent.

Ensuite, vous devez savoir de combien votre élément est situé en haut lorsque la barre de défilement est en haut (y a défilement zéro); il y a encore deux options. Tout d’abord, il s’agit de statique (un certain nombre) ou vous devez le lire à partir de l’élément parent.

Dans mon cas, il est à 150 pixels de la partie supérieure statique. Donc, quand vous voyez 150, c’est combien c’est l’élément du haut quand on n’a pas fait défiler.

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'); }); 

C’est facile (selon HTML ci-dessous)

L’astuce consiste à NE PAS utiliser top ou left sur l’élément (div) avec “position: fixed”. Si ceux-ci ne sont pas spécifiés, l’élément “contenu fixe” apparaîtra RELATIVE à l’élément englobant (le div avec “position: relative;”) INSTEAD OF relatif à la fenêtre du navigateur !!!

 
lots of Text To Be Scrolled vertically... bhah! blah! blah!

Ci-dessus, j’ai pu localiser un bouton de fermeture “X” en haut de beaucoup de texte dans un div avec défilement vertical. Le “X” est en place (ne bouge pas avec le texte défilé et pourtant il se déplace à gauche ou à droite avec le conteneur div englobant lorsque l’utilisateur redimensionne la largeur de la fenêtre du navigateur! Il est donc “fixe” verticalement mais positionné par rapport à l’élément enfermant horizontalement!

Avant que cela fonctionne, le “X” défilait vers le haut et disparaissait lorsque je faisais défiler le contenu du texte.

Toutes mes excuses pour ne pas avoir fourni ma fonction javascript hideDiv (), mais cela rendrait inutilement ce post plus long. J’ai choisi de le garder le plus court possible.

J’ai créé un jsfiddle pour montrer comment cela fonctionne en utilisant transform.

HTML

 
Content
X
Side bar

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/

J’ai le même problème, l’un des membres de notre équipe me donne une solution. Pour autoriser la position du correctif div et par rapport à une autre div, notre solution consiste à utiliser un conteneur père encapsulant le div et le scroll div.

 

css

 .container { position: relative; flex:1; display:flex; } .fix { prosition:absolute; } 

J’ai fait quelque chose comme ça il y a quelque temps. J’étais assez nouveau en JavaScript, donc je suis sûr que vous pouvez faire mieux, mais voici un sharepoint 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 devrez définir votre largeur, puis la largeur de la fenêtre et changer la marge toutes les quelques secondes. Je sais que c'est lourd, mais ça marche.

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

Mon projet est le modèle .NET ASP Core 2 MVC Angular 4 avec Bootstrap 4. L’ajout de “sticky-top” dans le composant d’application principal html (par exemple, app.component.html) sur la première ligne a fonctionné comme suit:

 

Vérifie ça: