我可以定位相对于父元素固定的元素吗? [复制]

Posted

技术标签:

【中文标题】我可以定位相对于父元素固定的元素吗? [复制]【英文标题】:Can I position an element fixed relative to parent? [duplicate] 【发布时间】:2011-07-09 18:00:59 【问题描述】:

我发现当我定位一个元素时,无论父元素是否相对定位,它都会相对于窗口定位固定?

#wrapper 
  width: 300px;
  background: orange;
  margin: 0 auto;
  position: relative;


#feedback 
  position: fixed;
  right: 0;
  top: 120px;
<div id="wrapper">
    ...
    <a id="feedback" href="#">Feedback</a>
</div>

http://jsbin.com/ibesa3

【问题讨论】:

正确答案在这里***.com/questions/4962266/… "position:sticky" 将是解决方案。截至 2016 年 4 月,Firefox 似乎是唯一支持此功能的浏览器 (caniuse.com/#feat=css-sticky)。 在最近的浏览器中(在提出这个问题后发布),有更好的解决方案。请参阅标记为2016 update 的答案 【参考方案1】:

CSS 规范要求position:fixed 锚定到视口,而不是包含定位元素。

如果您必须指定相对于父元素的坐标,则必须先使用 javascript 找到父元素相对于视口的位置,然后相应地设置子(固定)元素的位置。

替代:一些浏览器支持sticky CSS,这限制了元素在其容器和视口中的定位。根据提交消息:

sticky ... 将元素限制在其容器盒和视口的交点内。

粘性定位元素的行为类似于 position:relative(空格是 保留为其流入),但偏移量由 粘性位置。更改 isInFlowPositioned() 以涵盖相对和 粘性。

根据您的设计目标,此行为在某些情况下可能会有所帮助。它目前是一个工作草案,除了表格元素外,还得到了不错的支持。 position: sticky 在 Safari 中仍然需要 -webkit 前缀。

有关浏览器支持的最新统计信息,请参阅 caniuse。

【讨论】:

@rayfranco:不过已经很久了;我的猜测是操作更改了他的设计以匹配 DuckMaestro 的答案(这是一个更简单的设计),这就是它被接受的原因? @Jon,如果您单击帖子“已编辑”注释后的日期时间,您实际上可以看到编辑历史记录。 @JohnK 我知道。 “改变他的设计”是指操作在网站上使用的最终代码——不是对这里提出的问题的改变。 这不是一个好的解决方案,Chrome 不再支持-webkit-sticky(除非您启用实验标志)。它可能会在某个时候恢复,但在正式支持之前,最好使用 Grawl 的解决方案。 我刚刚更新了这个答案,因为sticky 有很好的支持。【参考方案2】:

让我回答这两个可能的问题。请注意,您现有的标题(和原始帖子)提出的问题不同于您在编辑和后续评论中寻求的问题。


要相对于父元素“固定”定位元素,您需要在子元素上使用position:absolute,并在父元素上使用除默认或静态以外的任何位置模式。 p>

例如:

#parentDiv  position:relative; 
#childDiv  position:absolute; left:50px; top:20px; 

这会将childDiv 元素定位在相对于 parentDiv 的位置向左 50 像素和向下 20 像素的位置。


要相对于窗口“固定”定位元素,您需要position:fixed,并且可以使用top:left:right:bottom: 定位为你觉得合适。

例如:

#yourDiv  position:fixed; bottom:40px; right:40px; 

这会将yourDiv 定位为相对于网络浏览器窗口固定的位置,距离底部边缘 40 像素,距离右侧边缘 40 像素。

【讨论】:

哦,嗯...我实际上想模仿一个粘性按钮,当它绝对定位时,当我向下滚动时,它不粘性......嗯 @将与选择它作为答案的 OP 一起讨论。显然他在稍后的某个阶段对他的问题进行了编辑。我并不急于删除这个答案,因为仍然有人显然觉得它很有用(8 票赞成),并且是对问题标题的回答。如果不同的答案现在是更好的答案,则 OP 应该选择不同的接受答案。 @DuckMaestro 在带有滚动条的溢出 div 中执行此操作怎么样? position:absolute 会让它随之滚动。 虽然这个解决方案实际上可能使 OP 受益,但它并没有回答标题中提出的问题。这个下面的答案要准确得多,应该标记为正确的。 您应该更新您的答案,因为 calc 可以帮助我们轻松解决这个问题。假设您的主容器的初始值可以增长到 900 像素,您可以在断点命中 css @media screen and (min-width: 901px) right: calc((100% - 900px) / 2) 后设置为 right: 0px,这将再次将这些元素附加到您的主容器。【参考方案3】:

2016 年更新

现在可以在现代浏览器中定位相对于其容器固定的元素。具有 transform 属性的元素充当其任何固定位置子元素的视口。

或者正如CSS Transforms Module 所说的那样:

对于布局由 CSS 框模型控制的元素,transform 属性的任何值(除了 none 之外)也会导致元素为所有后代建立一个包含块。它的填充框将用于为其所有绝对位置后代、固定位置后代和后代固定背景附件进行布局。

.context 
  width: 300px;
  height: 250px;
  margin: 100px;
  transform: translateZ(0);

.viewport 
  width: 100%;
  height: 100%;
  border: 1px solid black;
  overflow: scroll;

.centered 
  position: fixed;
  left: 50%;
  bottom: 15px;
  transform: translateX(-50%);
<div class="context">
  <div class="viewport">
    <div class="canvas">

      <table>
        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>
        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>

        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>

        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>
      </table>

      <button class="centered">OK</button>

    </div>
  </div>
</div>

【讨论】:

在 IE11 中不起作用 当具有absolute 定位的子元素在具有relativeabsolute 定位的父元素中行为相同时,为什么需要这样做? @Sean 当父元素有一个滚动条并且您希望在父元素在其后面滚动时保持固定位置元素。 我总是只在它周围放一个div,并且绝对定位到外部div,然后让内部div有滚动条。但是,有时您无法控制 html,很高兴知道这是有效的! 有几个不同的 CSS 属性具有这种效果。另一个是will-change: transform【参考方案4】:

首先,设置position: fixedleft: 50%,第二个——现在你的起点是一个中心,你可以设置新的位置和边距。

【讨论】:

这种方法要非常小心!如果固定元素不在视口中,它将无法按预期工作。如果视口太短,这个小提琴演示了这个问题。 jsbin.com/igolur/4/edit sticky 之前的最佳解决方案在更多浏览器中得到更好的支持。 您可以使用left: 50% (.parent) 在元素内部使用额外的包装器,并为其子元素(.child) 设置left: -50%,子元素将位于中心。提示:将pointer-events: none 用于.parent ;)【参考方案5】:

我知道这是超级旧的,但在没有找到我正在寻找的(纯 CSS)答案后,我想出了这个解决方案(部分从 medium.com 抽象出来),并认为它可能会帮助其他想要做同样事情的人。

如果您结合@DuckMaestro 的答案,您可以相对于父母(实际上是祖父母)定位一个固定的元素。使用position: absolute; 将元素定位在具有position: relative; 的父元素内,然后将position: fixed; 定位在绝对定位元素内的元素上,如下所示:

HTML

<div class="relative">
  <div class="absolute">
    <a class="fixed-feedback">This element will be fixed</a>
  </div>
</div>

CSS

.relative 
  margin: 0 auto;
  position: relative;
  width: 300px;


.absolute 
  position: absolute;
  right: 0;
  top: 0;
  width: 50px;


.fixed-feedback 
  position: fixed;
  top: 120px;
  width: 50px;

EXAMPLE

就像@JonAdams 所说,position: fixed 的定义要求元素相对于视口定位,但您可以使用此解决方案绕过水平方面。

注意:这与仅在固定元素上设置rightleft 值不同,因为这会导致它在调整窗口大小时水平移动。

【讨论】:

这似乎不像您声称的那样工作。该元素仍然相对于视口定位fixed,而不是包含元素。它的左/右位置没有改变,所以它保持在那个位置,但在真正意义上,它并不是根据它的父级固定的。看这个例子,我在父div上面加了一个div。 div.fixed-feedback 保持在距离窗口顶部 120 像素处。 codepen.io/anon/pen/LbvOaY @SeanKendle,这是正确的。如果元素是fixed 相对于父级,那么真正意义上的单词就是absolute。在这种情况下,它是fixed,垂直于视口,水平于父级。这就是我正在尝试的,因为这是我估计的问题似乎要问的问题。不过,我可能错了。 我同意,除非你说父级内部的absolute 本质上转换为fixed,因为如果它是absolute,滚动会导致它与父 div,不会像在真正的 fixed 位置那样保持静止。【参考方案6】:

这个解决方案对我有用!参考原文详细回答:https://***.com/a/11833892/5385623

css:

.level1 
    position: relative;



.level2 
    position: absolute;



.level3 
    position: fixed;
    /* Do not set top / left! */

html:

<div class='level1'>
    <div class='level2'>
        <div class='level3'>
            Content
        </div>
    </div>
</div>

【讨论】:

这个答案应该在上面【参考方案7】:

这是上面 Jon Adams 建议的一个示例,目的是使用 jQuery 将 div(工具栏)固定到页面元素的右侧。这个想法是找到从视口右侧到页面元素右侧的距离,并将工具栏的右侧保持在那里!

HTML

<div id="pageElement"></div>
<div id="toolbar"></div>

CSS

#toolbar 
    position: fixed;

....

jQuery

​​>
function placeOnRightHandEdgeOfElement(toolbar, pageElement) 
    $(toolbar).css("right", $(window).scrollLeft() + $(window).width()
    - $(pageElement).offset().left
    - parseInt($(pageElement).css("borderLeftWidth"),10)
    - $(pageElement).width() + "px");

$(document).ready(function() 
    $(window).resize(function() 
        placeOnRightHandEdgeOfElement("#toolbar", "#pageElement");
    );
    $(window).scroll(function ()  
        placeOnRightHandEdgeOfElement("#toolbar", "#pageElement");
    );
    $("#toolbar").resize();
);

【讨论】:

@Grawl ..JQuery 诞生于应对疯狂!随着 CSS 的成熟和浏览器合规性的提高,我希望您是正确的。【参考方案8】:

这是一篇旧帖子,但我会在这里留下我的 javascript 解决方案,以防万一有人需要它。


// you only need this function
function sticky( _el )
  _el.parentElement.addEventListener("scroll", function()
    _el.style.transform = "translateY("+this.scrollTop+"px)";
  );



// how to make it work:
// get the element you want to be sticky
var el = document.querySelector("#blbl > div");
// give the element as argument, done.
sticky(el);
#blbl
  position:relative;
  height:200px;  
  overflow: auto;
  background: #eee;


#blbl > div
  position:absolute; 
  padding:50px; 
  top:10px; 
  left:10px; 
  background: #f00
<div id="blbl" >
    <div><!-- sticky div --></div> 

    <br><br><br><br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>

注意事项

    我使用 transform: translateY(@px) 因为它应该是轻量级的计算,high-performance-animations

    我只在现代浏览器上尝试过这个功能,它不适用于需要供应商的旧浏览器(当然还有 IE)

【讨论】:

【参考方案9】:

我知道这是一篇较旧的帖子,但我认为在这个网站上已经可以找到 Jiew Meng 尝试做的一个很好的例子。查看位于此处的侧边菜单:https://***.com/faq#questions。在没有深入研究的情况下查看它,我可以告诉 javascript 在滚动命中锚标记下方时附加一个固定位置,如果滚动超出同一锚标记,则删除固定位置。希望这能让某人朝着正确的方向开始。

【讨论】:

【参考方案10】:

通过多个 div,我设法获得了一个固定 y 和绝对 x div。 在我的情况下,我需要一个左右两侧的 div,与居中的 1180 像素宽度的 div 对齐。

    <div class="parentdiv" style="
        background: transparent;
        margin: auto;
        width: 100%;
        max-width: 1220px;
        height: 10px;
        text-align: center;">
        <div style="
            position: fixed;
            width: 100%;
            max-width: 1220px;">
            <div style="
                position: absolute;
                background: black;
                height: 20px;
                width: 20px;
                left: 0;">
            </div>
            <div style="
                width: 20px;
                height: 20px;
                background: blue;
                position: absolute;                                           
                right: 0;">
            </div>
        </div>
    </div>

【讨论】:

以上是关于我可以定位相对于父元素固定的元素吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

相对于父元素的固定位置[重复]

如何使position:fixed;相对于父元素定位

JS如何判断元素相对于父窗口的绝对位置?

postion属性

38.相对于父元素的fixed定位的实现

定位及背景属性