@cristiancuray/mz-css
v1.0.4
Published
mz.css is a framework-agnostic CSS/SASS library with responsive grid up to 5K, local fonts/icons, and optional reusable JavaScript interactions
Maintainers
Readme
mz.css
Librería CSS/SASS ligera inspirada en MaterializeCSS con sistema de grid responsivo hasta 5K y componentes CSS-only sin JavaScript.
Autor: Cristian Curay [email protected]
Versión: 1.0.3
✨ Características
- 🎯 Sistema de grid de 12 columnas con soporte hasta 5K (5120px)
- 📱 9 breakpoints responsivos:
s,m,l,xl,xxl,hd,qhd,uhd,fk - 🎨 Paleta de colores Material Design completamente personalizable
- 🔤 Fuentes incluidas: Lato (default), Roboto, Roboto Mono, Material Icons
- ⚡ CSS-only interactivo: Modals, dropdowns, tabs, accordions sin JavaScript
- 🧩 24+ componentes: Buttons, badges, cards, forms, tables, alerts, datepicker, file input, etc.
- 📦 Sin dependencias obligatorias de JavaScript (DatePicker incluye helper opcional)
- ⚙️ Interactividad opcional reusable con
js/base-ui.js(SSR/SPA/framework agnostic) - 🔧 CLI incluido para purgar CSS no usado
- 🌐 Compatible con Angular, React, Vue, Svelte, Next.js, etc.
📦 Instalación
npm install @cristiancuray/mz-css🚀 Uso
CSS puro
<link rel="stylesheet" href="node_modules/@cristiancuray/mz-css/css/main.css">SASS/SCSS
// Importar toda la librería
@use '@cristiancuray/mz-css/sass/main';
// O importar módulos individuales
@use '@cristiancuray/mz-css/sass/grid';
@use '@cristiancuray/mz-css/sass/buttons';
@use '@cristiancuray/mz-css/sass/cards';Personalizar variables
@use '@cristiancuray/mz-css/sass/variables' with (
$color-primary: #6200ea,
$font-family-base: $font-family-roboto,
$gutter: 20px
);
@use '@cristiancuray/mz-css/sass/main';📐 Sistema de Grid
Breakpoints
| Clase | Min-width | Dispositivo |
|-------|-----------|-------------|
| s | 600px | Móviles |
| m | 768px | Tablets |
| l | 992px | Laptops |
| xl | 1200px | Monitores HD |
| xxl | 1500px | Monitores grandes |
| hd | 1920px | Full HD |
| qhd | 2560px | 2K / QHD |
| uhd | 3840px | 4K UHD |
| fk | 5120px | 5K |
Ejemplo
<div class="container">
<div class="row">
<div class="col s12 m6 l4 xl3">Columna responsiva</div>
<div class="col s12 m6 l4 xl3">Columna responsiva</div>
<div class="col s12 m6 l4 xl3">Columna responsiva</div>
<div class="col s12 m6 l4 xl3">Columna responsiva</div>
</div>
</div>Offsets
<div class="col s12 m6 offset-m3">Columna centrada</div>🧩 Componentes
Buttons
<!-- Variantes -->
<button class="btn btn-primary">Primary</button>
<button class="btn btn-outline-primary">Outline</button>
<button class="btn btn-soft-primary">Soft</button>
<button class="btn btn-ghost">Ghost</button>
<!-- Tamaños -->
<button class="btn btn-primary btn-xs">Extra Small</button>
<button class="btn btn-primary btn-sm">Small</button>
<button class="btn btn-primary btn-lg">Large</button>
<button class="btn btn-primary btn-xl">Extra Large</button>
<!-- Con iconos -->
<button class="btn btn-primary">
<i class="material-icons">add</i>
Add Item
</button>
<!-- Icon button -->
<button class="btn btn-icon btn-primary">
<i class="material-icons">favorite</i>
</button>
<!-- Button group -->
<div class="btn-group">
<button class="btn btn-primary">Left</button>
<button class="btn btn-primary">Middle</button>
<button class="btn btn-primary">Right</button>
</div>
<!-- Pill shape -->
<button class="btn btn-primary btn-pill">Pill Button</button>
<!-- Loading state -->
<button class="btn btn-primary btn-loading">Loading</button>
<!-- FAB (Floating Action Button) -->
<button class="btn btn-primary btn-fab">
<i class="material-icons">add</i>
</button>Badges & Chips
<!-- Badges -->
<span class="badge badge-primary">Primary</span>
<span class="badge badge-soft-success">Soft</span>
<span class="badge badge-outline-danger">Outline</span>
<span class="badge badge-primary badge-pill">Pill</span>
<!-- Badge dot (indicador) -->
<span class="badge badge-danger badge-dot"></span>
<span class="badge badge-success badge-dot badge-dot-pulse"></span>
<!-- Status badges -->
<span class="badge-status badge-status-online">Online</span>
<span class="badge-status badge-status-busy">Busy</span>
<!-- Version badge -->
<span class="badge-version">
<span class="badge-version-label">version</span>
<span class="badge-version-number">1.0.2</span>
</span>
<!-- Tags -->
<span class="tag tag-primary">Feature</span>
<span class="tag tag-success">Complete</span>
<!-- Chips -->
<span class="chip">Basic Chip</span>
<span class="chip chip-avatar">
<img src="avatar.jpg" class="chip-img">
John Doe
<button class="chip-close"></button>
</span>Cards
<!-- Card básica -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Title</h3>
</div>
<div class="card-body">
<p>Card content goes here.</p>
</div>
<div class="card-footer">
<button class="btn btn-primary">Action</button>
</div>
</div>
<!-- Card con imagen -->
<div class="card">
<img src="image.jpg" class="card-img-top" alt="...">
<div class="card-body">
<h3 class="card-title">Card Title</h3>
<p class="card-text">Description text.</p>
</div>
</div>
<!-- Card hover -->
<div class="card card-hover">...</div>
<!-- Pricing card -->
<div class="card card-pricing">
<div class="card-pricing-header">
<span class="card-pricing-name">Pro Plan</span>
<div class="card-pricing-price">
<span class="card-pricing-currency">$</span>
<span class="card-pricing-amount">29</span>
<span class="card-pricing-period">/month</span>
</div>
</div>
<ul class="card-pricing-features">
<li class="card-pricing-feature">
<i class="material-icons">check</i>
Feature 1
</li>
</ul>
</div>Dropdowns (CSS-only)
<!-- Dropdown con checkbox hack -->
<div class="dropdown">
<input type="checkbox" id="dd1" class="dropdown-toggle-input">
<label for="dd1" class="dropdown-toggle">Options</label>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">
<i class="material-icons">person</i>
Profile
</a>
<a href="#" class="dropdown-item">Settings</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item dropdown-item-danger">Sign out</a>
</div>
</div>
<!-- Dropdown hover -->
<div class="dropdown dropdown-hover">
<button class="dropdown-toggle">Hover Menu</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action 1</a>
<a href="#" class="dropdown-item">Action 2</a>
</div>
</div>
<!-- Posiciones -->
<div class="dropdown-menu dropdown-menu-end">...</div> <!-- Derecha -->
<div class="dropup">...</div> <!-- Arriba -->Tabs (CSS-only)
<div class="tabs">
<input type="radio" name="tabs" id="tab1" class="tab-input" checked>
<input type="radio" name="tabs" id="tab2" class="tab-input">
<ul class="tab-nav">
<li class="tab-item">
<label for="tab1" class="tab-link">Home</label>
</li>
<li class="tab-item">
<label for="tab2" class="tab-link">Profile</label>
</li>
</ul>
<div class="tab-content">
<div id="tabpane1" class="tab-pane">Home content</div>
<div id="tabpane2" class="tab-pane">Profile content</div>
</div>
</div>
<!-- Variantes -->
<div class="tabs tabs-pills">...</div>
<div class="tabs tabs-underline">...</div>
<div class="tabs tabs-boxed">...</div>Accordions (CSS-only)
<div class="accordion">
<div class="accordion-item">
<input type="checkbox" id="acc1" class="accordion-input" checked>
<label for="acc1" class="accordion-header">Section 1</label>
<div class="accordion-body">
<div class="accordion-content">
Content for section 1.
</div>
</div>
</div>
<div class="accordion-item">
<input type="checkbox" id="acc2" class="accordion-input">
<label for="acc2" class="accordion-header">Section 2</label>
<div class="accordion-body">
<div class="accordion-content">
Content for section 2.
</div>
</div>
</div>
</div>
<!-- Variantes -->
<div class="accordion accordion-flush">...</div>
<div class="accordion accordion-separated">...</div>
<div class="accordion accordion-plus-minus">...</div>Tooltips (CSS-only)
<!-- Usando data-tooltip -->
<button data-tooltip="This is a tooltip!">Hover me</button>
<button data-tooltip="Bottom tooltip" data-tooltip-position="bottom">Bottom</button>
<button data-tooltip="Left tooltip" data-tooltip-position="left">Left</button>
<button data-tooltip="Right tooltip" data-tooltip-position="right">Right</button>
<!-- Colores -->
<span data-tooltip="Info" data-tooltip-color="primary">Primary</span>
<span data-tooltip="Success" data-tooltip-color="success">Success</span>
<span data-tooltip="Error" data-tooltip-color="danger">Danger</span>
<!-- Multiline -->
<span data-tooltip="Long text here..." data-tooltip-multiline>Multiline</span>
<!-- Help tooltip -->
<span class="help-tooltip" data-tooltip="Help text here"></span>Modals (CSS-only)
<!-- Trigger -->
<label for="modal1" class="btn btn-primary">Open Modal</label>
<!-- Modal -->
<input type="checkbox" id="modal1" class="modal-toggle">
<div class="modal">
<label for="modal1" class="modal-backdrop"></label>
<div class="modal-box">
<label for="modal1" class="modal-close">×</label>
<h3 class="modal-title">Modal Title</h3>
<p>Modal content goes here.</p>
<div class="modal-actions">
<label for="modal1" class="btn btn-outline-secondary">Cancel</label>
<button class="btn btn-primary">Confirm</button>
</div>
</div>
</div>Alerts
<div class="alert alert-success">
<i class="material-icons alert-icon">check_circle</i>
<div class="alert-content">
<div class="alert-title">Success!</div>
<div class="alert-message">Your action was completed.</div>
</div>
</div>
<!-- Variantes -->
<div class="alert alert-danger">...</div>
<div class="alert alert-warning">...</div>
<div class="alert alert-info">...</div>
<!-- Con botón de cerrar -->
<div class="alert alert-info alert-dismissible">
<span class="alert-message">Dismissible alert</span>
<input type="checkbox" id="alert1" class="alert-close-toggle">
<label for="alert1" class="alert-close">×</label>
</div>Navbar
<nav class="navbar">
<div class="navbar-brand">
<a href="#" class="navbar-logo">Logo</a>
</div>
<input type="checkbox" id="nav-toggle" class="navbar-toggle-input">
<label for="nav-toggle" class="navbar-toggle">
<span class="navbar-toggle-icon"></span>
</label>
<div class="navbar-menu">
<ul class="navbar-nav">
<li class="navbar-item">
<a href="#" class="navbar-link active">Home</a>
</li>
<li class="navbar-item">
<a href="#" class="navbar-link">About</a>
</li>
</ul>
</div>
</nav>Sidebar
<input type="checkbox" id="sidebar-toggle" class="sidebar-toggle">
<aside class="sidebar">
<div class="sidebar-header">
<span class="sidebar-logo">Dashboard</span>
</div>
<nav class="sidebar-nav">
<a href="#" class="sidebar-link active">
<i class="material-icons">dashboard</i>
<span>Dashboard</span>
</a>
<a href="#" class="sidebar-link">
<i class="material-icons">people</i>
<span>Users</span>
</a>
</nav>
</aside>Forms
<!-- Input básico -->
<div class="input-field">
<label for="name">Name</label>
<input type="text" id="name" placeholder="Your name">
</div>
<!-- Input con label flotante -->
<div class="input-field input-float">
<input type="email" id="email" placeholder=" ">
<label for="email">Email</label>
</div>
<!-- Estados de validación -->
<div class="input-field input-success">...</div>
<div class="input-field input-error">...</div>
<!-- Select -->
<div class="input-field">
<label for="country">Country</label>
<select id="country">
<option value="">Select...</option>
<option value="us">United States</option>
</select>
</div>
<!-- Checkbox -->
<label class="checkbox">
<input type="checkbox">
<span class="checkbox-mark"></span>
Accept terms
</label>
<!-- Radio -->
<label class="radio">
<input type="radio" name="plan" value="free">
<span class="radio-mark"></span>
Free Plan
</label>DatePicker (CSS + JS opcional)
El componente DatePicker funciona con estructura CSS-only para abrir/cerrar con checkbox hack y puede usar un helper JavaScript opcional para navegacion, seleccion, eventos e i18n.
<div
id="demo-datepicker"
class="datepicker-wrapper"
data-value="2024-03-20"
data-format="DD/MM/YYYY"
data-locale="es"
>
<input type="checkbox" id="datepicker-toggle-demo" class="datepicker-toggle">
<label for="datepicker-toggle-demo" class="datepicker-overlay"></label>
<div class="datepicker-input">
<input type="text" placeholder="Select date" readonly>
<span class="datepicker-icon"><i class="material-icons">calendar_today</i></span>
</div>
<label for="datepicker-toggle-demo" class="datepicker-trigger"></label>
<div class="datepicker">
<div class="datepicker-nav">
<button type="button" class="datepicker-nav-btn"><i class="material-icons">chevron_left</i></button>
<span class="datepicker-title">March 2024</span>
<button type="button" class="datepicker-nav-btn"><i class="material-icons">chevron_right</i></button>
</div>
<div class="datepicker-calendar">
<div class="datepicker-weekdays"></div>
<div class="datepicker-days"></div>
</div>
<div class="datepicker-footer">
<button type="button" class="datepicker-btn btn-today">Today</button>
<button type="button" class="datepicker-btn btn-cancel">Cancel</button>
<button type="button" class="datepicker-btn btn-ok">OK</button>
</div>
</div>
</div>
<script src="node_modules/@cristiancuray/mz-css/js/datepicker.js"></script>
<script>
const instances = DatePicker.init();
const demo = DatePicker.getInstance('#demo-datepicker');
// Cambio de locale en runtime
demo?.setLocale('es');
demo?.on('change', (date) => {
console.log('Selected date:', date);
});
</script>Opciones principales:
format: formato de salida (YYYY-MM-DD,DD/MM/YYYY, etc.)locale: idioma (en,es,pt,fr)firstDayOfWeek: inicio de semana (0domingo,1lunes)minDate/maxDate: limites de fechadisabledDates: fechas deshabilitadas
API publica:
getValue()/getFormattedValue()setValue(date)/clear()open()/close()setLocale(locale)on(event, callback)/off(event, callback)
Base UI (JS opcional para componentes)
base-ui.js agrega interacciones reutilizables sobre componentes CSS-only, con API simple y flags por feature.
<script src="node_modules/@cristiancuray/mz-css/js/base-ui.js"></script>
<script>
const ui = BaseCSSUI.init({
forms: true,
paginator: true,
alerts: true,
auth: true,
navbar: true,
sidebar: true,
modals: true,
cardsButtonsBadges: true,
tabs: true,
accordion: true,
tooltips: true,
fileUpload: true
});
// Crear una instancia aislada en un root especifico
// const scoped = BaseCSSUI.create({ tabs: true, tooltips: true });
// scoped.init(document.getElementById('my-section'));
</script>Tables
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th class="numeric">Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>[email protected]</td>
<td class="numeric">28</td>
</tr>
</tbody>
</table>
<!-- Tabla responsiva -->
<div class="table-responsive">
<table class="table">...</table>
</div>
<!-- Tabla con filtros avanzados + sort + búsqueda inteligente -->
<div id="users-filter-demo" class="table-filter-demo">
<div class="table-filter-toolbar">
<input id="users-smart-search" type="search" placeholder="Buscar por coincidencia...">
<input id="users-date-from" type="date">
<input id="users-date-to" type="date">
<select id="users-score-op">
<option value="">Sin filtro</option>
<option value=">">Mayor que</option>
<option value="<">Menor que</option>
<option value="=">Igual</option>
</select>
<input id="users-score-value" type="number" placeholder="Score">
<select id="users-sort-by">
<option value="">Sin ordenar</option>
<option value="createdAt">Fecha alta</option>
<option value="score">Score</option>
</select>
<select id="users-sort-dir">
<option value="asc">Asc</option>
<option value="desc">Desc</option>
</select>
</div>
<table id="users-filter-table" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Nombre</th>
<th>
Rol
<button type="button" class="filter-trigger" data-filter-column="role">
<i class="material-icons">filter_alt</i>
</button>
<div class="filter-menu" data-filter-menu="role"></div>
</th>
<th>
Estado
<button type="button" class="filter-trigger" data-filter-column="status">
<i class="material-icons">filter_alt</i>
</button>
<div class="filter-menu" data-filter-menu="status"></div>
</th>
</tr>
</thead>
<tbody>
<tr data-role="Admin" data-status="Activo" data-created-at="2025-01-12" data-score="95">...</tr>
<tr data-role="Analista" data-status="Pendiente" data-created-at="2025-02-19" data-score="67">...</tr>
</tbody>
</table>
</div>
<script>
// Data desde JSON/array
const usersData = [
{ id: 1, name: 'Camila Rivera', role: 'Admin', status: 'Activo', createdAt: '2025-01-12', score: 95 }
];
// Props/config simple para prender o apagar capacidades
const tableConfig = {
data: usersData,
features: {
menuFilters: true,
smartSearch: true,
sort: true,
dateRange: true,
numericCompare: true
}
};
// const table = createSmartTable(tableConfig)
// table.setFeature('smartSearch', false)
// table.setFeature('dateRange', true)
// (implementacion completa en test-lib/index.html)
// Incluye:
// - filtros por valores unicos desde data-* con buscador interno en cada menu flotante
// - filtro por fecha (desde/hasta)
// - comparadores numericos (> >= = <= <)
// - sort asc/desc por columna
// - busqueda inteligente por coincidencia
// initFloatingTableFilters();
</script>Dividers
<hr class="divider">
<hr class="divider divider-dashed">
<hr class="divider divider-gradient">
<!-- Con texto -->
<div class="divider-text">
<span>OR</span>
</div>Shadow Utilities
<div class="shadow-sm">Small shadow</div>
<div class="shadow">Default shadow</div>
<div class="shadow-md">Medium shadow</div>
<div class="shadow-lg">Large shadow</div>
<div class="shadow-xl">Extra large shadow</div>
<div class="shadow-none">No shadow</div>Text Utilities
<!-- Colores -->
<span class="text-primary">Primary text</span>
<span class="text-success">Success text</span>
<span class="bg-primary text-light">Background</span>
<!-- Tamaños -->
<span class="text-xs">Extra small</span>
<span class="text-sm">Small</span>
<span class="text-lg">Large</span>
<span class="text-xl">Extra large</span>
<!-- Peso -->
<span class="font-light">Light</span>
<span class="font-bold">Bold</span>
<!-- Alineación -->
<p class="text-center">Centered</p>
<p class="text-right">Right aligned</p>
<!-- Familias de fuentes -->
<span class="font-lato">Lato font</span>
<span class="font-roboto">Roboto font</span>
<span class="font-mono">Monospace font</span>🔧 CLI - PurgeCSS
La librería incluye un CLI para eliminar CSS no utilizado:
# Crear configuración
npx mz-css init
# Purgar CSS no usado
npx mz-css purge
# Con opciones
npx mz-css purge --output dist/ --css path/to/file.css
# Ver ayuda
npx mz-css helpResultado típico
[mz.css] Original size: 169 KB
[mz.css] Purged CSS: 45 KB (73% reduction)
[mz.css] Output: ./dist/main.css📁 Estructura
mz.css/
├── css/
│ └── main.css # CSS compilado
├── js/
│ ├── datepicker.js # Helper JS opcional para DatePicker
│ └── base-ui.js # Interacciones opcionales para componentes
├── sass/
│ ├── _variables.scss # Variables globales
│ ├── _fonts.scss # @font-face
│ ├── main.scss # Entry point
│ ├── base.scss # Reset y base
│ ├── grid.scss # Sistema de grid
│ ├── buttons.scss # Botones
│ ├── badges.scss # Badges y chips
│ ├── cards.scss # Cards
│ ├── dropdowns.scss # Dropdowns
│ ├── tabs.scss # Tabs
│ ├── accordions.scss # Accordions
│ ├── tooltips.scss # Tooltips
│ ├── modals.scss # Modals
│ ├── navbar.scss # Navbar
│ ├── sidebar.scss # Sidebar
│ ├── forms.scss # Formularios
│ ├── file-input.scss # File input/upload
│ ├── table.scss # Tablas
│ ├── alerts.scss # Alertas
│ ├── dividers.scss # Divisores
│ ├── paginator.scss # Paginación
│ ├── icon.scss # Iconos
│ ├── text.scss # Utilidades de texto
│ ├── shadows.scss # Utilidades de sombras
│ ├── datepicker.scss # DatePicker
│ ├── bento.scss # Bento grid
│ └── auth.scss # Auth forms
├── fonts/
│ ├── lato/ # Fuente Lato
│ ├── roboto/ # Fuente Roboto
│ ├── roboto-mono/ # Fuente monospace
│ └── material-icons/ # Iconos Material
├── bin/
│ └── cli.js # CLI para purge
└── package.json🛠 Desarrollo
# Instalar dependencias
npm install
# Compilar SASS
npm run build
# Compilar expandido (debug)
npm run build:expanded
# Watch mode
npm run watch📄 Licencia
MIT License - Cristian Curay [email protected]
