npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

hequalizer

v1.0.0

Published

Librería JavaScript ligera que iguala automáticamente las alturas de elementos DOM mediante variables CSS. Perfecta para layouts perfectamente alineados en carousels, grids y tarjetas.

Readme

Hequalizer

Hequalizer es una librería JavaScript ligera que iguala automáticamente las alturas de elementos DOM mediante variables CSS. Con un enfoque simple y declarativo, facilita la creación de layouts perfectamente alineados sin la complejidad de soluciones CSS complejas o frameworks pesados.

Características principales:

  • Igualación automática: Calcula y aplica la altura máxima mediante variables CSS personalizables
  • Responsive por diseño: Sistema de breakpoints con configuración específica por viewport
  • Actualización automática: MutationObserver y eventos de resize mantienen las alturas sincronizadas
  • Modos de columnas flexibles: Iguala todos los elementos o agrúpalos por columnas
  • Lifecycle hooks completo: Eventos en cada etapa del ciclo de vida
  • Clases de estado: Clases CSS automáticas para animaciones y estilos condicionales
  • Zero dependencies: JavaScript vanilla puro, sin dependencias externas
  • Framework agnostic: Compatible con React, Vue, Angular, Svelte y cualquier framework
  • API global: Gestiona múltiples instancias desde un único punto de acceso
  • Omisión selectiva: Excluye elementos específicos del cálculo mediante clases

Menú

Instalación

Puedes integrar Hequalizer en tu proyecto de las siguientes formas:

NPM

npm install hequalizer

Importa en tu proyecto:

// ES modules
import Hequalizer from 'hequalizer';

// CommonJS
const Hequalizer = require('hequalizer');

CDN

<script src="https://cdn.jsdelivr.net/npm/[email protected]/hequalizer.min.js"></script>

Descarga directa

  1. Descarga hequalizer.min.js desde GitHub Releases
  2. Inclúyelo en tu HTML:
<script src="ruta/a/tu/proyecto/hequalizer.min.js"></script>

Uso básico

HTML

<div class="card-container">
  <div class="card">
    <h3>Título 1</h3>
    <p>Contenido variable...</p>
  </div>
  <div class="card">
    <h3>Título 2</h3>
    <p>Contenido con diferente altura...</p>
  </div>
  <div class="card">
    <h3>Título 3</h3>
    <p>Más contenido...</p>
  </div>
</div>

JavaScript

// Seleccionar los títulos de las tarjetas
const cardTitles = document.querySelectorAll('.card h3');

// Inicializar Hequalizer
new Hequalizer(cardTitles);

CSS

/* La variable CSS --height se aplica automáticamente */
.card h3 {
  height: var(--height);
}

¡Eso es todo! Ahora todos los títulos tendrán la misma altura, igualándose automáticamente al elemento más alto.

Hequalizer se encargará de recalcular las alturas cuando:

  • El DOM esté completamente cargado (DOMContentLoaded)
  • Las fuentes web terminen de cargar (document.fonts.ready)
  • El contenido cambie (mediante MutationObserver)
  • La ventana cambie de tamaño (resize event)

Ejemplos

Ejemplo 1: Grid responsive

const gridItems = document.querySelectorAll('.grid-item');

new Hequalizer(gridItems, {
  columns: 3,
  responsive: {
    1024: { columns: 2 },
    768: { columns: 1 }
  }
});

En este ejemplo:

  • Desktop (>1024px): Agrupa cada 3 elementos
  • Tablet (≤1024px): Agrupa cada 2 elementos
  • Mobile (≤768px): Sin agrupación, todos tienen la misma altura

Ejemplo 2: Carousel con Swiper.js

const swiper = new Swiper('.swiper', {
  slidesPerView: 3,
  spaceBetween: 20
});

const slideTitles = document.querySelectorAll('.swiper-slide h3');
const slideDescriptions = document.querySelectorAll('.swiper-slide p');

// Igualar títulos y descripciones independientemente
new Hequalizer(slideTitles);
new Hequalizer(slideDescriptions);

Ejemplo 3: Lifecycle hooks

const cards = document.querySelectorAll('.card');

new Hequalizer(cards, {
  on: {
    init: ({rows, instance}) => {
      console.log(`Altura inicial: ${rows}px`);
      console.log('ID de instancia:', instance.id);
    },
    afterResize: ({rows, instance}) => {
      console.log(`Nueva altura después de resize: ${rows}px`);
      // Añadir animación al cambiar tamaño
      cards.forEach(card => {
        card.style.transition = 'height 0.3s ease';
      });
    },
    afterChanges: ({rows, instance}) => {
      console.log('Contenido cambió, nueva altura:', rows);
    },
    afterUpdate: ({rows, instance}) => {
      console.log('Actualización manual completada:', rows);
    },
    afterDestroy: ({rows, instance}) => {
      console.log('Instancia destruida:', instance.id);
    }
  }
});

Ejemplo 4: Omitir elementos específicos

<div class="container">
  <div class="item">Elemento normal</div>
  <div class="item skip-height">Este elemento se omite del cálculo</div>
  <div class="item">Elemento normal</div>
  <div class="item skip-height">Este también se omite</div>
</div>
const items = document.querySelectorAll('.item');

new Hequalizer(items, {
  classElementToOmit: 'skip-height'
});

Los elementos con la clase skip-height no se considerarán para calcular la altura máxima, pero sí recibirán la variable CSS con el valor calculado.

Ejemplo 5: Múltiples instancias

// Crear instancias independientes
const instance1 = new Hequalizer(document.querySelectorAll('.group-1'));
const instance2 = new Hequalizer(document.querySelectorAll('.group-2'));

// Ver todas las instancias activas
console.log(window.HequalizerAPI.Instances);

// Actualizar instancia específica manualmente
instance1.update();

// Destruir instancia específica
instance2.destroy(true); // true = remover del registro global

// Remover por ID desde el API global
window.HequalizerAPI.removeInstance(instance1.id);

Ejemplo 6: Variables CSS personalizadas

const elements = document.querySelectorAll('.element');

new Hequalizer(elements, {
  cssVariable: '--card-height'
});
.element {
  min-height: var(--card-height);
  transition: min-height 0.3s ease;
}

Opciones de configuración

new Hequalizer(elements, options)

| Parámetro | Tipo | Descripción | |-----------|------|-------------| | elements | NodeList | Array | Elementos DOM a igualar (obligatorio) | | options | Object | Configuración opcional (ver tabla abajo) |

Opciones disponibles

| Opción | Tipo | Default | Descripción | |--------|------|---------|-------------| | cssVariable | String | '--height' | Nombre de la variable CSS que se aplicará a los elementos | | columns | String | Number | 'all' | Modo de columnas: "all" iguala todos los elementos, o un número para agrupar por columnas | | initialIndex | Number | 0 | Índice desde donde iniciar. Omite elementos anteriores a este índice | | resizeObserver | Boolean | true | Activa/desactiva el MutationObserver y recálculo automático | | classElementToOmit | String | '' | Clase CSS para omitir elementos del cálculo de altura máxima | | on | Object | {} | Objeto con lifecycle hooks (ver sección de Eventos) | | responsive | Object | {} | Configuración responsive con breakpoints (ver siguiente sección) |

Configuración responsive

La opción responsive te permite definir configuraciones específicas para diferentes anchos de viewport:

new Hequalizer(elements, {
  // Configuración base (desktop)
  columns: 3,
  cssVariable: '--desktop-height',

  // Configuraciones responsive
  responsive: {
    1024: {
      columns: 2,
      cssVariable: '--tablet-height'
    },
    768: {
      columns: 1,
      cssVariable: '--mobile-height',
      resizeObserver: false // Desactivar observador en móvil
    }
  }
});

Importante:

  • Los breakpoints se evalúan con <= (menor o igual)
  • Los breakpoints se ordenan automáticamente de menor a mayor
  • Las opciones del breakpoint activo se fusionan con las opciones base
  • Si no coincide ningún breakpoint, se usa la configuración base

API

Constructor

new Hequalizer(elements, options)

Retorna: Instancia de Hequalizer con ID único

Métodos de instancia

| Método | Descripción | |--------|-------------| | update() | Recalcula y actualiza las alturas manualmente | | init() | Reinicializa la instancia (se llama automáticamente al crear la instancia) | | destroy(removeFromAPI = false) | Destruye la instancia: limpia variables CSS, detiene observers y eventos. Si removeFromAPI es true, también elimina la instancia del registro global |

Ejemplo de uso:

const instance = new Hequalizer(elements);

// Actualizar manualmente después de cambios dinámicos
instance.update();

// Destruir sin remover del registro
instance.destroy();

// Destruir y remover del registro global
instance.destroy(true);

Propiedades de instancia

const instance = new Hequalizer(elements, options);

// Propiedades disponibles
instance.id               // String: ID único generado automáticamente
instance.elementsArray    // Array: Elementos originales pasados al constructor
instance.values           // Number | Array: Altura(s) calculada(s)
instance.actualOptions    // Object: Opciones actualmente aplicadas
instance.actualBreakpoint // String | Number: Breakpoint actual activo ("default" o el número del breakpoint)
instance.responsive       // Object: Configuración responsive original

API Global

Hequalizer mantiene un registro global de todas las instancias creadas:

// Acceder al API global
window.HequalizerAPI

// Propiedades y métodos disponibles
window.HequalizerAPI.Init              // Constructor de Hequalizer
window.HequalizerAPI.Instances         // Array con todas las instancias activas
window.HequalizerAPI.removeInstance(id) // Remover instancia por ID

Ejemplo de uso:

// Crear instancias
const inst1 = new Hequalizer(elements1);
const inst2 = new Hequalizer(elements2);

// Ver todas las instancias
console.log(window.HequalizerAPI.Instances); // [inst1, inst2]

// Crear usando el API global
const inst3 = window.HequalizerAPI.Init(elements3, options);

// Remover instancia específica
window.HequalizerAPI.removeInstance(inst1.id);

// Ver instancias restantes
console.log(window.HequalizerAPI.Instances); // [inst2, inst3]

Clases de estado

Hequalizer aplica automáticamente clases CSS durante el ciclo de vida de cálculo de alturas:

| Clase | Descripción | |-------|-------------| | .height-calculating | Se aplica durante el cálculo de alturas | | .height-calculated | Se aplica cuando el cálculo ha finalizado exitosamente | | .height-zero | Se aplica cuando la altura calculada es 0 |

Ejemplo de uso con CSS:

/* Animación durante el cálculo */
.element.height-calculating {
  opacity: 0.5;
  transition: opacity 0.3s;
}

.element.height-calculated {
  opacity: 1;
}

/* Ocultar elementos con altura cero */
.element.height-zero {
  display: none;
}

/* Animación de entrada */
.element.height-calculated {
  animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: translateY(0); }
}

Eventos (Lifecycle Hooks)

Hequalizer proporciona hooks en diferentes etapas del ciclo de vida:

| Hook | Cuándo se ejecuta | Parámetros | |------|-------------------|------------| | init | Después de la inicialización | {rows, instance} | | afterResize | Después de un evento resize | {rows, instance} | | afterChanges | Después de cambios en el DOM detectados por MutationObserver | {rows, instance} | | afterUpdate | Después de llamar manualmente a update() | {rows, instance} | | afterDestroy | Después de destruir la instancia | {rows, instance} |

Parámetros:

  • rows: Altura calculada (Number si columns: "all", Array si columns es un número)
  • instance: Referencia a la instancia de Hequalizer

Ejemplo completo:

const instance = new Hequalizer(elements, {
  on: {
    init: ({rows, instance}) => {
      console.log('✓ Inicializado');
      console.log('Altura:', rows);
      console.log('ID:', instance.id);
      console.log('Breakpoint actual:', instance.actualBreakpoint);
    },

    afterResize: ({rows, instance}) => {
      console.log('↔ Resize detectado');
      console.log('Nueva altura:', rows);

      // Ejemplo: Ejecutar código específico según breakpoint
      if (instance.actualBreakpoint === 768) {
        console.log('Ahora estamos en móvil');
      }
    },

    afterChanges: ({rows, instance}) => {
      console.log('⚡ Contenido cambió');
      console.log('Altura actualizada:', rows);
    },

    afterUpdate: ({rows, instance}) => {
      console.log('🔄 Actualización manual');
      console.log('Altura:', rows);
    },

    afterDestroy: ({rows, instance}) => {
      console.log('✕ Instancia destruida');
      console.log('ID destruido:', instance.id);
    }
  }
});

Modos de columnas

Hequalizer ofrece dos modos de cálculo de altura:

Modo "all" (por defecto)

Todos los elementos se igualan a la altura del elemento más alto:

new Hequalizer(elements, {
  columns: "all"
});

Resultado: Todos los elementos tendrán la misma altura (la del más alto)

Valor retornado en hooks: Number

// Ejemplo: Si el elemento más alto mide 150px
instance.values // 150

Modo columnas numéricas

Agrupa elementos por columnas y cada grupo tiene su propia altura máxima:

new Hequalizer(elements, {
  columns: 3 // Agrupa cada 3 elementos
});

Resultado: Los elementos se dividen en grupos de 3, cada grupo tiene su propia altura máxima

Valor retornado en hooks: Array con las alturas de cada grupo

// Ejemplo: 9 elementos agrupados de 3 en 3
instance.values // [150, 180, 140]
// Grupo 1: 150px, Grupo 2: 180px, Grupo 3: 140px

Ejemplo visual:

<!-- 6 elementos con columns: 2 -->
<div>Elemento 1</div>  ┐
<div>Elemento 2</div>  ┘ Grupo 1: Altura máxima = 120px

<div>Elemento 3</div>  ┐
<div>Elemento 4</div>  ┘ Grupo 2: Altura máxima = 150px

<div>Elemento 5</div>  ┐
<div>Elemento 6</div>  ┘ Grupo 3: Altura máxima = 100px

Sistema responsive

Hequalizer incluye un sistema responsive completo basado en breakpoints.

Funcionamiento

  1. Define breakpoints con window.innerWidth <= breakpoint
  2. Los breakpoints se evalúan de menor a mayor
  3. Las opciones del breakpoint activo se fusionan con las opciones base
  4. Al cambiar el breakpoint, se recalculan las alturas automáticamente

Ejemplo avanzado

const elements = document.querySelectorAll('.card');

new Hequalizer(elements, {
  // Configuración base (desktop > 1024px)
  cssVariable: '--desktop-height',
  columns: 4,
  resizeObserver: true,

  responsive: {
    // Tablets (≤ 1024px)
    1024: {
      cssVariable: '--tablet-height',
      columns: 2
    },

    // Móviles horizontal (≤ 768px)
    768: {
      cssVariable: '--mobile-landscape-height',
      columns: 2
    },

    // Móviles vertical (≤ 480px)
    480: {
      cssVariable: '--mobile-height',
      columns: 1,
      resizeObserver: false // Desactivar observador para mejor performance
    }
  },

  on: {
    afterResize: ({rows, instance}) => {
      console.log('Breakpoint actual:', instance.actualBreakpoint);
      console.log('Opciones aplicadas:', instance.actualOptions);
      console.log('Alturas calculadas:', rows);
    }
  }
});

CSS correspondiente:

.card {
  /* Desktop */
  height: var(--desktop-height);
}

@media (max-width: 1024px) {
  .card {
    /* Tablet */
    height: var(--tablet-height);
  }
}

@media (max-width: 768px) {
  .card {
    /* Mobile landscape */
    height: var(--mobile-landscape-height);
  }
}

@media (max-width: 480px) {
  .card {
    /* Mobile portrait */
    height: var(--mobile-height);
  }
}

Gestión de instancias

Hequalizer proporciona múltiples formas de gestionar instancias:

// 1. Crear instancia y guardar referencia
const myInstance = new Hequalizer(elements, options);

// 2. Acceder a instancia por ID
const instanceId = myInstance.id;
const foundInstance = window.HequalizerAPI.Instances.find(
  inst => inst.id === instanceId
);

// 3. Ver todas las instancias activas
console.log(window.HequalizerAPI.Instances);

// 4. Actualizar instancia específica
myInstance.update();

// 5. Destruir instancia (mantiene en registro)
myInstance.destroy();

// 6. Destruir y remover del registro
myInstance.destroy(true);

// 7. Remover instancia por ID
window.HequalizerAPI.removeInstance(instanceId);

// 8. Acceder a propiedades de la instancia
console.log('Altura actual:', myInstance.values);
console.log('Breakpoint:', myInstance.actualBreakpoint);
console.log('Opciones:', myInstance.actualOptions);

Compatibilidad

Navegadores

  • ✅ Chrome/Edge (últimas 2 versiones)
  • ✅ Firefox (últimas 2 versiones)
  • ✅ Safari 12+
  • ✅ Opera (últimas 2 versiones)

Características requeridas

  • CSS Custom Properties (Variables CSS)
  • MutationObserver API
  • ES6+ (arrow functions, template literals, destructuring)
  • Document.fonts.ready API

Frameworks

Compatible con:

  • ✅ Vanilla JavaScript
  • ✅ React
  • ✅ Vue.js
  • ✅ Angular
  • ✅ Svelte
  • ✅ Next.js
  • ✅ Nuxt.js
  • ✅ Cualquier framework moderno

Ejemplo con React:

import { useEffect, useRef } from 'react';
import Hequalizer from 'hequalizer';

function CardGrid() {
  const instanceRef = useRef(null);

  useEffect(() => {
    const cards = document.querySelectorAll('.card');
    instanceRef.current = new Hequalizer(cards, {
      columns: 3,
      responsive: {
        768: { columns: 1 }
      }
    });

    return () => {
      // Limpiar al desmontar
      if (instanceRef.current) {
        instanceRef.current.destroy(true);
      }
    };
  }, []);

  return (
    <div className="grid">
      <div className="card">Card 1</div>
      <div className="card">Card 2</div>
      <div className="card">Card 3</div>
    </div>
  );
}

Buenas prácticas

  1. Destruye instancias cuando ya no las necesites:

    instance.destroy(true); // Limpia memoria
  2. Usa nombres descriptivos para variables CSS:

    new Hequalizer(elements, {
      cssVariable: '--card-title-height' // En lugar de solo '--height'
    });
  3. Desactiva el observador en móvil para mejor performance:

    responsive: {
      480: {
        resizeObserver: false
      }
    }
  4. Usa initialIndex para omitir elementos iniciales:

    new Hequalizer(elements, {
      initialIndex: 1 // Omite el primer elemento
    });
  5. Aprovecha los lifecycle hooks para debugging:

    on: {
      init: (data) => console.log('Inicializado:', data),
      afterResize: (data) => console.log('Resize:', data)
    }

Funcionamiento Interno

Proceso de Inicialización

Hequalizer sigue un proceso optimizado para asegurar cálculos precisos:

  1. Verificación del DOM: Detecta si el DOM ya está cargado o espera al evento DOMContentLoaded
  2. Espera de fuentes: Utiliza document.fonts.ready para asegurar que todas las fuentes web estén cargadas antes de medir
  3. Configuración: Fusiona las opciones base con las opciones responsive según el viewport actual
  4. Cálculo inicial: Mide las alturas naturales de todos los elementos
  5. Aplicación: Establece la variable CSS con la altura máxima calculada
  6. Observación activa: Inicia los observers para detectar cambios automáticamente

Este proceso asegura que las mediciones sean precisas desde el primer momento, evitando recalculos innecesarios.

Manejo de Fuentes Web

Uno de los problemas comunes al calcular alturas es que las fuentes web pueden cambiar las dimensiones del texto después de cargarse. Hequalizer resuelve esto esperando a que todas las fuentes estén listas:

// Esto ocurre automáticamente al crear una instancia
document.fonts.ready.then(() => {
  // Ahora las mediciones serán precisas
  this.init();
});

Si las fuentes no pueden cargarse por algún motivo, Hequalizer inicializará de todas formas para evitar bloquear la funcionalidad.

Solución de problemas

| Problema | Posible causa | Solución | |----------|---------------|----------| | Las alturas no se actualizan | MutationObserver desactivado | Verifica que resizeObserver: true (es el valor por defecto) | | Las fuentes cambian la altura después | El cálculo se hace antes de cargar las fuentes | Hequalizer espera automáticamente a document.fonts.ready. Verifica que las fuentes se estén cargando correctamente | | Los elementos no tienen la misma altura | Variable CSS no aplicada en CSS | Verifica que tu CSS use height: var(--height) o la variable personalizada | | Performance lenta con muchos elementos | Demasiadas observaciones | Usa resizeObserver: false en breakpoints móviles | | Algunos elementos deben omitirse | No se está usando classElementToOmit | Añade la opción classElementToOmit: 'tu-clase' | | Las alturas no cambian en responsive | Breakpoints mal configurados | Verifica que los breakpoints usen <= en tus media queries CSS | | Error "Cannot read property of null" | Elementos no existen en el DOM | Asegúrate de inicializar Hequalizer después de que el DOM esté listo | | Múltiples instancias causan conflictos | Usando la misma variable CSS | Usa diferentes cssVariable para cada instancia | | Las alturas son 0 | Elementos ocultos o sin contenido | Verifica que los elementos sean visibles y tengan contenido | | No se disparan los lifecycle hooks | Sintaxis incorrecta en opciones | Verifica que uses on: { init: () => {}, ... } |

Contribuir

Las contribuciones son bienvenidas. Por favor:

  1. Fork el proyecto desde GitHub
  2. Crea una rama para tu feature (git checkout -b feature/AmazingFeature)
  3. Commit tus cambios (git commit -m 'Add: nueva característica increíble')
  4. Push a la rama (git push origin feature/AmazingFeature)
  5. Abre un Pull Request

Reportar bugs:

  • Abre un issue en GitHub Issues
  • Incluye pasos para reproducir el problema
  • Especifica navegador y versión

Licencia

Este proyecto está bajo la Licencia MIT. Ver el archivo LICENSE para más detalles.

Autor

Lenin Mazariegos (@soyleninjs)


Si este proyecto te es útil, considera:

  • ⭐ Dar una estrella en GitHub
  • 📦 Compartirlo con otros desarrolladores
  • 🐛 Reportar bugs o sugerir mejoras
  • 💡 Contribuir con código o documentación

Hecho con ❤️ por @soyleninjs