スクロールバーがWebページを再配置しないようにするにはどうすればよいですか?


218

中央揃えのDIVのあるWebサイトがあります。現在、スクロールが必要なページとそうでないページがあります。あるタイプから別のタイプに移動すると、スクロールバーの外観により、ページが数ピクセル横に移動します。各ページにスクロールバーを明示的に表示せずにこれを回避する方法はありますか?


6
overflow-y: overlayこのスレッドで誰も言及しないのはなぜですか?
milkersarac

3
mozilla docsによると、overflow-y: overlay
廃止

回答:


266

overflow-y:scrollは正しいですが、それをbodyタグではなくhtmlタグで使用する必要があります。そうしないと、IE 7でダブルスクロールバー
が表示されるので、正しいCSSは次のようになります。

html {
  overflow-y: scroll;
}

1
IE 10+にはフローティングスクロールバーがあるため、これらのブラウザーではこれを無効にする必要があります
Ruben

1
これは、fancyboxまたはtwitterブートストラップモーダルと組み合わせて使用​​すると、ダブルスクロールバーのような問題を引き起こす可能性があります
Ruben

追加情報:モーダルが開いているときに、Twitterブートストラップが.modal-openをあなたのボディに追加する
Ruben

55
これは永続的に垂直スクロールバーを表示することに言及する価値があります。常に受け入れられるとは限りません。
rustyx

ChromiumとFirefoxの両方でダブルスクロールバーが表示されます。フレックスボックスを使用しています。多分それがこれを引き起こしています...
ギャレット

72

スクロール可能な要素のコンテンツをdivにラップして適用しますpadding-left: calc(100vw - 100%);

<body>
    <div style="padding-left: calc(100vw - 100%);">
        Some Content that is higher than the user's screen
    </div>
</body>

トリックは100vw、スクロールバーを含むビューポートの100%を表すことです。100%スクロールバーなしで使用可能なスペースであるを減算すると、スクロールバーの幅になるか、スクロールバー0が表示されなくなります。左側にその幅のパディングを作成すると、2番目のスクロールバーがシミュレートされ、中央に配置されたコンテンツが右に戻ります。

これは、スクロール可能な要素がページの幅全体を使用する場合にのみ機能することに注意してください。ただし、スクロール可能なコンテンツを中央に配置するケースは他にほとんどないため、ほとんどの場合これは問題になりません。


1
インラインスタイルよりもクラスを介して適用する方が適切であり、これらのブラウザーでのみ機能しますが、これは賢い手法です。私はそれを認識していないこと100vw100%測定していなかったため、これから役立つことを学びました!
Nick F

21
これは絶対に天才であり、calcのブラウザーサポートが非常に優れていることを考えると、本当に最良の答えです。
マイケル

1
左側にマージンを追加する代わりに、右側に負のマージンを追加することを除いて、同じことを行うことができます(stackoverflow.com/a/39289453/6015444を参照)。
Touniouk 2018年

2
このソリューションでは、「width:calc(100vw-34px);」という回答のような背景色で同様の問題が発生します。左側にあります。
Maciej Lew 2018

1
このスタイルにメディアクエリを追加することをお勧めし@media screen and (min-width: 800px) {...} ます。コンテンツがページ幅に収まる場合。たとえば、小さな解像度では不要なギャップが生じ、コンテンツが右にシフトします
MarkosyanArtur

44

私はそうは思いません。しかし、でスタイリングbodyするoverflow: scroll必要があります。しかし、あなたはそれを知っているようです。


3
いいですね...スクロールバーが必要かどうかにかかわらず、ページに常にスクロールバーを表示するように強制します。そうすると、ページタイプ間で視覚的な変化はありません。
eidylon 2009

1
はい、しかしIIRC、これは両方のスクロールバーを表示します。横型は本当に必要ありません。
Dmitri Nesteruk、2009

それは本当だ。しかし、私はあなたを助けるために:(実は、私が唯一であることを私の回答の最初の文を考えてみ行うことができますあまりありません本当の答えはその質問を扱う。
マイケルKrelin -ハッカー

49
overflow-y: scroll:)
ヴィッシュ

2
以下はより良い答えです
Sami

36

常にスクロールが表示されるので、レイアウトには向かないかもしれません。

css3で本体の幅を制限してみてください

body {
    width: calc(100vw - 34px);
}

vwビューポートの幅です(いくつかの説明については、このリンクを参照してください)
calc。css3で計算し
34pxます。ダブルスクロールバーの幅を表します(固定サイズについては、これを参照してください。固定サイズが信頼できない場合は、これを計算してください)。


4
誰かが必要とするまで、すべてが無益です。
Moesio

3
これは、受け入れられた回答が説明するように、単にscollbarを強制するよりも視覚的にはるかに煩わしくないです。
Silas Hansen

4
これは、これまでのところ私のニーズに最も適してpadding-left: 34px;います。また、ページを中央揃えに追加しました。
Pat Migliaccio

3
これは、現在受け入れられているものとは異なり、実際に質問に回答しているものであるはずです。
Coz

2
あなたがなど身体の背景や下境界線とは異なる色でナビゲーションバー/ヘッダー持っている場合、これは問題が発生します
ジアのUIレーマンムガール

28
html {
  overflow-x: hidden;
  margin-right: calc(-1 * (100vw - 100%));
}

。「最小高さの変更」ボタンをクリックします。

これcalc(100vw - 100%)で、スクロールバーの幅を計算できます(表示されない場合は0になります)。アイデア:負のマージン右を使用して、幅<html>をこの幅に増やすことができます。水平スクロールバーが表示されます—を使用して非表示にする必要がありますoverflow-x: hidden


本体をdivに入れて、動作するようにdivにマージンを適用する必要がありました(Raptiの回答と同様です)。しかし、これは非常にきれいに見えます。
Touniouk 2018年

1
これはうまく機能し、ChromeやFirefoxで不要な水平スクロールバーが表示されるようには見えません。calc(100% - 100vw)乗算するのではなく単に使用しないのはなぜ-1ですか?
SystemParadox

13

これが古い投稿かどうかはわかりませんが、同じ問題があり、縦方向にのみスクロールしたい場合は、 overflow-y:scroll


13

サイズを変更したり、データを読み込んだ後にスクロールバーを追加したりする場合は、クラスを作成し、このクラスを適用してください。

.auto-scroll {
   overflow-y: overlay;
   overflow-x: overlay;
}

3

ビューポートのサイズからスクロールバーの幅を引いた値でJavaScriptの本文の幅を明示的に設定することにより、私のWebサイトの1つで問題を解決しました。ここに記載さているjQueryベースの関数を使用して、スクロールバーの幅を決定します。

<body id="bodyid>

var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";

10
なぜこれがそんなに悪い習慣なのか説明することすらできません。
mythofechelon

20
@BenHooper:なぜこれが悪い習慣なのか知りたいのですが。
2013年

1
ウィンドウのサイズを変更するとどうなりますか?
Braden Steffaniak 2017年

3

これを使用して答えを拡張する:

body {
    width: calc(100vw - 17px);
}

あるコメント投稿者は、中央揃えを維持するために左パディングも追加することを提案しました:

body {
    padding-left: 17px;
    width: calc(100vw - 17px);
}

ただし、コンテンツがビューポートよりも広い場合は、正しく表示されません。これを修正するには、次のようなメディアクエリを使用できます。

@media screen and (min-width: 1058px) {
    body {
        padding-left: 17px;
        width: calc(100vw - 17px);
    }
}

ここで、1058px =コンテンツの幅+ 17 * 2

これにより、水平スクロールバーがxオーバーフローを処理し、ビューポートが固定幅のコンテンツを含めるのに十分な幅の場合、中央に配置されたコンテンツを中央に維持します。


3

Raptiの回答から拡張すると、これも同様に機能するはずですが、ページのレイアウトに影響を与える可能性のある余分なパディングを追加する代わりに、の右側にマージンを追加bodyし、負のhtmlマージンで非表示にします。この方法では、実際のページでは何も変更されず(ほとんどの場合)、コードは引き続き機能します。

html {
    margin-right: calc(100% - 100vw);
}
body {
    margin-right: calc(100vw - 100%);
}

クロムでは、これにより、ブートストラップサイトに垂直スクロールバーがあるページに水平スクロールが追加されます。
ジンジャーリス

理由を調べてみましたか?要素インスペクタをチェックして、Bootstrapがマージンやスクロールバーなどで混乱していないかどうかを確認します。
Grant Gryczan、

1
おそらく、ページの検査時にコンテナーのマージンがスクロールバーの下にあるページを検査するときに、ブートストラップがすべてに適用する15pxのマージンと関係があるのでしょう。私はそれを適用しoverflow-x: hidden、それを修正しました。
Ginger Squirrel

3

@kashesandrの解決策は私にとってはうまくいきましたが、水平スクロールバーを非表示にするために、本文にもう1つのスタイルを追加しました。ここに完全なソリューションがあります:

CSS

<style>
/* prevent layout shifting and hide horizontal scroll */
html {
  width: 100vw;
}
body {
  overflow-x: hidden;
}
</style>

JS

$(function(){
    /**
     * For multiple modals.
     * Enables scrolling of 1st modal when 2nd modal is closed.
     */
    $('.modal').on('hidden.bs.modal', function (event) {
      if ($('.modal:visible').length) {
        $('body').addClass('modal-open');
      }
    });
});

JSのみのソリューション(2番目のモーダルが1番目のモーダルから開かれた場合):

/**
 * For multiple modals.
 * Enables scrolling of 1st modal when 2nd modal is closed.
 */
$('.modal').on('hidden.bs.modal', function (event) {
  if ($('.modal:visible').length) {
    $('body').addClass('modal-open');
    $('body').css('padding-right', 17);
  }
});

2

.modal-open適用されたtwitterブートストラップクラスによって引き起こされた同じ問題を修正しようとしましたbody。解決策html {overflow-y: scroll}は役に立ちません。私が見つけた1つの可能な解決策は{width: 100%; width: 100vw}html要素に追加することです。


1
または本文に変更{overflow-y:scroll}
Ruben

1
ただし、必要でない場合でも、常にスクロールバーが表示されます。
ラプティ2018

幅を2度設定する理由を説明する必要がありますか?html { width: 100vw; }私のために働きました
Hassan Tareq

私にとっては、実際には2つのスクロールバーが作成されます
rbansal

2

私はその問題を抱えていましたが、それを修正する簡単な方法はこれです(これは私にとってはうまくいきます):

CSSファイルタイプ:

body{overflow-y:scroll;}

とても簡単です!:)


2

calc(100vw-100%)を使用して投稿された解決策は正しい方向にありますが、これには問題があります。ウィンドウのサイズを変更してもコンテンツはビューポート全体を占めます。

メディアクエリでこれを回避しようとすると、ウィンドウのサイズを変更してもマージンが徐々に小さくならないため、厄介なスナップの瞬間があります。

これを回避するソリューションは次のとおりです。AFAIKには欠点がありません。

margin:autoを使用してコンテンツを中央に配置する代わりに、これを使用します。

body {
margin-left: calc(50vw - 500px);
}

500pxをコンテンツの最大幅の半分に置き換えます(この例では、コンテンツの最大幅は1000pxです)。これでコンテンツは中央に配置さたままになり、コンテンツがビューポートいっぱいになるまでマージンが徐々に減少します。

ビューポートがmax-widthより小さいときにマージンが負にならないようにするには、次のようなメディアクエリを追加します。

@media screen and (max-width:1000px) {
    body {
        margin-left: 0;
    }
}

エボラ!


2

テーブルの幅が変更されない場合は、スクロールバーを含む要素(tbodyなど)の幅を> 100%(スクロールバー用に余分なスペースを許可)に設定し、overflow-yを "overlay"(つまりスクロールバーは固定されたままで、表示されたときにテーブルを左にシフトしません)。また、スクロールバーを使用して要素に固定の高さを設定し、高さを超えるとスクロールバーが表示されるようにします。そのようです:

tbody {
  height: 100px;
  overflow-y: overlay;
  width: 105%
}

注:スクロールバーが占めるスペースの%はテーブルの幅に比例するため、幅%を手動で調整する必要があります(つまり、テーブルの幅が小さいほど、スクロールバーにフィットするために必要な%は、ピクセル単位のサイズが一定であるためです)

動的テーブルの例:

function addRow(tableID)
{
    var table = document.getElementById(tableID);
    var rowCount = table.rows.length;
    var row = table.insertRow(rowCount);
    var colCount = table.rows[0].cells.length;
  
    for(var i=0; i<colCount; i++)
    {
        var newRow = row.insertCell(i);

        newRow.innerHTML = table.rows[0].cells[i].innerHTML;
        newRow.childNodes[0].value = "";
    }
}
 
function deleteRow(row)
{
    var table = document.getElementById("data");
    var rowCount = table.rows.length;
    var rowIndex = row.parentNode.parentNode.rowIndex;

    document.getElementById("data").deleteRow(rowIndex);
}
.scroll-table {
  border-collapse: collapse;
}

.scroll-table tbody {
  display:block;
  overflow-y:overlay;
  height:60px;
  width: 105%
}

.scroll-table tbody td {
  color: #333;
  padding: 10px;
  text-shadow: 1px 1px 1px #fff;
}

.scroll-table thead tr {
  display:block;
}

.scroll-table td {
    border-top: thin solid; 
    border-bottom: thin solid;
}

.scroll-table td:first-child {
    border-left: thin solid;
}

.scroll-table td:last-child {
    border-right: thin solid;
}

.scroll-table tr:first-child {
    display: none;
}

.delete_button {
    background-color: red;
    color: white;
}

.container {
  display: inline-block;
}

body {
  text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" href="test_table.css">
</head>

<body>
<h1>Dynamic Table</h1>
<div class="container">

  <table id="data" class="scroll-table">
    <tbody>
      <tr>
        <td><input type="text" /></td>
        <td><input type="text" /></td>
        <td><input type="button" class="delete_button" value="X" onclick="deleteRow(this)"></td>
      </tr>
    </tbody>
  </table>

  <input type="button" value="Add" onclick="addRow('data')" />

</div>

<script src="test_table.js"></script>
</body>
</html>


1

このようにコンテナ要素の幅を設定するだけでうまくいきます

width: 100vw;

これにより、その要素はスクロールバーを無視し、背景色や画像で機能します。


-3

私はこれを解決するためにいくつかのjqueryを使用しました

$('html').css({
    'overflow-y': 'hidden'
});

$(document).ready(function(){
  $(window).load(function() {
    $('html').css({
      'overflow-y': ''
    });
  });
});

3
このソリューションにはJavaScriptフレームワーク全体が必要なため、回答の受信が悪くなる可能性があります。「jQueryすべてのもの!」
Paul Lammertsma、2016年

3
そうです、jQueryは間違いなく進むべき道です-doxdesk.com/img/updates/20091116-so-large.gif
匿名の

-4
@media screen and (min-width: 1024px){
    body {
    min-height: 700px
    }
}

Stack Overflowへようこそ!このコードスニペットは問題を解決する可能性がありますが、説明を含めると、投稿の品質を向上させるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。また、コードと説明コメントを混同しないようにしてください。これにより、コードと説明の両方が読みにくくなります。
Andrew Myers

-5

コンテンツが画面からオーバーフローしない場合でも、ブラウザーウィンドウに永続的なスクロールバーが表示されることを示唆する受け入れられた回答とは異なり、私は以下を使用することをお勧めします。

html{
  height:101%;
}

これは、コンテンツが実際にオーバーフローする場合、スクロールバーの外観がより意味をなすためです。

これこれよりも理にかなっています。


1
少なくとも最後の文はあなたの答えでは間違っています。プリンタで印刷された余分な空のページでも同様です。
vp_arth 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.