web-dev-qa-db-ja.com

固定位置だがコンテナに対する相対位置

私はdivを修正しようとしています、それでそれが常にスクリーンの一番上に固執するように:

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

ただし、divは中央揃えのコンテナの中にあります。私がposition:fixedを使うとき、それはブラウザウィンドウの右側にあるようにそれはブラウザウィンドウに関連してdivを固定します。代わりに、それはコンテナに対して固定されるべきです。

position:absolutedivに対して相対的な要素を修正するために使用できることを私は知っていますが、あなたがページを下にスクロールすると要素は消え、position:fixedのように上に固執しません。

これを達成するためのハックまたは回避策はありますか?

539
Zach Nicodemous

短い答え: いいえ。 (CSS変換で可能になりました。下記の編集を参照してください)

長い答え: "固定"ポジショニングを使用することの問題は、それが要素 をアウトオブフロー にすることです。したがって、親を基準にして再配置することはできません。ただし、コンテナの幅が固定されていることがわかっている場合は、次のようにします。

#fixedContainer {
  position: fixed;
  width: 600px;
  height: 200px;
  left: 50%;
  top: 0%;
  margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1/ /

編集(2015年3月):

これは古い情報です。 CSS3変換の魔法の助けを借りて、動的サイズ(水平方向および垂直方向)のコンテンツを中心に配置することが可能になりました。同じ原則が適用されますが、コンテナをオフセットするためにマージンを使用する代わりに、translateX(-50%)を使用できます。幅が固定されていない限りオフセットする量がわからず、(50%のような)相対値を使用できないため、これは上記のマージントリックでは機能しません。に適用されます。 transformは異なる動作をします。その値はそれらが適用される要素に相対的です。したがって、transform50%は要素の幅の半分を意味し、marginの50%は親の幅の半分です。これは IE9 +ソリューションです

上記の例と同様のコードを使用して、幅と高さを完全に動的にして同じシナリオを再現しました。

.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:水平方向のみ中央揃え /
jsFiddle:水平方向と垂直方向の両方に中央揃え
元のクレジットはユーザーに行く aaronk6 で私に指摘してくれた この答え

358
Joseph Marikle

実際、これは可能であり、受け入れられた答えは集中化だけを扱っており、それは十分に簡単です。また、本当にJavaScriptを使用する必要はありません。

これにより、あらゆるシナリオに対処できます。

位置:絶対位置:相対コンテナ内に配置する場合は、すべてを設定し、position: absoluteを使用してdiv内に新しい固定位置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 固定位置要素の余白としてbox-shadow blurピクセルをレンダリングするという問題を解決することを期待していましたが、それはバグのようです。
とにかく、これが役立つことを願っています!

168

はい、仕様によると、方法があります。

Graeme Blackwoodの回答が受け入れられるべきであることに同意しますが、実際に問題を解決するため、固定要素canコンテナに対して相対的に配置される

応募時に偶然気づいた

-webkit-transform: translateZ(0);

ボディに対して、(ビューポートの代わりに)それに関連する固定子を作成しました。したがって、私の固定要素leftおよびtopプロパティは、コンテナに関連するようになりました。

そのため、いくつかの調査を行ったところ、この問題はすでに Eric Meyer でカバーされていて、「トリック」のように感じても、これは仕様の一部であることがわかりました。

CSSボックスモデルによってレイアウトが制御される要素の場合、変換のnone以外の値は、スタックコンテキストと包含ブロックの両方を作成します。オブジェクトは、固定配置された子孫の包含ブロックとして機能します。

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

そのため、親要素に変換を適用すると、それが包含ブロックになります。

しかし...

問題は、(このビットが仕様の一部であるように見えなくても)要素も修正されたように振る舞うのをやめるので、実装がバグ/創造的に見えることです。

Safari、Chrome、Firefoxでも同じ動作が見られますが、IE11(fixed要素はまだ固定されたままです)では見られません。

別の興味深い(文書化されていない)ことは、固定要素が変換された要素内に含まれる場合、そのtopおよびleftプロパティはbox-sizingプロパティを考慮してコンテナに関連付けられることです。スクロールコンテキストは、ボックスサイズがborder-boxに設定されているかのように、要素の境界線を超えて拡張されます。そこにある創造的なものにとって、これはおそらく遊び道具になるかもしれません:)

TEST

127

答えは、divの位置をfixedに設定した後でleft: 0またはright: 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>
55
Shadow_boi

position: stickyは、概念的にposition: fixedに似た要素を配置するための新しい方法です。違いは、ビューポートで特定のオフセットしきい値が満たされるまで、position: stickyを持つ要素は、その親内でposition: relativeのように動作することです。 

Chrome 56(現在は2016年12月現在ベータ版、2017年1月安定)では、stickyが復活しました。

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

詳細はにありますposition:WebKitのスティッキーランド.

23
PoseLab

私はこのjQueryプラグインを作成して、中央に配置されたコンテナー(表形式データ)がある場所で発生していた同様の問題を解決しました。表形式のデータなので、コンテナをどこに置いても(中央、左、右)、水平にスクロールしたときにページと一緒に左右に移動できます。

これはこの問題を解決するかもしれないこの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();
});
18
bigspotteddog

固定位置の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が配置されている場所に配置されますが、そこで固定されます。 

17
hobberwickey

私のクライアントがコンテンツエリアの外に座って欲しいという広告でこれをしなければなりませんでした。私は単純に次のようにしました、そしてそれは魅力のように働きました!

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

2つのHTML要素と純粋なCSS(最新のブラウザー)

このjsFiddleの例を参照してください。サイズ変更し、固定要素がフロート要素とともに移動する方法を確認します。 -スクロールがサイトでどのように機能するかを確認するためのほとんどのスクロールバー(固定要素は固定されたままです)。

ここで多く述べているように、1つのキーはfixed要素に位置設定を設定していません(toprightbottom、またはleftの値は設定していません) 。

むしろ、次のように、すべての固定要素(最後のボックスに4つの要素があることに注意してください)を最初に配置するボックスに配置します。

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

次に、margin-topmargin-leftを使用して、コンテナに関連してこれらを「移動」します。このCSSのように:

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

fixed要素は他のすべてのレイアウト要素を無視するため、最後のコンテナー in the fiddle は複数のfixed要素を持つことができ、それらの要素はすべて左上隅に関連することに注意してください。しかし、これは、それらがすべてコンテナに最初に配置されている場合にのみ当てはまります。 この比較フィドルは、コンテナコンテンツ内に分散すると、配置が信頼できなくなることを示しています

ラッパーの位置が staticrelative 、または absolute であるかどうかは関係ありません。

7
ScottS

position: stickyプロパティを使用できます。  

使い方と、position: fixedとの違いを説明する _ codepen _ の例を次に示します。 

それがどのように振る舞うかは以下で説明されます:

  1. 固定位置を持つ要素は、ユーザーのスクロール位置に基づいて配置されます。要素が特定のオフセットを超えてスクロールされるまで基本的にはposition: relativeのように振る舞います。後方にスクロールすると、前の(相対的な)位置に戻ります。

  2. これは、ページ内の他の要素の流れに影響を及ぼします。つまり、ページ上の特定のスペースを占有します(position: relativeのように)。

  3. あるコンテナー内で定義されている場合は、そのコンテナーに対して配置されます。コンテナにオーバーフロー(スクロール)がある場合、スクロールオフセットに応じて、コンテナは所定の位置に変わります。固定。

そのため、コンテナ内で固定機能を実現したい場合は、stickyを使用してください。

6
Pransh Tiwari

私のjQueryプラグイン、 FixTo を試してみることができます。

使用法:

$('#mydiv').fixTo('#centeredContainer');
3
Burak

相対的な固定位置を実現するもう1つの奇妙な解決策は、コンテナをiframeに変換することです。これにより、固定要素をページ全体ではなくコンテナのビューポートに固定できます。

2
Beto Aveiga

純粋なCSSでは、それをどうにかできません。少なくとも私は持っていません。しかし、あなたは非常に簡単にjQueryでそれを行うことができます。私は私の問題を説明します、そして少しの変更であなたはそれを使うことができます。

それで、最初は、(ウィンドウの上から)固定された上を持ち、(親要素が中央に配置されているため)親要素から継承する左要素を持つことを望みました。左側のコンポーネントを設定するには、要素を親に配置し、親要素にposition:relativeを設定します。

次に、スクロールバーが一番上にあるとき(y 0スクロール)、要素が一番上からどれだけ離れているかを知る必要があります。ふたつの選択肢があります。まず、それは静的(ある数)であるか、親要素からそれを読まなければなりません。

私の場合は、上の静的ピクセルから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
Mr Br

私は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/ /

1
Wen

私は同じ問題を抱えています、私たちのチームメンバーの一人が私に解決策を提供します。 

<div class="container">
  <div class="scroll"></div>
  <div class="fix"></div>
</div>

cSS

.container {
  position: relative;
  flex:1;
  display:flex;
}

.fix {
  prosition:absolute;
}
1
Jay0Lu

これは簡単です(下記のHTMLのとおり)。

トリックは、 "position:fixed;"の付いた要素(div)の上または左を使用しないことです。これらが指定されていない場合、 "fixed content"要素はそれを囲む要素(div "position:relative;"付き)ブラウザウィンドウに対して相対的な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()関数を提供していないことをお詫び申し上げますが、不必要にこの投稿を長くするでしょう。私はそれをできるだけ短くすることを選びました。

1
Bruce Allen

私のプロジェクトは、.NET ASP Core 2 MVC Angular 4テンプレートとブートストラップ4です。行は次のように機能しました。

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

それは条約ですか、それとも私はこれを単純化しすぎたのでしょうか。

0
Adam Cox
/* 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%);
}
0
Carol McKay

私はしばらくそのようなことをしました。私は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)
}

あなたはあなたの幅を設定する必要があるでしょう、そしてそれは窓の幅を取得し、数秒ごとにマージンを変えます。私はそれが重いことを知っています、しかしそれはうまくいきます。

0

JavaScriptを使用すれば可能です。この場合、jQueryプラグインSticky-Kit

0
Paz Aricha