位置元素垂直固定,绝对水平固定


77

这是我要完成的工作:

我需要一个按钮,该按钮与div的右侧保持一定距离,并且无论视口的大小如何,该按钮始终与div的侧面保持相同的距离,但是会随窗口滚动。

因此,始终是div右侧的x像素,而始终是视口顶部的y像素。

这可能吗?

Answers:


54

水平放置固定元素(基于另一个元素)

免责声明此处提供的解决方案在技术上并非如问题标题所述为“绝对水平”,而是实现了OP最初想要的功能,固定位置元素与另一个元素的右边缘为'X'距离,但固定在其右侧垂直滚动。)

我喜欢这些类型的CSS挑战。是的,作为概念证明,您可以得到想要的东西。您可能需要调整一些东西以满足您的需要,但是这里有一些通过FireFox,IE8和IE7的示例html和css(当然IE6没有position: fixed)。

HTML:

<body>
  <div class="inflow">
    <div class="positioner"><!-- may not be needed: see notes below-->
      <div class="fixed"></div>
    </div>
  </div>
</body>

CSS(用于演示的边界和所有尺寸):

div.inflow {
  width: 200px; 
  height: 1000px; 
  border: 1px solid blue; 
  float: right; 
  position: relative; 
  margin-right: 100px;
}
div.positioner {position: absolute; right: 0;} /*may not be needed: see below*/
div.fixed {
  width: 80px; 
  border: 1px solid red; 
  height: 100px; 
  position: fixed; 
  top: 60px; 
  margin-left: 15px;
}

关键是根本不设置leftright的水平位置,div.fixed而要使用两个包装div来设置水平位置。的div.positioner需要的,如果div.inflow是一个固定的宽度,随着左边距div.fixed可以设置在容器的已知宽度。但是,如果您希望容器比一个容器具有一定的宽度,则需要div.positioner将推div.fixed到第一个的右侧div.inflow

编辑:作为一个有趣的方面说明,当我设置overflow: hidden(应一个需要这样做)的div.inflow没有影响的固定位置的div被对方的边界之外。显然,固定位置足以将其移出包含div的上下文overflow


5
我的荣幸(从字面上看,这很有趣)
ScottS 2010年

11
它实际上没有按预期工作。一旦有了水平滚动条并且可以向右滚动,固定位置框就不会与div保持相同的距离。在此页面上向右滚动:jsfiddle.net/tXXtL
备用字节2012年

@sparebytes-如果那是您所期望的,那么我同意。最初的OP只是在寻找一种方法来将固定元素水平放置在另一个元素之外。在他的版本中,查看端口将更改大小(不会出现水平滚动条)。元素最终仍然是fixed元素,并且不受滚动影响。也许我应该更新问题标题以反映这一点。
ScottS 2012年

@sparebytes-我选择在我的回答中添加免责声明,而不是更改帖子的标题,这样就不会有人对它的成就感到措手不及。感谢您提请我注意我们的期望,以便能够解决这个期望。
ScottS 2012年

3
@ScottS,很高兴您更新了答案。我认为单独使用Css不可能拥有一个维度fixed,而另一个维度absolute,JavaScript必须在滚动时更新坐标。
12

13

经过大量的挖掘(包括这篇文章),我找不到我喜欢的解决方案。此处的“接受的答案”与OP的标题不符,我可以找到的最佳解决方案无疑会导致跳动的元素。然后,它使我震惊:将元素“固定”,检测何时发生水平滚动,并将其切换为绝对位置。这是结果代码:

以代码笔查看。

的HTML

  <div class="blue">
    <div class="red">
    </div>
  </div>

的CSS

/* Styling */
.blue, .red {
  border-style: dashed;
  border-width: 2px;
  padding: 2px;
  margin-bottom: 2px;
}

/* This will be out "vertical-fixed" element */
.red {
  border-color: red;
  height: 120px;
  position: fixed;
  width: 500px;
}

/* Container so we can see when we scroll */
.blue {
  border-color: blue;
  width: 50%;
  display: inline-block;
  height: 800px;
}

的JavaScript

$(function () {
  var $document = $(document),
      left = 0,
      scrollTimer = 0;

  // Detect horizontal scroll start and stop.
  $document.on("scroll", function () {
    var docLeft = $document.scrollLeft();
    if(left !== docLeft) {
      var self = this, args = arguments;
      if(!scrollTimer) {
        // We've not yet (re)started the timer: It's the beginning of scrolling.
        startHScroll.apply(self, args);
      }
      window.clearTimeout(scrollTimer);
      scrollTimer = window.setTimeout(function () {
        scrollTimer = 0;
        // Our timer was never stopped: We've finished scrolling.
        stopHScroll.apply(self, args);
      }, 100);
      left = docLeft;
    }
  });

  // Horizontal scroll started - Make div's absolutely positioned.
  function startHScroll () {
    console.log("Scroll Start");
    $(".red")
    // Clear out any left-positioning set by stopHScroll.
    .css("left","")
    .each(function () {
      var $this = $(this),
          pos = $this.offset();
      // Preserve our current vertical position...
      $this.css("top", pos.top)
    })
    // ...before making it absolutely positioned.
    .css("position", "absolute");
  }

  // Horizontal scroll stopped - Make div's float again.
  function stopHScroll () {
    var leftScroll = $(window).scrollLeft();
    console.log("Scroll Stop");
    $(".red")
    // Clear out any top-positioning set by startHScroll.
    .css("top","")
    .each(function () {
      var $this = $(this), 
        pos = $this.position();
      // Preserve our current horizontal position, munus the scroll position...
      $this.css("left", pos.left-leftScroll);
    })
    // ...before making it fixed positioned.
    .css("position", "fixed");
  }
});

1
这是迄今为止找到的最佳解决方案。甚至在发布此解决方案后的4年。似乎我们必须使用此方法,只要Sticky在所有浏览器中都没有适当的支持
Hedva

8

我到达这里是为了寻找类似问题的解决方案,那就是要有一个页脚栏,该页脚栏跨越窗口的宽度,并位于(可变的高度和宽度)内容以下。换句话说,似乎使页脚相对于其水平位置“固定”,但相对于其垂直位置在文档流中保持其正常位置。就我而言,我的页脚文本右对齐,因此它可以动态调整页脚的宽度。这是我想出的:

的HTML

<div id="footer-outer">
<div id="footer">
    Footer text.
</div><!-- end footer -->
</div><!-- end footer-outer -->

的CSS

#footer-outer
{
    width: 100%;
}
#footer
{
    text-align: right;
    background-color: blue;
    /* various style attributes, not important for the example */
}

CoffeeScript / JavaScript

(使用prototype.js)。

class Footer
document.observe 'dom:loaded', ->
    Footer.width = $('footer-outer').getDimensions().width
Event.observe window, 'scroll', ->
    x = document.viewport.getScrollOffsets().left
    $('footer-outer').setStyle( {'width': (Footer.width + x) + "px"} )

编译成:

Footer = (function() {

  function Footer() {}

  return Footer;

})();

document.observe('dom:loaded', function() {
  return Footer.width = $('footer-outer').getDimensions().width;
});

Event.observe(window, 'scroll', function() {
  var x;
  x = document.viewport.getScrollOffsets().left;
  return $('footer-outer').setStyle({
    'width': (Footer.width + x) + "px"
  });
});

这在FireFox中效果很好,在Chrome中效果很好(有点抖动);我没有尝试过其他浏览器。

我还希望页脚下方的任何备用空间都可以使用不同的颜色,因此我添加了以下footer-stretchdiv:

的HTML

...
</div><!-- end footer -->
<div id="footer-stretch"></div>
</div><!-- end footer-outer -->

的CSS

#footer-outer
{
    height: 100%;
}
#footer-stretch
{
    height: 100%;
    background-color: #2A2A2A;
}

请注意,要使#footer-stretch div有效,直到body元素(可能还有html元素-不确定)之前的所有父元素必须具有固定的高度(在这种情况下,height = 100%)。

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.