Jak zapobiec zmianie pozycji strony internetowej przez pasek przewijania?

218

Mam stronę internetową z wyrównanym centralnie DIV. Teraz niektóre strony wymagają przewijania, niektóre nie. Kiedy przechodzę od jednego typu do drugiego, wygląd paska przewijania przesuwa stronę o kilka pikseli w bok. Czy jest jakiś sposób, aby tego uniknąć bez wyraźnego wyświetlania pasków przewijania na każdej stronie?

Dmitri Nesteruk
źródło
6
Dlaczego nikt nie wspomina overflow-y: overlayw tym wątku?
milkersarac,
3
Według dokumentacji overflow-y: overlay
Mozilli

Odpowiedzi:

266

przepełnienie-y: przewijanie jest poprawne, ale powinieneś go używać z tagiem html, a nie z treścią, bo w IE 7 pojawia się podwójny pasek przewijania
Tak więc poprawny css byłby:

html {
  overflow-y: scroll;
}
Ruben
źródło
1
IE 10+ ma pływający pasek przewijania, dlatego powinieneś wyłączyć to dla tych przeglądarek
Ruben
1
może to powodować problemy, takie jak podwójne paski przewijania, gdy używa się go w połączeniu z fancyboxem lub twitterowym modalem bootstrap
Ruben
dodatkowe informacje: bootstrap twitter dodaje teraz .modal-open do twojego ciała, gdy modal jest otwarty
Ruben
55
Warto wspomnieć, że stale wyświetla pionowy pasek przewijania. Nie zawsze może być do zaakceptowania.
rustyx
Dostaję podwójny pasek przewijania w Chromium i Firefox. Używam flex-box; może to powoduje ...
Garrett,
72

Zawiń zawartość przewijalnego elementu w div i zastosuj 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>

Sztuczka polega na tym, że 100vwreprezentuje 100% rzutni, w tym pasek przewijania. Po odjęciu 100%, czyli dostępnej przestrzeni bez paska przewijania, kończy się szerokość paska przewijania lub 0jego brak. Utworzenie dopełnienia o tej szerokości po lewej stronie zasymuluje drugi pasek przewijania, przesuwając wyśrodkowaną treść z powrotem w prawo.

Pamiętaj, że zadziała to tylko wtedy, gdy przewijalny element wykorzystuje całą szerokość strony, ale nie powinno to stanowić większego problemu, ponieważ istnieje tylko kilka innych przypadków, w których wyśrodkowałeś przewijaną zawartość.

Rapti
źródło
1
Lepiej byłoby zastosować klasę niż styl wbudowany i działa tylko w tych przeglądarkach , ale jest to sprytna technika - nie zdawałem sobie z tego sprawy 100vwi 100%mierzyłem różne rzeczy, więc nauczyłem się z tego czegoś pożytecznego!
Nick F
21
Jest to absolutnie genialne i jest naprawdę najlepszą odpowiedzią, biorąc pod uwagę, że obsługa przeglądarki w Calc jest bardzo dobra.
Michael
1
Możesz zrobić to samo, ale zamiast dodawania marginesu po lewej stronie, dodajesz margines ujemny po prawej stronie (patrz stackoverflow.com/a/39289453/6015444 ).
Touniouk
2
To rozwiązanie spowoduje podobne problemy z kolorem tła, takie jak odpowiedź „width: calc (100vw - 34px);” ale po lewej stronie.
Maciej Lew
1
Poleciłbym dodać kilka zapytań o media do tego stylu @media screen and (min-width: 800px) {...} . W przypadkach, gdy treść będzie pasować do szerokości strony. Na przykład przy małych rozdzielczościach pojawi się niepotrzebna luka, przesuwająca treść w prawo
MarkosyanArtur
44

Myślę, że nie. Ale stylizacji bodyze overflow: scrollpowinien robić. Wydaje się, że o tym wiesz.

Michael Krelin - haker
źródło
3
Brzmi dobrze ... zmusza stronę, aby zawsze pokazywała pasek przewijania, czy tego potrzebuje, czy nie, ... wtedy nie ma wizualnej zmiany między typami stron.
eidylon
1
Tak, ale IIRC, pokazuje oba paski przewijania. Tak naprawdę nie potrzebuję poziomego.
Dmitri Nesteruk
To prawda. Ale niewiele mogę zrobić, aby ci pomóc :( Właściwie pierwsze zdanie mojej odpowiedzi uważam za prawdziwą odpowiedź, która dotyczy tego pytania.
Michael Krelin - haker
49
overflow-y: scroll:)
Svish
2
Poniżej znajduje się lepsza odpowiedź
Sami
36

Z przewijaniem zawsze wyświetlanym, być może nie jest dobry dla układu.

Spróbuj ograniczyć szerokość ciała za pomocą css3

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

vwto szerokość rzutni (zobacz ten link w celu wyjaśnienia)
calcoblicz w css3
34pxoznacza podwójną szerokość paska przewijania (zobacz to dla stałej lub to do obliczenia, jeśli nie ufasz ustalonym rozmiarom)

Moesio
źródło
4
Wszystko jest daremne, dopóki ktoś nie potrzebuje.
Moesio
3
Jest to wizualnie o wiele mniej inwazyjne niż zmuszanie scollbarów, jak opisuje zaakceptowana odpowiedź.
Silas Hansen
4
Do tej pory działało to najlepiej dla moich potrzeb, dodałem również, padding-left: 34px;aby równomiernie wyśrodkować stronę.
Pat Migliaccio,
3
To powinna być zaakceptowana odpowiedź, w przeciwieństwie do obecnie akceptowanej, w rzeczywistości odpowiada na pytanie!
Coz
2
Spowoduje to problemy, jeśli masz pasek nawigacyjny / nagłówek w innym kolorze niż tło ciała lub dolna ramka itp.
Zia Ul Rehman Mughal
28
html {
  overflow-x: hidden;
  margin-right: calc(-1 * (100vw - 100%));
}

Przykład . Kliknij przycisk „zmień minimalną wysokość”.

Za pomocą calc(100vw - 100%)możemy obliczyć szerokość paska przewijania (a jeśli nie zostanie wyświetlony, będzie wynosił 0). Pomysł: używając ujemnego marginesu z prawej strony, możemy zwiększyć szerokość <html>do tej szerokości. Zobaczysz poziomy pasek przewijania - należy go ukryć za pomocą overflow-x: hidden.

pongo
źródło
Musiałem umieścić ciało w div i zastosować margines do div, aby zadziałało (podobnie do odpowiedzi Rapti .) Ale to wygląda o wiele ładniej.
Touniouk
1
Działa to świetnie i wydaje się, że nie powoduje niepożądanych poziomych pasków przewijania w Chrome lub Firefox. Dlaczego nie użyć po prostu calc(100% - 100vw)zamiast pomnożyć przez -1?
SystemParadox
13

Nie wiem, czy to stary post, ale miałem ten sam problem i jeśli chcesz przewijać w pionie, tylko powinieneś spróbować overflow-y:scroll


źródło
13

Jeśli zmieniasz rozmiar lub po załadowaniu niektórych danych dodajesz pasek przewijania, możesz spróbować wykonać, utworzyć klasę i zastosować tę klasę.

.auto-scroll {
   overflow-y: overlay;
   overflow-x: overlay;
}
kunalkamble
źródło
3

Rozwiązałem problem na jednej z moich stron internetowych, jawnie ustawiając szerokość ciała w javascript według rozmiaru okienka ekranu pomniejszonego o szerokość paska przewijania. Używam udokumentowanej tutaj funkcji opartej na jQuery , aby określić szerokość paska przewijania.

<body id="bodyid>

var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
Frank L.
źródło
10
Nie umiem nawet wyjaśnić, dlaczego to taka zła praktyka.
mythofechelon
20
@BenHooper: Chciałbym wiedzieć, dlaczego jest to zła praktyka.
Saad
1
Co się stanie, jeśli zmienisz rozmiar okna?
Braden Steffaniak
3

Rozwijanie odpowiedzi za pomocą tego:

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

Jeden z komentatorów zasugerował dodanie lewy dopełnienie również w celu utrzymania centrowania:

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

Ale wtedy rzeczy nie wyglądają poprawnie, jeśli treść jest szersza niż rzutnia. Aby to naprawić, możesz użyć zapytań o media, takich jak to:

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

Gdzie 1058px = szerokość treści + 17 * 2

Dzięki temu poziomy pasek przewijania obsługuje przepełnienie x i utrzymuje wyśrodkowaną treść w środku, gdy rzutnia jest wystarczająco szeroka, aby pomieścić zawartość o stałej szerokości

Greg St.Onge
źródło
3

Poza odpowiedzią Rapti powinno to działać równie dobrze, ale dodaje więcej marginesu po prawej stronie bodyi ukrywa go z htmlmarginesem ujemnym , zamiast dodawać dodatkowe wypełnienie, które może potencjalnie wpłynąć na układ strony. W ten sposób nic się nie zmienia na rzeczywistej stronie (w większości przypadków), a kod nadal działa.

html {
    margin-right: calc(100% - 100vw);
}
body {
    margin-right: calc(100vw - 100%);
}
Grant Gryczan
źródło
Odkryłem, że w chrome dodaje to poziomy przewijanie na stronach, które mają pionowy pasek przewijania na mojej stronie bootstrap.
Wiewiórka imbirowa
Próbowałeś dowiedzieć się, dlaczego? Sprawdź inspektora elementów i sprawdź, czy Bootstrap nie zadziała z marginesami, paskami przewijania lub czymkolwiek podobnym.
Grant Gryczan
1
Prawdopodobnie miało to związek z marginesami 15 pikseli, które bootstrap nakłada na wszystko, podczas sprawdzania strony margines kontenera spada pod paskiem przewijania. Zastosowałem overflow-x: hiddeni to naprawiło.
Wiewiórka imbirowa
3

Rozwiązanie @ kashesandr działało dla mnie, ale aby ukryć poziomy pasek przewijania, dodałem jeszcze jeden styl dla ciała. oto kompletne rozwiązanie:

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');
      }
    });
});

Tylko rozwiązanie JS (gdy 2. modal otwiera się od 1. modalu):

/**
 * 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);
  }
});
Hassan Tareq
źródło
2

Próbowałem naprawić prawdopodobnie ten sam problem, który był spowodowany .modal-openzastosowaną klasą bootowania na Twitterze body. Rozwiązanie html {overflow-y: scroll}nie pomaga. Jednym z możliwych rozwiązań jest dodanie {width: 100%; width: 100vw}do htmlelementu.

kashandr
źródło
1
lub zmień na body {overflow-y: scroll}
Ruben
1
Ale to zawsze wyświetla pasek przewijania, nawet jeśli nie jest to wymagane.
Rapti
Powinieneś wyjaśnić, dlaczego ustawiasz szerokość dwukrotnie? html { width: 100vw; }pracował dla mnie
Hassan Tareq
Dla mnie tworzy dwa paski przewijania
rbansal
2

Zwykle mam ten problem, ale najprostszym sposobem rozwiązania tego problemu jest (działa dla mnie):

na typ pliku CSS:

body{overflow-y:scroll;}

tak proste! :)

Melvin Guerrero
źródło
2

Rozwiązania opublikowane przy użyciu funkcji calc (100vw - 100%) są na dobrej drodze, ale jest z tym problem: na zawsze będziesz mieć margines po lewej stronie rozmiaru paska przewijania, nawet jeśli zmienisz rozmiar okna, aby zawartość wypełnia całą rzutnię.

Jeśli spróbujesz obejść ten problem za pomocą zapytania o media, będziesz miał niezręczny moment przyciągania, ponieważ margines nie będzie stopniowo zmniejszał się podczas zmiany rozmiaru okna.

Oto rozwiązanie, które obejdzie ten problem, a AFAIK nie ma wad:

Zamiast używać marginesu: auto do centrowania treści, użyj tego:

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

Zamień 500px na połowę maksymalnej szerokości treści (więc w tym przykładzie maksymalna szerokość treści to 1000px). Zawartość pozostanie wyśrodkowana, a margines będzie stopniowo zmniejszał się do końca, aż zawartość wypełni obszar ekranu.

Aby zatrzymać margines przed ujemnym, gdy rzutnia jest mniejsza niż maksymalna szerokość, po prostu dodaj zapytanie medialne:

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

Zrobione!

Jonathan SI
źródło
2

Jeśli szerokość tabeli się nie zmieni, możesz ustawić szerokość elementu (np. Tbody) zawierającego pasek przewijania> 100% (pozwalając na dodatkowe miejsce dla paska przewijania) i ustawić overflow-y na „nakładkę” (więc że pasek przewijania pozostaje stały i nie przesunie tabeli w lewo, gdy się pojawi. Ustaw także stałą wysokość elementu za pomocą paska przewijania, aby pasek przewijania pojawił się po przekroczeniu wysokości. Tak jak:

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

Uwaga: będziesz musiał ręcznie ustawić szerokość%, ponieważ% miejsca zajmowanego przez pasek przewijania będzie zależny od szerokości stołu (tj. Mniejsza szerokość stołu, więcej% wymagane do dopasowania paska przewijania, ponieważ jego rozmiar w pikselach jest stały )

Przykład tabeli dynamicznej:

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>

Robert James Mieta
źródło
1

Wystarczy ustawić szerokość elementu kontenera w ten sposób

width: 100vw;

Spowoduje to, że element ten zignoruje pasek przewijania i będzie działać z kolorem tła lub obrazami.

Barsonax
źródło
-3

Użyłem trochę jquery do rozwiązania tego

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

$(document).ready(function(){
  $(window).load(function() {
    $('html').css({
      'overflow-y': ''
    });
  });
});
Will McMillian
źródło
3
Prawdopodobnie otrzymujesz słaby odbiór odpowiedzi, ponieważ to rozwiązanie wymaga całej struktury JavaScript. „jQuery wszystkich rzeczy!”
Paul Lammertsma
3
tak, jQuery to zdecydowanie najlepsza droga - doxdesk.com/img/updates/20091116-so-large.gif
Annonim
-4
@media screen and (min-width: 1024px){
    body {
    min-height: 700px
    }
}
Vicky
źródło
Witamy w Stack Overflow! Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie dla czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu. Staraj się również nie tłoczyć kodu objaśniającymi komentarzami, co zmniejsza czytelność zarówno kodu, jak i objaśnień!
Andrew Myers
-5

W przeciwieństwie do przyjętej odpowiedzi, która sugeruje stały pasek przewijania w oknie przeglądarki, nawet jeśli zawartość nie przepełnia ekranu , wolałbym używać:

html{
  height:101%;
}

Wynika to z faktu, że wygląd paska przewijania ma większy sens, jeśli zawartość faktycznie się przepełnia .

Ma to większy sens niż to .

Nikunj Madhogaria
źródło
1
Przynajmniej ostatnie zdanie jest błędne w twojej odpowiedzi. To ma sens podobnie z nadmiarem pustej strony drukowanej przez drukarkę.
vp_arth