web-dev-qa-db-ja.com

位置要素を垂直に固定、絶対水平に

ここに私が達成しようとしているものがあります:

Divの右側から特定の距離に配置され、ビューポートのサイズに関係なくdivの側から常に同じ距離にあるボタンが必要ですが、ウィンドウと共にスクロールします。

したがって、常にdivの右側からxピクセルですが、常にビューポートの上部からyピクセルです。

これは可能ですか?

68
Jimmy

固定要素を水平方向に別の要素に基づいて配置

免責事項ここで提供される解決策 は、技術的には「 absolute horizo​​ntal 」ではないが、タイトルが述べているように、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;
}

キーは、div.fixedの水平に対してleftまたはrightをまったく設定せず、2つのラッパーdivを使用して水平位置を設定することです。 。 div.positionerは、div.inflowの左マージンが固定幅であるため、div.fixedが固定幅の場合、notが必要です。コンテナの既知の幅に設定されます。ただし、コンテナよりもパーセント幅を使用する場合は、div.positionerを最初にdiv.fixedの右側にプッシュするためにdiv.inflowが必要です。

編集:興味深い副次的な注意事項として、overflow: hiddendiv.inflowを設定する必要があります(そうする必要があります)効果なし固定位置のdivが相手の境界外にある。どうやら、固定位置は、overflowを含むdivのコンテキストからそれを取り出すのに十分です。

44
ScottS

掘り下げた後(この投稿を含む)、気に入った解決策を見つけることができませんでした。ここで受け入れられた回答は、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");
  }
});
10
Grinn

私はここに着いて、同様の問題の解決策を探しました。それは、ウィンドウの幅に広がり、(可変の高さと幅)コンテンツの下にあるフッターバーを持つことでした。言い換えれば、フッターは水平位置に対しては「固定」されているように見えますが、垂直位置に関しては文書フロー内の通常の位置を保持しています。私の場合、フッターのテキストを右揃えにしていたので、フッターの幅を動的に調整することができました。ここに私が思いついたものがあります:

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-stretch div:

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要素-不明)が固定の高さ(この場合、高さ= 100%)を持っている必要があることに注意してください。

7
Waz