固定位置但相对于容器

时间:2011-07-22 17:47:01

标签: css position css-position fixed

我正在尝试修复div,因此它总是贴在屏幕顶部,使用:

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

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

我知道position:absolute可用于修复相对于div的元素,但是当您向下滚动页面时,该元素会消失,并且不会像{{1 }}

是否有实现此目的的黑客攻击或解决方法?

26 个答案:

答案 0 :(得分:367)

简答: no。(现在可以使用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% transform表示元素宽度的一半,而边距50%表示父元素宽度的一半。这是IE9+ solution

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

.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: Centered horizontally only
jsFiddle: Centered both horizontally and vertically
原始赠送给用户aaronk6,以便在this answer

中向我指出

答案 1 :(得分:162)

实际上这是可能的,并且接受的答案仅涉及集中化,这很简单。你真的不需要使用JavaScript。

这将让您处理任何情况:

设置所有内容,如果你想要定位:绝对位置:相对容器,然后在div中用position: absolute创建一个新的固定位置div,但是设置其顶部和左侧属性。然后,它将相对于容器固定在您想要的任何位置。

例如:

/* 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渲染框阴影模糊像素作为固定位置元素的边距,但似乎这是一个错误。
无论如何,我希望这个帮助!

答案 2 :(得分:125)

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

虽然我同意Graeme Blackwood应该是公认的答案,因为它实际上解决了这个问题,但应该注意固定元素可以相对于其容器定位。

我在申请时意外注意到

-webkit-transform: translateZ(0);

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

所以我做了一些研究,发现Eric Meyer已经涵盖了这个问题,即使它感觉像是一个“技巧”,但事实证明这是规范的一部分:

  

对于布局由CSS框模型控制的元素,任何值   除了没有变换导致两者的创建   堆叠上下文和包含块。该对象充当   包含固定位置后代的块。

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

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

但是...

问题在于实现似乎有缺陷/创造性,因为元素也会停止表现为固定(即使这个位似乎不是规范的一部分)。

在Safari,Chrome和Firefox中可以找到相同的行为,但IE11中不会出现相同的行为(固定元素仍然保持固定)。

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

TEST

答案 3 :(得分:57)

答案是肯定的,只要您在将div位置设置为固定后未设置left: 0right: 0

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>

答案 4 :(得分:28)

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

在Chrome 56中(目前为2016年12月的测试版,2017年1月稳定)位置:粘性现已回归。

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

更多详情请参阅 Stick your landings! position: sticky lands in WebKit

答案 5 :(得分: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();
});

答案 6 :(得分:17)

只需将固定位置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所在的位置,但会在那里修复。

答案 7 :(得分: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>

答案 8 :(得分:7)

您可以使用position: sticky属性。

以下示例CODEPEN演示了该用法以及它与position: fixed的区别。

如何表现如下:

  1. 根据用户的滚动位置定位具有粘性位置的元素。它基本上像position: relative一样,直到一个元素滚动超过特定的偏移量,在这种情况下它转变为position:fixed。当它向后滚动时,它会回到之前的(相对)位置。

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

  3. 如果在某个容器内定义它,则它相对于该容器定位。如果容器有一些溢出(滚动),根据滚动偏移,它会变成位置:固定。

  4. 因此,如果您想要在容器内实现固定功能,请使用sticky。

答案 9 :(得分:7)

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

See this jsFiddle example. 调整大小并查看固定元素如何随着它们所处的浮动元素移动。使用最里面的滚动条查看滚动在网站上的工作方式(固定元素保持固定)。

正如许多人所述,一个关键是没有在fixed元素上设置任何位置设置(无toprightbottom或{{1} }))。

相反,我们将所有固定元素(注意最后一个方框中有四个是如何)放在它们要放置的框中,如下所示:

left

然后我们使用<div class="reference"> <div class="fixed">Test</div> Some other content in. </div> margin-top来“移动”它们与容器的关系,就像这个CSS一样:

margin-left

请注意,由于.fixed { position: fixed; margin-top: 200px; /* Push/pull it up/down */ margin-left: 200px; /* Push/pull it right/left */ } 元素会忽略所有其他布局元素,因此最终容器in our fiddle可以包含多个fixed元素,并且仍然具有与左上角相关的所有元素。但只有当它们全部放在容器as this comparison fiddle shows that if dispersed within the container content, positioning becomes unreliable中时才会出现这种情况。

包装器在定位中是staticrelative还是absolute,无关紧要。

答案 10 :(得分:3)

是的,只要您不设置top元素的位置(leftfixed等)(您仍然可以使用{{1} }来设置相对位置)。西蒙·博斯posted about this a while ago

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

查看demo here

答案 11 :(得分:3)

您可以试试我的jQuery插件FixTo

用法:

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

答案 12 :(得分: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');
});

答案 13 :(得分:2)

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

答案 14 :(得分:1)

这很容易(根据下面的HTML)

诀窍是不要在元素(div)上使用top或left,“position:fixed;”。 如果未指定这些,则“fixed content”元素将显示为RELATIVE为封闭元素(div为“position:relative;”)INSTEAD OF相对于浏览器窗口!!!

<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()函数,但它会不必要地使这篇文章变得更长。我选择尽量缩短它。

答案 15 :(得分:1)

我创建了一个jsfiddle来演示如何使用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/

答案 16 :(得分: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;
}

答案 17 :(得分: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%);
}

答案 18 :(得分:0)

如果容器使用某些 containment 规则,则可以相对于其容器以固定位置定位元素。

<div class='parent'>
  <div class='child'></div>
<div>
.parent {
  contain: content;
}

.child {
  position: fixed;
  top: 0;
  left: 0;
}

答案 19 :(得分:0)

魔术是将屏幕宽度减去容器宽度,然后除以2:

//1400px is according to container max-width (left can be also right)
.fixed {
  position: fixed;
  right: calc((100vw - 1400px)/2);
}

注意:几乎支持css calc()函数,但不100%支持。对于大多数用例来说,它绝对是受支持的。 Click here了解更多详情

摘要(带有300px的容器,仅适合该网站的小部件):

.container {
  max-width: 300px;
  margin-left: auto;
  margin-right: auto;
}


.fixed {
  position: fixed;
  right: calc((100vw - 300px)/2);
}


@media screen and (max-width: 300px) {
  right: 0px;
}
<div style="height: 3000px">
    <div class="container">
        <button class="fixed">
            FIXED CONTENT
        </button>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum, eum? Animi quidem accusamus minima vel, dolorem suscipit quia accusantium minus harum modi commodi distinctio! Iste voluptatum earum quam voluptate culpa ad, ipsum dolorum recusandae quis atque eligendi necessitatibus magnam nisi dolores beatae qui? Perspiciatis natus cum nostrum in quod odio sapiente doloremque rerum quo dolore tenetur facere, quisquam atque accusamus fugiat eligendi, deleniti nisi minus recusandae distinctio dignissimos! Dicta quos ipsum qui pariatur at vel veritatis veniam quisquam minus modi et voluptas aliquam laborum, cumque in quo magnam sapiente. Expedita ut dolore laboriosam tempora reprehenderit vero eaque blanditiis, cumque voluptatibus, velit nemo, veniam tenetur quisquam numquam adipisci quae odio repellendus neque incidunt! Cum odio corporis soluta voluptate nesciunt, quasi nobis deleniti neque porro expedita fugiat placeat alias autem pariatur animi error, dicta veritatis atque perspiciatis inventore tempora dolor ad! Mollitia in dolorem ipsam eos porro magni perspiciatis possimus maiores, itaque facere ut. Eos culpa eum error quia incidunt repellendus quam possimus, asperiores earum ipsum molestias dicta sint fugit atque veniam dolorum illo? Officia harum sint incidunt totam, reiciendis illum eos maxime sequi neque repellat quis, expedita eum, corporis quaerat nemo qui soluta aspernatur animi. Sint ad rem numquam omnis sit.
    </div>
 </div>

答案 20 :(得分:0)

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

一种解决方法是使用margin属性而不是top / left / right / bottom

答案 21 :(得分:0)

免责声明:

这仅回答标题:固定位置,但相对于容器。 对于实际用例,用户要求使用position: sticky是一种解决方法。


https://developer.mozilla.org/en-US/docs/Web/CSS/position

相对于由视口建立的初始包含块定位,除非其祖先之一的transform,perspective或filter属性设置为非none

您只需要向容器添加一个转换,固定元素的位置将相对于容器。我认为transform: translateX(0);就足够了。

答案 22 :(得分:0)

我的项目是带有Bootstrap 4的.NET ASP Core 2 MVC Angular 4模板。添加&#34; sticky-top&#34;在第一行工作的主应用程序组件html(即app.component.html)中,如下所示:

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

这是惯例还是我过度简化?

答案 23 :(得分:0)

如果您使用JavaScript,则可能。在这种情况下,jQuery插件 Sticky-Kit

答案 24 :(得分: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)
}

您需要设置宽度,然后获取窗口宽度并每隔几秒更改一次边距。我知道它很重,但它确实有效。

答案 25 :(得分:-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>