固定位置,但相对于容器


639

我正在尝试使用以下方法修复一个问题div,使其始终停留在屏幕顶部:

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

但是,那 div位于内部居中容器中。当我使用position:fixed它时,它div相对于浏览器窗口进行了修复,例如它靠在浏览器的右侧。相反,它应该相对于容器固定。

我知道 position:absolute可以用来相对于修复元素div,但是当您向下滚动页面时,该元素消失并且不会像那样粘在顶部position:fixed

是否有破解或解决方法来实现这一目标?


“ Tether是一个低级的UI库,可用于将页面上的任何元素放置在任何其他元素旁边。” github.com/shipshapecode/tether + Demos / Docs在tether.io
Kai Noack

Answers:


407

简短的回答:不。(现在可以使用CSS转换。请参见下面的编辑)

长答案:使用“固定”定位的问题是它使元素脱离流动。因此无法相对于其父对象重新定位,因为好像它没有父对象。但是,如果容器的宽度是已知的固定宽度,则可以使用以下方法:

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

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

编辑(03/2015):

这是过时的信息。现在,借助CSS3转换的魔力,可以将动态大小的内容(水平和垂直)居中。遵循相同的原则,但是可以使用代替使用边距来偏移容器translateX(-50%)。这不适用于上面的边距技巧,因为除非宽度固定,否则您不知道要偏移多少,并且您不能使用相对值(如50%),因为它将相对于父元素而不是相对于它的元素应用于。 transform表现不同。其值相对于它们所应用的元素。因此,50%for transform表示元素宽度的一半,而50%for margin表示父元素宽度的一半。这是个 IE9 +解决方案

使用与以上示例类似的代码,我使用完全动态的宽度和高度重新创建了相同的场景:

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

如果希望它居中,也可以这样做:

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

演示:

jsFiddle:仅水平居中jsFiddle:仅
水平居中
原始功劳归用户aaronk6指出,在此答案中


为我做得很漂亮。尽管我需要我的div左边并且已经居中且未固定div,所以只需要减小左边距,直到对齐即可。无论窗户的宽度如何,都不会保持对齐。谢谢。+1
伊恩·诺曼

9
@Joseph知道为什么position:fixed不指定topleft 有时有效吗?如果元素的位置正常,某些浏览器似乎会将元素的默认位置恢复为通常的位置。stackoverflow.com/questions/8712047/…–
Flash

2
没有固定的高度和宽度怎么办?就我而言,我没有给任何容器提供任何信号宽度,甚至没有到body tag。您会说我该怎么办。
mfq

1
@mfq不幸的是,如果没有已知的高度和宽度,此方法将根本无法工作。您选择的内容在很大程度上取决于您要确定的重点。如果是图像,则将其用作100%x 100%容器的背景。如果它是完全动态的实际元素,则可能必须使用javascript解决方案进行探索以获取尺寸。
Joseph Marikle

2
我发现添加left:inherit到固定位置元素可以强制浏览器遵守父级的偏移量。
Willster 2014年

180

实际上这是可能的,并且被接受的答案仅涉及集中,这很简单。另外,您确实不需要使用JavaScript。

这将使您处理任何情况:

设置好一切,你会如果你要的位置:位置内绝对的:相对的容器,然后创建一个DIV中一个新的固定位置格position: absolute,但没有设置它的顶部和左侧属性。然后,它将相对于容器固定在所需的位置。

例如:

/* 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>

可悲的是,我希望该线程可以解决Android WebKit渲染框阴影模糊像素作为固定位置元素上的空白的问题,但这似乎是一个错误。
无论如何,我希望这会有所帮助!


1
并非任何情况,但这都是一个好的开始。如果.wrapper下有很多空间,则.fixed-wrapper将在父级的底部结束,但是.fixed元素将继续从这两个容器中流出,并流入下面的任何内容中。就像我说的那样,这是一个好的开始,不是一个完美的开始,但是我不知道如果没有一些js怎么可以做到这一点。
o_O 2013年

4
但是,这在流体设计中不能很好地发挥作用。
Zuhaib Ali 2014年

3
我试图做到这一点,但是当我向下滚动时,我滚动固定时所应用的标头(与父级相对的父级绝对值)并没有移动。
Mirage 2014年

这对我在Chromium和Firefox中的右上角div起作用,但固定div的垂直位置不同(在Chromium上它位于父div的顶部,在Firefox上位于其内部)。
Damien 2014年

2
这就是我的答案!感谢@Graeme Blackwood
Tabu.Net

136

是的,根据规格,有一种方法。

尽管我同意Graeme Blackwood的答案是可以接受的答案,因为它实际上可以解决问题,但应注意,可以将固定元素相对于其容器放置。

我偶然发现申请时

-webkit-transform: translateZ(0);

相对于它,它相对于它是一个固定的子对象(而不是视口)。因此,我的固定元素lefttop属性现在相对于容器。

因此,我进行了一些研究,发现该问题已经被Eric Meyer所涵盖,即使感觉像是“绝招”,事实证明,这也是规范的一部分:

对于其布局由CSS盒模型控制的元素,转换中除“ none”以外的任何值都将同时创建堆栈上下文和包含块。该对象充当固定位置后代的包含块。

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

因此,如果将任何转换应用于父元素,它将成为包含块。

但...

问题在于实现似乎是错误的/创造性的,因为元素也停止了固定的行为(即使此位似乎不属于规范的一部分)。

在Safari,Chrome和Firefox中会发现相同的行为,但在IE11中不会发现(固定元素仍将保持固定)。

另一个有趣的(未记录)的事情是,当固定元素包含在转换后的元素中时,尽管它的topleft属性现在将与容器相关联,同时尊重该box-sizing属性,但其滚动上下文将在元素的边界上延伸,就像框一样-sizing设置为border-box。对于那里的一些创意,这可能会成为一种玩物:)

测试


4
这使我能够在容器内
Zach Saucier 2013年

好的,这对我在Chrome中有效。关于如何在IE中实现相同的任何想法?我试过使用translateZ,但在任何版本的IE中都没有。
阿尼斯·帕特尔

同样..有人知道如何在IE中执行此操作吗?检测浏览器,然后系统显示或不显示left:(考虑将其弄乱)是一种痛苦
Tallboy 2014年

我只是遇到了相反的情况,我需要在相对的容器中进行固定,但要通过transform属性进行更改。您的回答非常有帮助,谢谢!
mytharcher 2014年

8
@Francesco Frapporti似乎不再起作用了……在最新版本的Chrome中(版本42.0.2311.90):(
jjenzz

60

答案是肯定的,只要您未设置left: 0right: 0将div位置设置为fixed之后即可。

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

检出侧边栏div。它是固定的,但与父项有关,与窗口视点无关。

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>

12
为什么没有得到更多支持?对我来说似乎是最明显的解决方案。
跟踪

跨浏览器兼容性如何?你们有没有检查过这个?
Alexandre Bourlier 2015年

3
这是正确的,但仅适用于固定元素的“定位”。它不会以任何方式尊重容器的宽度或大小。例如,如果您有一个max-width:1000px的流体包装器;保证金:自动; 这是行不通的。如果一切都可以是固定宽度,那么可以解决您的问题。
Rhys

3
@AlexandreBourlier是的,至少对于Chrome,Firefox和IE11中的固定元素,这对我来说效果很好。
杰森·弗兰克

工作完美。必须添加margin-left:X%来将元素移到容器的右侧
Anand

45

position: sticky这是一种定位元素的新方法,在概念上与position: fixed。不同之处在于元素的position: sticky行为类似于position: relative其父元素,直到在视口中满足给定的偏移阈值为止。

在Chrome 56(目前为2016年12月测试版,2017年1月稳定)中:粘性现在又回来了。

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

有关更多详细信息,请保持着陆!位置:WebKit中的粘性土地


这使生活变得更加轻松,唯一的问题是Internet Explorer或Edge 15及更早版本不支持粘性。
里克斯(Ricks)

1
position:sticky是很棒的。通过支持除IE以外所有浏览器caniuse.com/#feat=css-sticky
Yarin

大声笑,这么老的api,您就节省了我的时间...即时通讯将其用于flex表的固定列。
弗拉迪斯拉夫·格里申科

1
“在其父级内”-如果父级向上滚动变得不可见,是否有可能将粘性元素保留在顶部?
Fikret

28

2019解决方案:您可以使用position: sticky财产。

这是一个示例CODEPEN,演示了用法以及与用法有何不同position: fixed

其行为说明如下:

  1. 根据用户的滚动位置来定位具有粘性位置的元素。基本上,其作用类似于position: relative直到元素滚动到特定偏移量为止,在这种情况下,它会变成位置:固定。向后滚动时,它将返回到其先前(相对)位置。

  2. 它会影响页面中其他元素的流动,即占据页面上的特定空间(就像position: relative)。

  3. 如果将其定义在某个容器内,则相对于该容器定位。如果容器有一些溢出(滚动),则取决于滚动偏移量,它会变为position:fixed。

因此,如果要在容器内部实现固定功能,请使用粘性。


不错的解决方案。我不知道position: sticky呢。帮助很大,谢谢!
dave0688 '19

我正要发布这个。好答案!黏是方式。
dkellner,

18

只需从固定位置div中取出顶部和左侧样式即可。这是一个例子

<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> 

#content div将位于父div所在的任何位置,但将固定在该位置。


3
为什么减?这非常适合在DOM流中的任何位置固定元素。deadlykitten.com/tests/fixedPositionTest.php
hobberwickey 2012年

18

我已经创建了这个jQuery插件来解决我在居中放置容器(表格数据)时遇到的类似问题,并且我希望在滚动列表时将标头固定到页面顶部,但我希望将其锚定到表格数据,因此它可以放在我放置容器的任何位置(居中,向左,向右),并且在水平滚动时还可以使其随页面左右移动。

这是可以解决此问题的jQuery插件的链接:

https://github.com/bigspotteddog/ScrollToFixed

该插件的说明如下:

如果该元素会垂直滚动出视图,则该插件用于将元素固定在页面顶部。但是,它确实允许元素随着水平滚动继续向左或向右移动。

给定一个marginTop选项,一旦垂直滚动到达目标位置,元素将停止垂直向上移动;否则,元素将停止垂直移动。但是,当页面向左或向右滚动时,元素仍将水平移动。页面向下滚动到目标位置后,该元素将恢复到页面上的原始位置。

此插件已在Firefox 3/4,Google Chrome 10/11,Safari 5和Internet Explorer 8/9中经过测试。

特定情况的用法:

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

12

我必须做一个广告,说我的客户想坐在内容区域之外。我只是简单地进行了以下操作,它就像一个魅力!

<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>

我的广告宽度为140像素,因此我将其向左移动了150像素,以使其相对于网站框架的边缘略微留有空白。
埃里克K

7

两个HTML元素和纯CSS(现代浏览器)

请参阅此jsFiddle示例。调整大小并查看固定元素甚至如何与它们所在的浮动元素一起移动。使用最里面的滚动条查看滚动在站点上的工作方式(固定元素保持固定)。

由于这里的许多人所指出的,一个密钥不上设置任何位置设置fixed元素(无toprightbottom,或者left值)。

相反,我们将所有固定元素(请注意最后一个盒子中有四个元素)放在要放置它们的盒子中的第一位,如下所示:

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

然后,我们使用margin-top和相对margin-left于其容器“移动”它们,就像此CSS一样:

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

请注意,由于fixed元素会忽略所有其他布局元素,因此小提琴中的最终容器可以具有多个fixed元素,并且仍然具有与左上角相关的所有那些元素。但这只有在它们都首先放置在容器中的情况下才是正确的,因为此比较小提琴表明,如果将它们分散在容器内容物中,则定位将变得不可靠

包装器的位置是静态的相对的还是绝对的,都没有关系。


3

您可以尝试一下我的jQuery插件FixTo

用法:

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

2

实现相对固定位置的另一种奇怪的解决方案是将容器转换为iframe,这样就可以将固定元素固定到容器的视口而不是整个页面。


2

使用纯CSS,您将无法做到;至少我没有。但是,您可以使用jQuery非常简单地做到这一点。我将解释我的问题,只需稍作更改即可使用它。

因此,一开始,我希望我的元素具有固定的顶部(从窗口顶部开始),并具有一个从父元素继承的左侧组件(因为父元素居中)。要设置左侧组件,只需将您的元素放入position:relative父元素并设置为父元素。

然后,当滚动条位于顶部(y零滚动)时,您需要知道元素从顶部开始的多少;再次有两个选择。首先是静态的(一些数字),或者您必须从父元素中读取它。

以我为例,它离顶部静态像素有150像素。因此,当您看到150时,就是我们没有滚动时从顶部算起的元素数。

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

问题是滚动时相关的div闪烁。
vvohra87

可能是因为滚动刷新太多或太快。我没有那个问题,但我建议您尝试使用全局“阻止程序”,例如每10毫秒或一段时间会刷新一次,并在每次更改高度时将其设置为阻止值。当然,您必须在.scroll事件中添加if条件,以检查是否已在此时间段(10ms)中滚动了div。我再说一遍,我没有尝试过,但是我相信它可以工作:)这样一来,您可以阻止div改变其位置太多,以致于计算机无法真正跟随,并且足够人眼可以看到。
Br Br

我已经给您的答案+1伴侣;)附加全局循环方法的痛苦实际上就是性能。要使类似的东西在较旧的PC和平板电脑上正常工作是很痛苦的。初级开发人员经常在这种方法中编写“ var x”,如果页面打开时间过长,则会导致不必要的内存泄漏:P但是,是的,您的建议似乎是唯一选择。
vvohra87

您了解全局循环;不好,我同意。我只是想考虑这种问题,所以才写了另一个建议:) Tbh,现在看起来好多了,我会避免它xD我现在有了另一个解决方案。关于在调用func的滚动事件上设置setTimeout()的内容。这会导致div移动..您还可以使用全局阻止程序,在等待超时时将其设置为true,当调用超时时,您将阻止程序返回为false,这会在一段时间后启用另一个调用...这样您就不会使用全局循环但仍然可以控制div移动的频率。
Br Br先生

它更优雅,但我很难接受。我希望这是html和css规范来处理tbh的问题。讨厌首先涉及到js的事实!
vvohra87

1

这很容易(按照下面的HTML)

诀窍是不要在元素(div)的顶部或左侧使用“ position:fixed;”。如果未指定这些内容,则“固定内容”元素将相对于封闭元素(带有“ position:relative;”的div)相对于浏览器窗口出现!

<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>

上面的内容使我可以在带有垂直滚动的div中许多文本的顶部找到一个关闭的“ X”按钮。“ X”位于适当位置(不会随着滚动文本一起移动,但是当用户调整浏览器窗口的宽度大小时,它确实会与封闭的div容器一起向左或向右移动!因此它是垂直“固定”的,但相对于水平包围元素!

在进行此工作之前,向下滚动文本内容时,“ X”会向上滚动并看不见。

很抱歉没有提供我的javascript hideDiv()函数,但是会不必要地延长这篇文章的时间。我选择使其尽可能短。


可靠的跨浏览器解决方案,可像在IE8中一样发挥作用。
dmi3y 2015年

1

我创建了一个jsfiddle来演示如何使用转换工作。

的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

我有同样的问题,我们的团队成员之一给了我一个解决方案。为了允许div固定位置以及相对于其他div的位置,我们的解决方案是使用父容器包装固定div并滚动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
/* 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%);
}

1

是的,只要您不设置元素的位置(topleft等),fixed就可以(margin尽管您仍然可以使用它来设置相对位置)。西蒙·博斯(Simon Bos)前不久对此发表了评论

但是,不要指望固定元素与非固定亲戚一起滚动。

在此处查看演示


0

我不久前做了类似的事情。我刚接触JavaScript,因此可以肯定您可以做得更好,但这是一个起点:

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

您将需要设置宽度,然后它获取窗口宽度并每隔几秒钟更改边距。我知道它很重,但是可以用。


我可以用这种方法看到的一个问题是,它依赖计时器(2.5秒),在此期间,如果用户调整窗口的大小,则需要花费该时间来校正它。就用户体验而言,这并不是最好的选择。另外,如果有帮助,请尝试使用事件侦听器而不是计时器。
Joseph Marikle 2011年

就像我说的是OLD脚本,这是我的第一个脚本,不需要回去修复它。因此,这不是最好的方法,但是它可以是一个很好的起点。
webLacky3rdClass 2011年


0

我的项目是带有Bootstrap 4的.NET ASP Core 2 MVC Angular 4模板。将“ sticky-top”添加到第一行的主要应用程序组件html(即app.component.html)中,如下所示:

<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>

那是惯例还是我简化了?


0

当您使用position:fixedCSS规则,并尝试应用top/ left/ right/ bottom它相对于窗口元素位置。

解决方法是使用margin属性代替top/ left/ right/bottom


-1

检查一下:

<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>

5
我认为这并不能完全满足OP的要求。
杰森怀亚特(JasonWyatt)2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.