Saltar al contenido
CCH TechLab

Cómo filtrar, ordenar y paginar una tabla con JavaScript Vanilla

Carlos Campos14 min
Desarrollo Web

Cuando una tabla HTML contiene muchos registros, encontrar información concreta puede convertirse rápidamente en una tarea incómoda. Añadir un buscador, ordenar las columnas y dividir los resultados en páginas mejora considerablemente la experiencia de uso.

El problema es que implementar cada una de estas funciones por separado puede obligarnos a escribir una gran cantidad de código cada vez que creamos una tabla nueva.

En este tutorial vamos a crear una clase reutilizable llamada TableManager, desarrollada únicamente con JavaScript Vanilla, que nos permitirá añadir las siguientes funcionalidades a cualquier tabla HTML:

  • Filtrado de registros mediante un campo de búsqueda.
  • Ordenación ascendente y descendente por columnas.
  • Paginación de resultados.
  • Selector de registros por página.
  • Comparación automática de textos, números y fechas.
  • Navegación accesible mediante teclado.
  • Personalización de textos y opciones.
  • Actualización de la tabla cuando cambian sus filas.

Todo ello sin instalar librerías externas como DataTables, jQuery o frameworks de JavaScript.

¿Qué vamos a crear?

Partiremos de una tabla HTML normal que contiene una lista de personajes, junto con su identificador y planeta de nacimiento.

Una vez aplicada la clase TableManager, la tabla tendrá automáticamente:

  1. Un campo para buscar registros.
  2. Cabeceras pulsables para ordenar los datos.
  3. Un selector para elegir cuántas filas aparecen por página.
  4. Botones para navegar entre las distintas páginas.
  5. Información sobre el número de registros mostrados.

La principal ventaja es que no tendremos que programar estas funciones cada vez. Bastará con incluir el archivo JavaScript e inicializar la clase con unas pocas líneas.

Estructura de archivos del proyecto

Para este ejemplo utilizaremos dos archivos:

/proyecto-tabla
├── index.html
└── tableManager.js

El archivo index.html contiene la tabla y la inicialización del componente.

El archivo tableManager.js contiene la clase TableManager, encargada de añadir toda la funcionalidad.

Crear la tabla HTML

En primer lugar, necesitamos una tabla HTML correctamente estructurada.

Es importante que tenga los elementos <thead> y <tbody>, ya que la clase utiliza la cabecera para activar la ordenación y el cuerpo para gestionar las filas.

Un ejemplo simplificado sería el siguiente:

<table id="myTable">
  <thead>
    <tr>
      <th>ID</th>
      <th>Nombre</th>
      <th>Planeta de nacimiento</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>1</td>
      <td>Iron Man</td>
      <td>Tierra</td>
    </tr>

    <tr>
      <td>2</td>
      <td>Captain America</td>
      <td>Tierra</td>
    </tr>

    <tr>
      <td>3</td>
      <td>Thor</td>
      <td>Asgard</td>
    </tr>

    <tr>
      <td>4</td>
      <td>Hulk</td>
      <td>Tierra</td>
    </tr>
  </tbody>
</table>
Lenguaje del código: HTML, XML (xml)

Podemos añadir tantas filas y columnas como necesitemos. La clase detectará automáticamente las filas existentes en el <tbody>.

El atributo id="myTable" nos permitirá seleccionar la tabla posteriormente desde JavaScript.

Incluir el archivo JavaScript

Al final del documento HTML, antes de cerrar la etiqueta </body>, incluimos el archivo que contiene la clase:

<script src="tablas.js"></script>
Lenguaje del código: HTML, XML (xml)

Después de cargarlo, podemos crear una instancia de TableManager:

<script>
  document.addEventListener("DOMContentLoaded", () => {
    const tablaPersonajes = new TableManager("#myTable", {
      sortable: true,
      filterable: true,
      pagination: true,
      rowsPerPage: 10,
      rowsPerPageOptions: [5, 10, 25, 50],
    });
  });
</script>

Lenguaje del código: JavaScript (javascript)

Con este pequeño bloque de código ya tendremos funcionando el buscador, la ordenación y la paginación.

Cómo funciona la clase TableManager

La clase recibe dos parámetros:

new TableManager(tableSelector, options);Lenguaje del código: JavaScript (javascript)

El primer parámetro identifica la tabla que queremos mejorar.

Podemos utilizar un selector CSS:

new TableManager("#myTable");Lenguaje del código: JavaScript (javascript)

También podemos pasar directamente el elemento HTML:

const tabla = document.getElementById("myTable");

new TableManager(tabla);Lenguaje del código: JavaScript (javascript)

El segundo parámetro es un objeto con las opciones de configuración.

new TableManager("#myTable", {
  sortable: true,
  filterable: true,
  pagination: true,
});Lenguaje del código: JavaScript (javascript)

Si no indicamos ninguna opción, la clase utiliza una configuración predeterminada.

Opciones disponibles

Activar o desactivar la ordenación

La opción sortable determina si se podrá ordenar la tabla pulsando sobre sus cabeceras.

sortable: trueLenguaje del código: JavaScript (javascript)

Para desactivar esta función:

sortable: falseLenguaje del código: JavaScript (javascript)

Cuando la ordenación está activa, el primer clic ordena la columna de forma ascendente y el siguiente la ordena de forma descendente.

La funcionalidad también puede activarse mediante las teclas Enter o espacio cuando la cabecera tiene el foco.

Activar o desactivar el buscador

La opción filterable controla la creación del campo de búsqueda:

filterable: trueLenguaje del código: JavaScript (javascript)

Mientras el usuario escribe, la clase recorre las filas y muestra únicamente aquellas que contienen el texto introducido.

La búsqueda no distingue entre mayúsculas y minúsculas.

Por ejemplo, buscar:

asgard

permitirá localizar registros como Thor, Odin, Hela o Heimdall.

Activar o desactivar la paginación

La opción pagination permite dividir los resultados en páginas:

pagination: trueLenguaje del código: JavaScript (javascript)

Para mostrar todas las filas sin paginación:

pagination: falseLenguaje del código: JavaScript (javascript)

Elegir el número de filas por página

Podemos definir cuántos registros se mostrarán inicialmente:

rowsPerPage: 10Lenguaje del código: HTTP (http)

La tabla mostrará diez filas y ocultará el resto hasta que el usuario cambie de página.

Configurar el selector de registros

La opción rowsPerPageOptions define los valores disponibles dentro del selector:

rowsPerPageOptions: [5, 10, 25, 50]Lenguaje del código: CSS (css)

El usuario podrá elegir mostrar 5, 10, 25 o 50 registros por página.

La clase añade automáticamente el valor configurado en rowsPerPage cuando este no se encuentra dentro del array.

Buscar solamente en determinadas columnas

Por defecto, el buscador comprueba el contenido de todas las columnas.

Podemos limitar la búsqueda mediante filterColumns.

new TableManager("#myTable", {
  filterable: true,
  filterColumns: [1, 2],
});Lenguaje del código: JavaScript (javascript)

Los índices de las columnas comienzan en cero:

0 → ID
1 → Nombre
2 → Planeta de nacimiento

En este ejemplo, el buscador ignorará la columna del identificador y buscará únicamente en el nombre y en el planeta.

Excluir columnas de la ordenación

En algunas tablas podemos tener columnas que no tenga sentido ordenar, como una columna de botones de edición o eliminación.

Podemos excluirlas mediante excludedSortColumns:

new TableManager("#myTable", {
  sortable: true,
  excludedSortColumns: [3],
});Lenguaje del código: CSS (css)

En este caso, la cuarta columna no responderá al hacer clic sobre su cabecera.

Aplicar una ordenación inicial

También podemos indicar que la tabla aparezca ordenada automáticamente al cargarse.

new TableManager("#myTable", {
  initialSort: {
    column: 1,
    direction: "asc",
  },
});Lenguaje del código: CSS (css)

Esta configuración ordenará inicialmente la segunda columna de forma ascendente.

Para ordenar de manera descendente:

initialSort: {
  column: 1,
  direction: "desc",
}Lenguaje del código: CSS (css)

Ordenación automática de números, fechas y textos

Uno de los puntos más interesantes de la clase es que intenta detectar el tipo de contenido antes de ordenar los valores.

El orden de comprobación es el siguiente:

  1. Números.
  2. Fechas.
  3. Texto.

Ordenación numérica

La clase puede interpretar valores como:

1000
1.000
1.000,50
1000.50
25 €Lenguaje del código: CSS (css)

Esto evita el problema habitual de ordenar números como si fueran cadenas de texto.

Por ejemplo, una ordenación textual podría colocar 100 antes que 20. Al convertir los valores correctamente a números, la clase mantiene su orden lógico.

Ordenación de fechas

La clase admite inicialmente estos formatos:

2026-07-27
27/07/2026

Las fechas se convierten internamente en marcas de tiempo para poder compararlas correctamente.

Ordenación de texto

Cuando el valor no es un número ni una fecha, se utiliza localeCompare con configuración en español:

valueA.localeCompare(valueB, "es", {
  numeric: true,
  sensitivity: "base",
});Lenguaje del código: CSS (css)

Esto permite realizar una comparación más natural de textos y evita que las diferencias entre mayúsculas y minúsculas alteren innecesariamente el resultado.

Personalizar los textos del componente

Todos los textos visibles pueden modificarse mediante la propiedad labels.

new TableManager("#myTable", {
  labels: {
    search: "Filtrar personajes:",
    rowsPerPage: "Filas visibles:",
    previous: "Atrás",
    next: "Adelante",
    noResults: "No hay personajes que coincidan con la búsqueda",
  },
});Lenguaje del código: CSS (css)

No es necesario definir todos los textos. Podemos sobrescribir solamente los que queramos cambiar.

Las etiquetas disponibles son:

labels: {
  search: "Buscar:",
  rowsPerPage: "Registros por página:",
  previous: "Anterior",
  next: "Siguiente",
  showing: "Mostrando",
  to: "a",
  total: "de",
  records: "registros",
  noResults: "No se encontraron resultados",
}Lenguaje del código: CSS (css)

También podemos personalizar el texto del campo de búsqueda:

filterPlaceholder: "Buscar personaje..."Lenguaje del código: JavaScript (javascript)

Navegación entre páginas

La clase calcula automáticamente el número total de páginas según:

  • El número de filas filtradas.
  • La cantidad de registros seleccionada por página.

Cuando existen pocas páginas, se muestran todos sus números:

1 2 3 4 5

Cuando hay muchas páginas, se añaden puntos suspensivos:

1 … 5 6 7 … 20

Los botones anterior y siguiente se desactivan automáticamente al llegar a los límites de la paginación.

También aparece un texto informativo similar a este:

Mostrando 1 a 10 de 91 registros

Si aplicamos un filtro, la información se actualiza para reflejar únicamente los resultados encontrados.

Actualizar la tabla dinámicamente

En algunas aplicaciones, las filas pueden añadirse o eliminarse después de crear la instancia de TableManager.

Para informar a la clase de estos cambios podemos utilizar el método refresh().

const tablaPersonajes = new TableManager("#myTable");Lenguaje del código: JavaScript (javascript)

Posteriormente añadimos una nueva fila:

const tbody = document.querySelector("#myTable tbody");

tbody.insertAdjacentHTML(
  "beforeend",
  `
    <tr>
      <td>92</td>
      <td>Nuevo personaje</td>
      <td>Tierra</td>
    </tr>
  `,
);Lenguaje del código: HTML, XML (xml)

Finalmente actualizamos el componente:

tablaPersonajes.refresh();Lenguaje del código: CSS (css)

El método vuelve a obtener las filas, aplica el filtro actual y actualiza la paginación.

Limpiar el buscador mediante JavaScript

La clase también incluye el método clearFilter(), que permite eliminar el texto de búsqueda y volver a mostrar todos los registros.

tablaPersonajes.clearFilter();Lenguaje del código: CSS (css)

Podemos utilizarlo, por ejemplo, desde un botón externo:

<button type="button" id="clearSearch">
  Limpiar búsqueda
</button>Lenguaje del código: HTML, XML (xml)
document
  .getElementById("clearSearch")
  .addEventListener("click", () => {
    tablaPersonajes.clearFilter();
  });Lenguaje del código: JavaScript (javascript)

Ejemplo de configuración completa

Una configuración más avanzada podría ser la siguiente:

document.addEventListener("DOMContentLoaded", () => {
  const tablaPersonajes = new TableManager("#myTable", {
    sortable: true,
    filterable: true,
    pagination: true,

    rowsPerPage: 10,
    rowsPerPageOptions: [5, 10, 25, 50],

    filterPlaceholder: "Buscar por nombre o planeta...",

    filterColumns: [1, 2],

    excludedSortColumns: [],

    initialSort: {
      column: 1,
      direction: "asc",
    },

    labels: {
      search: "Buscar personaje:",
      rowsPerPage: "Personajes por página:",
      previous: "Anterior",
      next: "Siguiente",
      records: "personajes",
      noResults: "No se encontraron personajes",
    },
  });
});Lenguaje del código: JavaScript (javascript)

Esta configuración:

  • Busca solamente en el nombre y el planeta.
  • Ordena inicialmente por el nombre.
  • Muestra diez personajes por página.
  • Permite elegir entre 5, 10, 25 y 50 filas.
  • Personaliza los principales textos del componente.

Añadir estilos CSS

La clase genera automáticamente varios elementos y clases CSS. Podemos utilizarlas para adaptar el diseño a nuestra página.

.table-manager {
  width: 100%;
}

.table-manager__toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 1rem;
}

.table-manager__search {
  padding: 0.6rem 0.8rem;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
}

.table-manager table {
  width: 100%;
  border-collapse: collapse;
}

.table-manager th,
.table-manager td {
  padding: 0.75rem;
  border: 1px solid #d1d5db;
  text-align: left;
}

.table-manager__sortable {
  cursor: pointer;
  user-select: none;
}

.table-manager__sort-asc::after {
  content: " ▲";
}

.table-manager__sort-desc::after {
  content: " ▼";
}

.table-manager__pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
  flex-wrap: wrap;
}

.table-manager__page-buttons,
.table-manager__number-buttons {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.table-manager__button {
  padding: 0.5rem 0.75rem;
  border: 1px solid #cbd5e1;
  border-radius: 5px;
  background-color: #ffffff;
  cursor: pointer;
}

.table-manager__button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.table-manager__page-number.is-active {
  font-weight: bold;
  border-color: #2563eb;
}

.table-manager__no-results td {
  padding: 1.5rem;
  text-align: center;
}Lenguaje del código: CSS (css)

Estos estilos son solamente un punto de partida. Podemos modificar los colores, espacios y tamaños para integrarlos con el diseño de nuestro proyecto o tema de WordPress.

Accesibilidad del componente

La clase incluye varias mejoras de accesibilidad:

  • Las cabeceras ordenables pueden utilizarse con el teclado.
  • Se añaden atributos aria-sort para indicar la dirección de ordenación.
  • La página activa utiliza aria-current="page".
  • El buscador y el selector tienen etiquetas accesibles.
  • La información de paginación utiliza aria-live="polite".

Estas características permiten que el componente sea más fácil de utilizar para usuarios que navegan mediante teclado o tecnologías de asistencia.

Ventajas de utilizar una clase reutilizable

Podríamos escribir la lógica directamente para una tabla concreta, pero encapsularla dentro de una clase ofrece varias ventajas:

Menos código repetido

Podemos aplicar la misma funcionalidad a varias tablas sin copiar y pegar toda la lógica.

new TableManager("#tablaUsuarios");
new TableManager("#tablaProductos");
new TableManager("#tablaPedidos");Lenguaje del código: JavaScript (javascript)

Configuración independiente

Cada tabla puede utilizar opciones diferentes.

new TableManager("#tablaUsuarios", {
  rowsPerPage: 10,
});

new TableManager("#tablaProductos", {
  rowsPerPage: 25,
  filterColumns: [1, 2],
});

new TableManager("#tablaPedidos", {
  initialSort: {
    column: 3,
    direction: "desc",
  },
});Lenguaje del código: CSS (css)

Sin dependencias externas

El componente funciona con JavaScript nativo, por lo que no necesitamos:

  • Instalar paquetes.
  • Añadir un framework.
  • Cargar jQuery.
  • Depender de servicios externos.
  • Incorporar archivos JavaScript de terceros.

Esto ayuda a mantener el proyecto ligero y facilita entender cómo funciona cada parte.

Limitaciones que debemos tener en cuenta

Esta solución trabaja directamente con las filas existentes en el HTML.

Es apropiada para tablas pequeñas o medianas, pero no es la mejor opción para mostrar decenas de miles de registros.

Cuando tenemos una cantidad muy grande de datos, lo recomendable es realizar el filtrado, la ordenación y la paginación desde el servidor o mediante una API.

En esos casos, el navegador debería solicitar únicamente los registros correspondientes a la página actual.

También debemos tener en cuenta que la clase utiliza el contenido visible de las celdas. Si necesitamos ordenar valores complejos, podemos ampliar el componente para utilizar atributos como:

<td data-sort-value="20260729">
  29/07/2026
</td>Lenguaje del código: HTML, XML (xml)

Conclusión

Crear un sistema para filtrar, ordenar y paginar una tabla no requiere necesariamente instalar una biblioteca externa.

Mediante la clase TableManager podemos convertir una tabla HTML convencional en un componente mucho más práctico utilizando solamente JavaScript Vanilla.

Una vez incluido el archivo tableManager.js, la configuración básica se reduce a unas pocas líneas:

new TableManager("#myTable", {
  sortable: true,
  filterable: true,
  pagination: true,
  rowsPerPage: 10,
});Lenguaje del código: JavaScript (javascript)

A partir de ahí podemos personalizar las columnas de búsqueda, excluir columnas de la ordenación, cambiar las etiquetas, establecer una ordenación inicial y actualizar las filas dinámicamente.

Este tipo de ejercicio también es una buena forma de aprender conceptos importantes de JavaScript, como las clases, la manipulación del DOM, los eventos, los arrays, la ordenación de datos y la creación de componentes reutilizables.

FAQs

¿Cómo ordenar una tabla HTML con JavaScript?

Para ordenar una tabla HTML con JavaScript debes detectar el clic sobre cada cabecera, obtener los valores de la columna seleccionada y reorganizar las filas del <tbody>. La clase TableManager automatiza este proceso y permite alternar entre orden ascendente y descendente simplemente pulsando sobre el encabezado de una columna.

¿Cómo crear un buscador para una tabla HTML?

Puedes crear un buscador añadiendo un campo <input type="search"> y escuchando su evento input. Cada vez que el usuario escribe, JavaScript compara el texto introducido con el contenido de las celdas y oculta las filas que no coinciden. TableManager genera automáticamente el buscador y permite limitar la búsqueda a columnas concretas.

¿Cómo paginar una tabla sin usar jQuery?

Para paginar una tabla sin usar jQuery puedes trabajar directamente con JavaScript Vanilla. El proceso consiste en calcular cuántas páginas son necesarias, ocultar las filas que no pertenecen a la página actual y crear botones para navegar entre ellas. TableManager incluye esta funcionalidad sin depender de librerías externas.

¿Se puede utilizar TableManager con datos dinámicos?

Sí. TableManager puede utilizarse con filas añadidas o eliminadas dinámicamente. Después de modificar el contenido del <tbody>, debes ejecutar el método refresh() para que la clase vuelva a detectar las filas, aplique el filtro actual y actualice la ordenación y la paginación.

¿Qué diferencia hay entre DataTables y JavaScript Vanilla?

DataTables es una biblioteca con muchas funciones avanzadas, pero normalmente requiere cargar archivos adicionales y, según la versión utilizada, puede depender de jQuery. Una solución con JavaScript Vanilla no necesita dependencias externas, suele ser más ligera y ofrece un mayor control sobre el código. Sin embargo, DataTables puede ser más adecuada para proyectos que necesitan funciones complejas ya preparadas.

¿Cómo ordenar números y fechas correctamente en una tabla HTML?

Para ordenar números y fechas correctamente no debes compararlos únicamente como texto. Los números deben convertirse a valores numéricos y las fechas a objetos Date o marcas de tiempo antes de realizar la comparación. TableManager intenta detectar automáticamente números, importes y fechas en formatos como 2026-07-27 o 27/07/2026.

¿Cómo actualizar la tabla después de añadir nuevas filas?

Después de añadir nuevas filas al <tbody>, debes llamar al método refresh() de la instancia de TableManager. Este método vuelve a recopilar todas las filas, reaplica el filtro activo, regresa a la primera página y actualiza los controles de paginación.
tablaPersonajes.refresh();

¿Es compatible con todos los navegadores modernos?

Sí. TableManager utiliza características estándar de JavaScript compatibles con las versiones modernas de Chrome, Edge, Firefox y Safari. No obstante, podría necesitar ajustes o transpilación si el proyecto debe funcionar en navegadores antiguos que no soporten clases, propagación de objetos, encadenamiento opcional u otras características modernas de JavaScript.

Scroll al inicio