首页 文章

固定位置但相对于容器

提问于
浏览
529

我正在尝试修复一个 div 所以它总是粘在屏幕顶部,使用:

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

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

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

有没有一个黑客或解决方法来实现这一目标?

21 回答

  • 353

    简答:不 . (现在可以使用CSS转换 . 请参阅下面的编辑)

    答案很长:使用"fixed"定位的问题在于它需要元素 out of flow . 因此它可以't be re-positioned relative to its parent because it',好像它没有一个 . 但是,如果容器具有固定的已知宽度,则可以使用以下内容:

    #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指出它给我

  • 2

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

    这将让您处理任何场景:

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

    例如:

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

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

    虽然我同意格雷姆·布莱克伍德应该是公认的答案,因为它实际上解决了这个问题,但应该注意的是,固定元素相对于其容器是定位的 .

    申请时我偶然注意到了

    -webkit-transform: translateZ(0);
    

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

    所以我做了一些研究,发现这个问题已经被Eric Meyer涵盖了,即使它感觉像是"trick",结果证明这是规范的一部分:

    对于布局由CSS框模型控制的元素,转换的除none之外的任何值都会导致创建堆叠上下文和包含块 . 该对象充当固定定位后代的包含块 .

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

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

    但......

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

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

    另一个有趣的(未记录的)是当一个固定元素包含在一个转换元素中,而它的 topleft 属性现在将与容器相关,尊重 box-sizing 属性,它的滚动上下文将扩展到元素的边界,好像box-sizing设置为 border-box . 对于那里的一些创意,这可能成为一个玩物:)

    TEST

  • 0

    答案是肯定的,只要在将div位置设置为fixed后不设置 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>
    
  • 21

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

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

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

    更多细节见Stick your landings! position: sticky lands in WebKit .

  • 0

    我创建了这个jQuery插件来解决我遇到的类似问题,我有一个居中的容器(表格数据),我希望在滚动列表时将 Headers 修复到页面顶部,但我希望它锚定到表格数据,所以它放在容器(中心,左,右)的任何地方,并允许它在水平滚动时左右移动页面 .

    以下是此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();
    });
    
  • 155

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

  • 1

    我不得不用我的客户希望坐在内容区域之外的广告来做这件事 . 我只是做了以下,它就像一个魅力!

    <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

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

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

    正如许多人所述,一个关键是没有在 fixed 元素上设置任何位置设置(没有 toprightbottomleft 值) .

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

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

    然后我们使用 margin-topmargin-left 到"move"它们与容器相关,就像这个CSS一样:

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

    请注意,因为 fixed 元素忽略所有其他布局元素,所以最终容器in our fiddle可以有多个 fixed 元素,并且仍然具有与左上角相关的所有元素 . 但这只有在它们全部放在容器中时才会出现,as this comparison fiddle shows that if dispersed within the container content, positioning becomes unreliable .

    无论封装器在定位中是staticrelative还是absolute,都没关系 .

  • 6

    如果你使用JavaScript,这是可能的 . 在这种情况下,jQuery插件Sticky-Kit

  • 54

    You can use position: sticky property.

    这是一个示例CODEPEN,演示了用法以及它与 position: fixed 的区别 .

    它的表现如下:

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

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

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

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

  • 18

    你可以尝试我的jQuery插件,FixTo .

    用法:

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

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

  • 3

    使用纯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');
    });
    
  • 2

    这很容易(根据HTML下面)

    诀窍是不要在元素(div)上使用top或left,“position:fixed;” . 如果未指定这些,则“fixed content”元素将显示为RELATIVE为封闭元素(具有“position:relative;”的div)相对于浏览器窗口的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()函数,但它会不必要地使这篇文章变得更长 . 我选择尽可能地缩短它 .

  • 0

    我创建了一个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/

  • 0

    我有同样的问题,我们的团队成员之一给了我一个解决方案 . 为了允许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

    我做了类似的事情 . 我对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)
    }
    

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

  • 1

    我的项目是带有Bootstrap 4的.NET ASP Core 2 MVC Angular 4模板 . 在第一行工作中将“sticky-top”添加到主app组件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>
    

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

  • 17
    /* 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%);
    }
    
  • 119

    检查一下:

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

相关问题