Jak wyświetlić pasek przewijania w tabeli html


85

Piszę stronę, na której potrzebuję tabeli html, aby zachować ustalony rozmiar. Potrzebuję, aby nagłówki na górze tabeli pozostały tam przez cały czas, ale potrzebuję również, aby treść tabeli była przewijana bez względu na liczbę wierszy dodanych do tabeli.

Chcę, aby wyglądało to jak metoda 2 w tym adresie URL: http://www.cssplay.co.uk/menu/tablescroll.html

Próbowałem to zrobić, ale nie pojawia się pasek przewijania:

tbody {
  height: 80em;
  overflow: scroll;
}
<table border=1 id="qandatbl" align="center">
  <tr>
    <th class="col1">Question No</th>
    <th class="col2">Option Type</th>
    <th class="col1">Duration</th>
  </tr>

  <tbody>
    <tr>
      <td class='qid'></td>
      <td class="options"></td>
      <td class="duration"></td>
    </tr>
  </tbody>
</table>


Dlaczego nie używasz kodu z metody przykładowej? Nie możesz <tbody>niestety użyć .
Mike Park

Odpowiedzi:


163

Coś takiego?

http://jsfiddle.net/TweNm/

Chodzi o to, aby zawijać element <table>umieszczony niestatycznie, <div>który ma overflow:autowłaściwość CSS. Następnie umieść elementy w <thead>absolutnie.

#table-wrapper {
  position:relative;
}
#table-scroll {
  height:150px;
  overflow:auto;  
  margin-top:20px;
}
#table-wrapper table {
  width:100%;

}
#table-wrapper table * {
  background:yellow;
  color:black;
}
#table-wrapper table thead th .text {
  position:absolute;   
  top:-20px;
  z-index:2;
  height:20px;
  width:35%;
  border:1px solid red;
}
<div id="table-wrapper">
  <div id="table-scroll">
    <table>
        <thead>
            <tr>
                <th><span class="text">A</span></th>
                <th><span class="text">B</span></th>
                <th><span class="text">C</span></th>
            </tr>
        </thead>
        <tbody>
          <tr> <td>1, 0</td> <td>2, 0</td> <td>3, 0</td> </tr>
          <tr> <td>1, 1</td> <td>2, 1</td> <td>3, 1</td> </tr>
          <tr> <td>1, 2</td> <td>2, 2</td> <td>3, 2</td> </tr>
          <tr> <td>1, 3</td> <td>2, 3</td> <td>3, 3</td> </tr>
          <tr> <td>1, 4</td> <td>2, 4</td> <td>3, 4</td> </tr>
          <tr> <td>1, 5</td> <td>2, 5</td> <td>3, 5</td> </tr>
          <tr> <td>1, 6</td> <td>2, 6</td> <td>3, 6</td> </tr>
          <tr> <td>1, 7</td> <td>2, 7</td> <td>3, 7</td> </tr>
          <tr> <td>1, 8</td> <td>2, 8</td> <td>3, 8</td> </tr>
          <tr> <td>1, 9</td> <td>2, 9</td> <td>3, 9</td> </tr>
          <tr> <td>1, 10</td> <td>2, 10</td> <td>3, 10</td> </tr>
          <!-- etc... -->
          <tr> <td>1, 99</td> <td>2, 99</td> <td>3, 99</td> </tr>
        </tbody>
    </table>
  </div>
</div>


15
A co powiesz na brak kolumn o stałej szerokości?
Fractaliste

3
Wypróbowałem twoją odpowiedź, ale kolumny nagłówków nie są wyrównane. Użyłem tylko twojego css w tagu stylu wewnątrz tagu body, gdzie skopiowałem twoją tabelę
Antonio

Świetne rozwiązanie, ale mam z tym problem. Podczas próby ukrycia wiersza i ustawienia wyświetlania: none, między wierszami są spacje. Tak nie jest w przypadku zwykłego stołu. Jakieś pomysły, wskazówki lub sugestie?
Daniil Shevelev

@Antonio: Miałem ten sam problem (wyśrodkowane * kolumny nagłówka wydawały się nie wyrównane), ale dodanie załatwiło sprawę transform: translateX(-50%)[* wyśrodkowany to standardowy styl w przeglądarce Firefox, który jest usuwany przez opcję „normalizuj CSS” w JSFiddle tej odpowiedzi]
Sora.

44

Musisz włożyć swój <table>w taki, <div>który ma ustalony rozmiar i <div>styl, który musisz ustawić overflow: scroll.


1
podał wysokość jako 500px dla mojego div i działało dobrze. <div style = "overflow: scroll; height: 500px;">
Ziggler,

3
Nie wiem, dlaczego wszyscy to tak skomplikowali. To powinna być akceptowana odpowiedź.
amallard

1
To zdecydowanie najłatwiejsze rozwiązanie. Mogą być pewne zastrzeżenia co do dodawania elementu DIV z przepełnieniem i stałą wysokością, ale to rozwiązanie przynajmniej ustawi Cię we właściwym kierunku.
lsimonetti

1
Znakomita odpowiedź kolego! Pozdrawiam
:)

1
To powinna być akceptowana odpowiedź. Prosty, od razu do rzeczy i nic innego tym nie niszczę.
Bardzo się staram, ale płaczę mocniej

40

Zaakceptowana odpowiedź była dobrym punktem wyjścia, ale jeśli zmienisz rozmiar ramki, zmienisz szerokość kolumn, a nawet zmienisz dane w tabeli, nagłówki zostaną pomieszane na różne sposoby. Każdy inny przykład, który widziałem, ma podobne problemy lub nakłada poważne ograniczenia na układ tabeli.

Myślę, że w końcu udało mi się rozwiązać wszystkie te problemy. Zajęło to dużo CSS, ale produkt końcowy jest mniej więcej tak niezawodny i łatwy w użyciu, jak zwykły stół.

Oto przykład, który ma wszystkie wymagane funkcje do replikacji tabeli, do której odwołuje się OP: jsFiddle

Należy zmienić kolory i obramowania, aby były identyczne z odniesieniem. Informacje o tym, jak wprowadzić tego typu zmiany, znajdują się w komentarzach CSS.

Oto kod:

/*the following html and body rule sets are required only if using a % width or height*/
/*html {
width: 100%;
height: 100%;
}*/
body {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 20px 0 20px;
  text-align: center;
  background: white;
}
.scrollingtable {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: middle;
  overflow: hidden;
  width: auto; /*if you want a fixed width, set it here, else set to auto*/
  min-width: 0/*100%*/; /*if you want a % width, set it here, else set to 0*/
  height: 188px/*100%*/; /*set table height here; can be fixed value or %*/
  min-height: 0/*104px*/; /*if using % height, make this large enough to fit scrollbar arrows + caption + thead*/
  font-family: Verdana, Tahoma, sans-serif;
  font-size: 15px;
  line-height: 20px;
  padding: 20px 0 20px 0; /*need enough padding to make room for caption*/
  text-align: left;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
  position: relative;
  border-top: 1px solid black;
  height: 100%;
  padding-top: 20px; /*this determines column header height*/
}
.scrollingtable > div:before {
  top: 0;
  background: cornflowerblue; /*header row background color*/
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 100%;
  height: 100%;
  left: 0;
}
.scrollingtable > div > div {
  min-height: 0/*43px*/; /*if using % height, make this large enough to fit scrollbar arrows*/
  max-height: 100%;
  overflow: scroll/*auto*/; /*set to auto if using fixed or % width; else scroll*/
  overflow-x: hidden;
  border: 1px solid black; /*border around table body*/
}
.scrollingtable > div > div:after {background: white;} /*match page background color*/
.scrollingtable > div > div > table {
  width: 100%;
  border-spacing: 0;
  margin-top: -20px; /*inverse of column header height*/
  /*margin-right: 17px;*/ /*uncomment if using % width*/
}
.scrollingtable > div > div > table > caption {
  position: absolute;
  top: -20px; /*inverse of caption height*/
  margin-top: -1px; /*inverse of border-width*/
  width: 100%;
  font-weight: bold;
  text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
  display: inline-block;
  padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 20px; /*match column header height*/
  border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
  position: absolute;
  top: 0;
  white-space: pre-wrap;
  color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
  content: "";
  display: block;
  min-height: 20px; /*match column header height*/
  padding-top: 1px;
  border-left: 1px solid black; /*borders between header cells*/
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
  position: absolute;
  width: 100px;
  top: -1px; /*inverse border-width*/
  background: white; /*match page background color*/
}
.scrollingtable > div > div > table > tbody > tr:after {
  content: "";
  display: table-cell;
  position: relative;
  padding: 0;
  border-top: 1px solid black;
  top: -1px; /*inverse of border width*/
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
  border-bottom: 1px solid black;
  padding: 0 6px 0 6px;
  height: 20px; /*match column header height*/
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /*alternate row color*/
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /*borders between body cells*/
<div class="scrollingtable">
  <div>
    <div>
      <table>
        <caption>Top Caption</caption>
        <thead>
          <tr>
            <th><div label="Column 1"></div></th>
            <th><div label="Column 2"></div></th>
            <th><div label="Column 3"></div></th>
            <th>
              <!--more versatile way of doing column label; requires 2 identical copies of label-->
              <div><div>Column 4</div><div>Column 4</div></div>
            </th>
            <th class="scrollbarhead"/> <!--ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW-->
          </tr>
        </thead>
        <tbody>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
        </tbody>
      </table>
    </div>
    Faux bottom caption
  </div>
</div>

<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->


wspaniała praca. Mam jednak tabelę z 15 kolumnami i nie mogę teraz zawrzeć tabeli na stronie bez poziomego paska przewijania. Próbowałem ulepszyć twój css, twój pięknie zakodowany css, aby pomieścić bardziej dynamiczne kolumny o szerokości, ale nic, co zmieniam, poza szerokością tabeli, nie robi różnicy. Jeśli zmienię szerokość tabeli na 100%, to tabela będzie renderowana na szerokość tabeli, ale ponieważ szerokości kolumn się nie zawijają, nadal nie widzę wszystkich 15 kolumn danych. Prawie mam przewijany stół, który wygląda jak kewl, więc każda pomoc jest mile widziana.
nanker

och, chwileczkę, bez poziomego paska przewijania, stół po prostu się ucina.
nanker

@nanker Jeśli potrzebujesz przewijania w poziomie i chcesz użyć odrobiny JavaScript, powinieneś sprawdzić tę odpowiedź . To najlepszy sposób na przewijanie tabeli, o którym wiem. Nie było dobrego sposobu na przewijanie w poziomie za pomocą samego CSS, kiedy opublikowałem tę odpowiedź, ale nie zaglądałem do tego przez jakiś czas, więc nie wiem, co jest teraz możliwe.
DoctorDestructo

Świetna robota. Czy mógłbyś skomentować, jak dostosować wiele wierszy nagłówka? Zwykłe powtórzenie <tr><th></th>..</tr>konstrukcji wyraźnie nie działa. Dzięki.
David I. McIntosh

@ DavidI.McIntosh Wielowierszowy nagłówek byłby trudny przy użyciu tej techniki. Dodawanie wierszy byłoby łatwe, ale nie jestem pewien, jak uzyskać poziome granice między nimi. Możesz wypróbować rozwiązanie JavaScript, które zamieściłem w moim poprzednim komentarzu, chyba że z jakiegoś powodu nie możesz używać JS.
DoctorDestructo

3

Rozwiązałem ten problem, rozdzielając zawartość na dwie tabele.

Jedna tabela to wiersz nagłówka.

Sekundy również są <table>tagami, ale są opakowane <div>statyczną wysokością i przewijaniem przepełnienia.


1

Warto zauważyć, że w zależności od celu (moje były wyniki autouzupełniania paska wyszukiwania) możesz chcieć, aby wysokość była zmienna, a pasek przewijania istniał tylko wtedy, gdy wysokość przekracza tę.

Jeśli chcesz, aby wymienić height: x;się max-height: x;oraz overflow:scrollzoverflow:auto .

Dodatkowo możesz użyć overflow-xi, overflow-yjeśli chcesz, i oczywiście to samo działa w poziomiewidth : x;


0

Jeśli dojdziesz do momentu, w którym wszystkie wymienione rozwiązania nie działają (tak jak u mnie), zrób to:

  • Utwórz dwie tabele. Jeden dla nagłówka, a drugi dla ciała
  • Nadaj dwóm tabelom różne nadrzędne kontenery / elementy div
  • Stylizuj element div drugiej tabeli, aby umożliwić przewijanie zawartości w pionie.

W ten sposób w twoim HTML

<div class="table-header-class">
    <table>
       <thead>
          <tr>
            <th>Ava</th>
            <th>Alexis</th>
            <th>Mcclure</th>
          </tr>
       </thead>
    </table>
</div>
<div class="table-content-class">
   <table>
       <tbody>
          <tr>
            <td>I am the boss</td>
            <td>No, da-da is not the boss!</td>
            <td>Alexis, I am the boss, right?</td>
          </tr>
       </tbody>
    </table>
</div>

Następnie nadaj styl rodzicowi drugiej tabeli, aby umożliwić przewijanie w pionie w pliku CSS

    .table-content-class {
        overflow-y: scroll;    // use auto; or scroll; to allow vertical scrolling; 
        overflow-x: hidden;    // disable horizontal scroll 
    }

To ta sama realizacja, co odpowiedź Zvi rok wcześniej.
TylerH

0

po prostu dodaj na stole

style="overflow-x:auto;"

<table border=1 id="qandatbl" align="center" style="overflow-x:auto;">
    <tr>
    <th class="col1">Question No</th>
    <th class="col2">Option Type</th>
    <th class="col1">Duration</th>
    </tr>

   <tbody>
    <tr>
    <td class='qid'></td>
    <td class="options"></td>
    <td class="duration"></td>
    </tr>
    </tbody>
</table>

style = "overflow-x: auto;" `


0

Bardzo proste, wystarczy owinąć tabelę w div, który ma overflow-y:scroll;i overflow-x:scrollwłaściwości, i sprawiają, że div mieć szerokość i długość mniejszą niż tabeli. TO BĘDZIE DZIAŁAĆ!!!


Podaj kod, aby poprawić odpowiedź.
mishsx
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.