关于CSS:固定位置,但相对于容器

Fixed position but relative to container

我正在尝试修复div,因此它始终使用以下方法固定在屏幕顶部:

1
2
3
position: fixed;
top: 0px;
right: 0px;

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

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

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


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

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

1
2
3
4
5
6
7
8
#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的行为有所不同。其值相对于它们所应用的元素。因此,transform50%表示元素宽度的一半,而空白的50%表示父元素宽度的一半。这是IE9 +解决方案

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

1
2
3
4
5
6
7
8
.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 0%;
    transform: translateX(-50%);
}

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

1
2
3
4
5
6
7
8
.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

演示:

jsFiddle:仅水平居中
jsFiddle:水平和垂直居中

原始信誉归用户aaronk6指出,在此答案中向我指出了这一点


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

这将使您处理任何情况:

设置所有内容,如要在位置:相对容器中定位:absolute,然后使用position: absolute在div内创建新的固定位置div,但不要设置其top和left属性。然后,它将相对于容器固定在所需的位置。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 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! */
}
1
            Content in here will be fixed position, but 240px to the left of the site body.

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


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

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

我偶然发现申请时

1
-webkit-transform: translateZ(0);

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

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

For elements whose layout is governed by the CSS box model, any value
other than none for the transform results in the creation of both a
stacking context and a containing block. The object acts as a
containing block for fixed positioned descendants.

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

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

但...

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

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

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

测试


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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
    sidebar
    main


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


2019解决方案:您可以使用position: sticky属性。

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

其行为说明如下:

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

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

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

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


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

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

    https://github.com/bigspotteddog/ScrollToFixed

    该插件的说明如下:

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

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

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

    特定情况的用法:

    1
    2
    3
    4
    5
    6
    <script src="scripts/jquery-1.4.2.min.js" type="text/javascript">
    <script src="scripts/jquery-scrolltofixed-min.js" type="text/javascript">

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

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

    1
            content

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


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

    1
        <img src="###" />


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

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

    如此处许多人所述,一个键没有在fixed元素上设置任何位置设置(没有toprightbottomleft值)。

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

    1
    2
      Test
      Some other content in.

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

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

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

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


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

    用法:

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

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


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

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

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

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

    的CSS

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

    jQuery的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $(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');
    });


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

    的HTML

    1
    2
    3
    4
    5
    6
    7
        Content



        X

        Side bar

    的CSS

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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的

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

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


    我有同样的问题,我们的团队成员之一给了我一个解决方案。
    要允许div固定位置和相对于其他div的位置,我们的解决方案是使用父容器包装固定div并滚动div。

    1
     

    的CSS

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .container {
      position: relative;
      flex:1;
      display:flex;
    }

    .fix {
      prosition:absolute;
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    /* html */

    /* this div exists purely for the purpose of positioning the fixed div it contains */


         
              my fixed content
         





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

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

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

    1
    2
    3
    4
    5
    6
    7
                    <span style="font-size:18pt; font-weight:bold;">X</span>
               
           
       
          <!-- container for... -->
             lots of Text To Be Scrolled vertically...
             bhah! blah! blah!

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

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

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


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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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)
    }

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
            <nav-menu-top></nav-menu-top>
       


       
            <nav-menu></nav-menu>
       
       
            <router-outlet></router-outlet>

    那是惯例还是我简化了?


    检查一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
           
        </head>
        <body style="width: 1000px !important;margin-left: auto;margin-right: auto">
           
           
           
           
           
           
           
           
        </body>
    </html>