Cómo mostrar la barra de desplazamiento en una tabla html

85

Estoy escribiendo una página en la que necesito una tabla html para mantener un tamaño establecido. Necesito que los encabezados en la parte superior de la tabla permanezcan allí en todo momento, pero también necesito que el cuerpo de la tabla se desplace sin importar cuántas filas se agreguen a la tabla.

Quiero que se vea como el método 2 en esta URL: http://www.cssplay.co.uk/menu/tablescroll.html

He intentado hacer esto pero no aparece la barra de desplazamiento:

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>

BruceyBandit
fuente
¿Por qué no usa el código del método de ejemplo? <tbody>Desafortunadamente, no puedes usar .
Mike Park

Respuestas:

163

¿Algo como esto?

http://jsfiddle.net/TweNm/

La idea es envolver el <table>en una posición no estática <div>que tenga una overflow:autopropiedad CSS. Luego coloque los elementos en el <thead>absolutamente.

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

Richard JP Le Guen
fuente
15
¿Qué tal si no hay columnas de ancho fijo?
Fractaliste
3
Probé su respuesta pero las columnas de encabezado no están alineadas. Usé solo su css en una etiqueta de estilo dentro de la etiqueta del cuerpo donde copié su tabla
Antonio
Gran solución, pero tengo problemas con ella. Cuando intente ocultar una fila y configurar la visualización: ninguna, hay algunos espacios en blanco entre las filas. Ese no es el caso de la mesa normal. ¿Alguna idea, consejo o sugerencia?
Daniil Shevelev
@Antonio: Tuve el mismo problema (las columnas de encabezado centradas * parecen no alineadas), pero agregar me transform: translateX(-50%)sirvió [* centrado es el estilo estándar en Firefox que se elimina con la opción "normalizar CSS" en el JSFiddle de esta respuesta]
Sora.
44

Tienes que insertar tu <table>en un <div>tamaño fijo, y en <div>estilo tienes que configurarlo overflow: scroll.

hossein barzegari
fuente
1
dio una altura de 500px para mi div y funcionó bien. <div style = "overflow: scroll; height: 500px;">
Ziggler
3
No sé por qué todo el mundo lo hizo tan complicado. Esta debería ser la respuesta aceptada.
amallard
1
Esta es, con mucho, la solución más sencilla. Puede haber advertencias para agregar un div con un desbordamiento y una altura fija, pero esta solución al menos lo colocará en la dirección correcta.
lsimonetti
1
¡Excelente respuesta, compañero! Saludos
:)
1
Esta debería ser la respuesta aceptada. Sencillo, directo al grano y no destruyo nada más con él.
Me esfuerzo mucho pero lloro más fuerte
40

La respuesta aceptada proporcionó un buen punto de partida, pero si cambia el tamaño del marco, cambia el ancho de las columnas o incluso cambia los datos de la tabla, los encabezados se estropearán de varias maneras. Todos los demás ejemplos que he visto tienen problemas similares o imponen algunas restricciones serias en el diseño de la mesa.

Sin embargo, creo que finalmente he resuelto todos estos problemas. Se necesitó mucho CSS, pero el producto final es tan confiable y fácil de usar como una tabla normal.

Aquí hay un ejemplo que tiene todas las características necesarias para replicar la tabla a la que hace referencia el OP: jsFiddle

Los colores y los bordes deberían cambiarse para que sea idéntico a la referencia. La información sobre cómo realizar ese tipo de cambios se proporciona en los comentarios de CSS.

Aquí está el código:

/*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]-->

Doctor Destructo
fuente
trabajo asombroso. Sin embargo, tengo una tabla con 15 columnas y parece que ahora no puedo contener la tabla a la página sin una barra de desplazamiento horizontal. Intenté ajustar su CSS, su CSS bellamente codificado, para acomodar columnas de ancho más dinámicas, pero nada de lo que cambie, excepto el ancho de la tabla, hace la diferencia. Si cambio el ancho de la tabla al 100%, entonces la tabla se representa en el ancho de la tabla, pero debido a que el ancho de las columnas no se ajusta, todavía no puedo ver las 15 columnas de datos. Casi tengo una tabla de desplazamiento que se ve muy bien, por lo que cualquier ayuda agradece.
nanker
oh, espera un segundo, no hay barra de desplazamiento horizontal, la tabla simplemente se corta.
nanker
@nanker Si necesita desplazamiento horizontal y está dispuesto a usar un poco de JavaScript, debe verificar esta respuesta . Es la mejor manera de hacer una tabla de desplazamiento que conozco. No había una buena manera de hacer el desplazamiento horizontal con solo CSS cuando publiqué esta respuesta, pero no lo he investigado durante un tiempo, así que no sé qué es posible ahora.
DoctorDestructo
Impresionante trabajo. ¿Podrías comentar cómo modificar varias filas de encabezado? Simplemente repetir la <tr><th></th>..</tr>construcción claramente no funciona. Gracias.
David I. McIntosh
@ DavidI.McIntosh Un encabezado de varias filas sería complicado con esta técnica. Agregar filas sería fácil, pero no estoy seguro de cómo obtendría los bordes horizontales entre ellas. Es posible que desee probar la solución de JavaScript que vinculé en mi comentario anterior a menos que no pueda usar JS por alguna razón.
DoctorDestructo
3

Resolví este problema separando mi contenido en dos tablas.

Una tabla es la fila del encabezado.

Los segundos también son <table>etiqueta, pero envueltos <div>con altura estática y desplazamiento de desbordamiento.

Zvi
fuente
1

Vale la pena señalar que, dependiendo de su propósito (el mío fueron los resultados de autocompletar de una barra de búsqueda), es posible que desee que la altura sea cambiable y que la barra de desplazamiento solo exista si la altura excede eso.

Si lo desea, reemplace height: x;con max-height: x;y overflow:scrollcon overflow:auto.

Además, puede utilizar overflow-xyoverflow-y si lo desea, y obviamente lo mismo funciona horizontalmente conwidth : x;

Ben
fuente
0

Si llega al punto en el que todas las soluciones mencionadas no funcionan (como me pasó a mí), haga esto:

  • Crea dos tablas. Uno para la cabecera y otro para el cuerpo
  • Dar a las dos tablas diferentes contenedores / divs principales
  • Diseñe el div de la segunda tabla para permitir el desplazamiento vertical de su contenido.

Así, en tu 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>

Luego, diseñe el padre de la segunda tabla para permitir el desplazamiento vertical, en su CSS

    .table-content-class {
        overflow-y: scroll;    // use auto; or scroll; to allow vertical scrolling; 
        overflow-x: hidden;    // disable horizontal scroll 
    }
Kaka Ruto
fuente
Esta es la misma implementación que la respuesta de Zvi un año antes.
TylerH
0

solo agrega en la mesa

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 = "desbordamiento-x: auto;" `

Maestro del lugar de aprendizaje
fuente