🌟 A lightweight, pure vanilla JavaScript utility library that makes DOM manipulation and event handling simple and efficient. 🌟
6x smaller than jQuery • Zero dependencies • Modern ES6+ • Performance optimized
<!-- Via jsDelivr CDN -->
<script src="https://cdn.jsdelivr.net/gh/lam0819/MicroUI@latest/dist/microui.min.js"></script>
<!-- Via GitHub Releases -->
<script src="https://github.com/lam0819/MicroUI/releases/latest/download/microui.min.js"></script>
Why Vanilla JS? • Performance • Examples • Building • Contributing
- Pure Vanilla JS: Zero dependencies, no frameworks, just native JavaScript
- Ultra Lightweight: Only 18.2KB minified (5.1KB gzipped) - 6x smaller than jQuery
- Modern: Built with ES6+ features and Promise-based APIs
- Fast: Event delegation by default, optimized for performance
- Complete: Includes DOM manipulation, AJAX, animations, components, and more
- Simple: Clean, intuitive API that's easy to learn
- No Build Required: Drop in a script tag and start coding
Modern web development has become unnecessarily complex. While frameworks like React, Vue, and Angular are powerful, they often introduce:
- Build Complexity: Webpack, Babel, and countless dependencies
- Bundle Bloat: Megabytes of JavaScript for simple interactions
- Learning Overhead: New syntax, concepts, and paradigms
- Runtime Overhead: Virtual DOM diffing and framework abstractions
jQuery revolutionized web development by making DOM manipulation simple and cross-browser compatible. However:
- Outdated: Built for IE6 era, carries legacy baggage
- Large: 87KB minified, 30KB gzipped - too heavy for modern needs
- Monolithic: Can't tree-shake unused features
- Not Modern: No ES6+, Promises, or modern JavaScript features
"Maximum functionality, minimum complexity"
MicroUI brings back the simplicity of jQuery while embracing modern JavaScript:
// jQuery way (2006)
$(document).ready(function() {
$('.button').click(function() {
$(this).addClass('clicked');
});
});
// MicroUI way (2024)
MicroUI.ready(() => {
MicroUI.on('click', '.button', function() {
MicroUI.addClass(this, 'clicked');
});
});
No frameworks. No dependencies. Just JavaScript.
MicroUI is built entirely with native browser APIs, making it:
- No Virtual DOM: Direct DOM manipulation is faster for most use cases
- Zero Runtime Overhead: No framework initialization or abstractions
- Native Speed: Direct access to browser APIs without wrappers
- Memory Efficient: No framework memory footprint
- Familiar API: If you know jQuery, you know MicroUI
- Modern Features: Promises, async/await, ES6+ syntax
- TypeScript Ready: Full type definitions included
- No Build Required: Drop in a script tag and start coding
- Web Standards: Built on stable browser APIs
- Framework Agnostic: Use with React, Vue, or anything
- Future Proof: Vanilla JavaScript never goes out of style
- Zero Breaking Changes: Stable API you can depend on
Feature | MicroUI | jQuery | React | Alpine.js | Vanilla JS |
---|---|---|---|---|---|
Bundle Size | 5.1KB gzipped | 30KB gzipped | 42KB+ gzipped | 15KB gzipped | 0KB |
Learning Curve | ⭐⭐ Easy | ⭐⭐ Easy | ⭐⭐⭐⭐⭐ Steep | ⭐⭐⭐ Medium | ⭐⭐⭐⭐ Hard |
Build Required | ❌ Optional | ❌ No | ✅ Yes | ❌ No | ❌ No |
Modern Syntax | ✅ ES6+ | ❌ ES5 | ✅ JSX | ✅ ES6+ | ✅ Native |
Component System | ✅ Built-in | ❌ Plugins | ✅ Core | ✅ Directives | ❌ Manual |
Event Delegation | ✅ Default | ✅ Manual | ❌ Manual | ✅ Auto | ❌ Manual |
Animation API | ✅ Web Animations | ❌ CSS only | ❌ CSS/Libraries | ❌ CSS only | ✅ Native |
AJAX Promises | ✅ Native | ❌ Custom | ❌ External | ❌ Fetch | ✅ Native |
TypeScript | ✅ Included | ⭐ Community | ✅ First-class | ❌ Limited | ✅ Native |
- Content Websites: Blogs, marketing sites, documentation
- E-commerce: Product pages, shopping carts, checkout flows
- Dashboards: Admin panels, analytics interfaces
- Progressive Enhancement: Adding interactivity to existing sites
- Prototyping: Quick experiments and proof of concepts
- Team Onboarding: Easy for junior developers to understand
- Complex SPAs: Applications with heavy state management
- Real-time Apps: Chat applications, collaborative tools
- Data-Heavy UIs: Large tables, complex visualizations
- Team Standardization: If your team is already invested in a framework
// Traditional Framework Component
function TodoApp() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
const addTodo = useCallback(() => {
setTodos(prev => [...prev, { id: Date.now(), text: inputValue }]);
setInputValue('');
}, [inputValue]);
return (
<div>
<input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
onKeyPress={e => e.key === 'Enter' && addTodo()}
/>
<button onClick={addTodo}>Add</button>
{todos.map(todo => (
<div key={todo.id}>{todo.text}</div>
))}
</div>
);
}
// MicroUI Component
MicroUI.component('todo-app', {
template: `
<div>
<input class="todo-input" placeholder="Add todo...">
<button class="add-btn">Add</button>
<div class="todos"></div>
</div>
`,
events: {
'click .add-btn': 'addTodo',
'keypress .todo-input': function(e) {
if (e.key === 'Enter') this.methods.addTodo();
}
},
methods: {
addTodo() {
const input = MicroUI.$('.todo-input');
const text = input.value.trim();
if (text) {
MicroUI.append('.todos', `<div>${text}</div>`);
input.value = '';
}
}
}
});
Performance Benefits:
- Faster Initial Load: Smaller bundle = quicker downloads and parsing
- Lower Memory Usage: No framework overhead, minimal runtime footprint
- Better Mobile Performance: Less JavaScript to parse and execute
- Improved Core Web Vitals: Smaller bundles improve Lighthouse scores
MicroUI delivers exceptional performance through modern optimization techniques:
# Production Build Sizes (Automated via GitHub Actions)
Original: ~45KB (source code)
Minified: 18.2KB (60% reduction)
Gzipped: 5.1KB (89% reduction)
# Comparison with Popular Libraries (Gzipped)
jQuery 3.7: 30KB (5.8x larger)
React 18: 13KB (2.5x larger)
Vue 3: 16KB (3.1x larger)
Alpine.js: 15KB (2.9x larger)
- Event Delegation: All events use delegation by default (faster than direct binding)
- DOM Optimization: Smart caching and batched operations
- Memory Efficient: Minimal memory footprint with automatic cleanup
- Native APIs: Direct browser API usage for maximum speed
- Tree Shakable: Import only the modules you need
MicroUI prioritizes performance through:
- Zero Dependencies: No framework overhead or initialization cost
- Small Bundle Size: 5.1KB gzipped means faster downloads and parsing
- Native JavaScript: Direct browser API access without abstractions
- Event Delegation: Efficient event handling for dynamic content
- Minimal Overhead: Direct DOM manipulation without virtual DOM diffing
# Download time on different connections
MicroUI (5.1KB gzipped):
- Fast 3G: ~50ms
- Slow 3G: ~165ms
- 2G: ~665ms
jQuery (30KB gzipped):
- Fast 3G: ~300ms
- Slow 3G: ~1000ms
- 2G: ~4000ms
- User Experience: Faster loading = better user engagement
- SEO Benefits: Google factors page speed into search rankings
- Mobile Performance: Critical for slower devices and networks
- Developer Productivity: Less build time, faster development cycles
- Hosting Costs: Smaller bundles = less bandwidth = lower costs
<!-- Via jsDelivr CDN (Latest) -->
<script src="https://cdn.jsdelivr.net/gh/lam0819/MicroUI@latest/dist/microui.min.js"></script>
<!-- Via jsDelivr CDN (Specific Version) -->
<script src="https://cdn.jsdelivr.net/gh/lam0819/[email protected]/dist/microui.min.js"></script>
<!-- Via unpkg CDN -->
<script src="https://unpkg.com/@extralam/microui@latest/dist/microui.min.js"></script>
npm install @extralam/microui
// ES6 Import
import MicroUI from '@extralam/microui';
// CommonJS
const MicroUI = require('@extralam/microui');
Download the latest release from GitHub Releases
<!-- Local file -->
<script src="microui.min.js"></script>
<!-- ES Module -->
<script type="module">
import MicroUI from 'https://unpkg.com/@extralam/microui@latest/dist/microui.esm.js';
// Your code here
</script>
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/lam0819/MicroUI@latest/dist/microui.min.js"></script>
</head>
<body>
<button class="my-button">Click me!</button>
<script>
// DOM ready
MicroUI.ready(() => {
// Event handling
MicroUI.on('click', '.my-button', function() {
this.textContent = 'Clicked!';
// AJAX request
MicroUI.get('/api/data')
.then(data => console.log(data));
});
});
</script>
</body>
</html>
MicroUI is built around a few core principles:
- Event Delegation: All events use delegation for better performance
- Promise-Based: All async operations return Promises
- Modular: Use only what you need
- Vanilla JS: No new syntax or compilation required
MicroUI.ready(() => {
console.log('DOM is ready!');
});
// Basic event
MicroUI.on('click', '.button', function(e) {
console.log('Clicked:', this);
});
// Multiple events
MicroUI.on('mouseenter mouseleave', '.hover', function(e) {
this.classList.toggle('active');
});
// One-time event
MicroUI.once('click', '.one-time', function() {
console.log('This only fires once');
});
// Remove events
MicroUI.off('click', '.button');
// Query elements
const element = MicroUI.$('.my-element');
const elements = MicroUI.$$('.all-elements');
// Manipulate classes
MicroUI.addClass(element, 'active highlight');
MicroUI.removeClass(element, 'inactive');
MicroUI.toggleClass(element, 'visible');
// Insert content
MicroUI.append('.container', '<div>New content</div>');
MicroUI.prepend('.container', '<div>First content</div>');
MicroUI.html('.container', '<p>Replace all content</p>');
// Attributes and data
MicroUI.attr(element, 'id', 'my-id');
MicroUI.data(element, 'user', { name: 'John', age: 30 });
// GET request
MicroUI.get('/api/users')
.then(users => console.log(users))
.catch(error => console.error(error));
// POST request
MicroUI.post('/api/users', {
name: 'John Doe',
email: '[email protected]'
}).then(response => console.log(response));
// Load HTML
MicroUI.load('.content', '/partial.html');
// Fade effects
MicroUI.fadeIn('.element', 300);
MicroUI.fadeOut('.element', 300, () => console.log('Fade complete'));
// Slide effects
MicroUI.slideDown('.dropdown', 400);
MicroUI.slideUp('.dropdown', 400);
// Custom animation
MicroUI.animate('.box', {
transform: ['translateX(0)', 'translateX(100px)'],
opacity: [1, 0.5]
}, {
duration: 500,
easing: 'ease-out'
});
Attach an event handler using delegation.
MicroUI.on('click', '.button', function(e) {
console.log('Clicked:', this);
});
Remove event handlers.
MicroUI.off('click', '.button');
Attach a handler that fires only once.
MicroUI.once('submit', '.form', function(e) {
e.preventDefault();
console.log('Form submitted once');
});
Trigger a custom event.
MicroUI.trigger('.element', 'customEvent', { value: 42 });
Query single element (with caching).
const header = MicroUI.$('.header');
Query multiple elements.
const buttons = MicroUI.$$('.button');
Add one or more classes.
MicroUI.addClass(element, 'active highlight');
Remove one or more classes.
MicroUI.removeClass(element, 'inactive');
Toggle a class.
MicroUI.toggleClass(element, 'visible');
Check if element has class.
if (MicroUI.hasClass(element, 'active')) {
// ...
}
Perform GET request.
MicroUI.get('/api/data', {
headers: { 'Authorization': 'Bearer token' }
}).then(data => console.log(data));
Perform POST request.
MicroUI.post('/api/users', { name: 'John' })
.then(response => console.log(response));
Generic AJAX request.
MicroUI.ajax({
url: '/api/data',
method: 'PUT',
data: { id: 1, name: 'Updated' },
headers: { 'Content-Type': 'application/json' }
}).then(response => console.log(response));
Fade in an element.
MicroUI.fadeIn('.modal', 300, () => {
console.log('Fade in complete');
});
Fade out an element.
MicroUI.fadeOut('.modal', 300);
Slide down animation.
MicroUI.slideDown('.dropdown', 400);
Custom animation using Web Animations API.
MicroUI.animate('.box', {
transform: ['scale(1)', 'scale(1.2)', 'scale(1)'],
opacity: [1, 0.8, 1]
}, {
duration: 1000,
iterations: Infinity
});
Create debounced function.
const search = MicroUI.debounce((query) => {
console.log('Searching:', query);
}, 300);
Create throttled function.
const handleScroll = MicroUI.throttle(() => {
console.log('Scrolling');
}, 100);
Merge objects.
const config = MicroUI.extend({}, defaults, userOptions);
LocalStorage wrapper.
// Set
MicroUI.store.set('user', { name: 'John', age: 30 });
// Get
const user = MicroUI.store.get('user');
// Remove
MicroUI.store.remove('user');
// Clear all
MicroUI.store.clear();
SessionStorage wrapper.
MicroUI.session.set('token', 'abc123');
const token = MicroUI.session.get('token');
Create reusable component.
MicroUI.component('counter', {
template: `
<div class="counter">
<button class="dec">-</button>
<span class="value">{{count}}</span>
<button class="inc">+</button>
</div>
`,
state: {
count: 0
},
methods: {
increment() {
this.state.count++;
this.update();
},
decrement() {
this.state.count--;
this.update();
}
},
events: {
'click .inc': 'increment',
'click .dec': 'decrement'
},
lifecycle: {
created() {
console.log('Component created');
},
mounted() {
console.log('Component mounted');
}
}
});
// Mount component
MicroUI.mount('.app', 'counter', { count: 10 });
Create event delegation namespace.
const cart = MicroUI.delegate('shoppingCart', {
'click .add-to-cart': function(e) {
console.log('Adding to cart');
},
'click .remove-item': function(e) {
console.log('Removing item');
}
});
// Add more handlers
cart.on('click', '.checkout', handleCheckout);
// Remove handlers
cart.off('click', '.add-to-cart');
// Destroy all
cart.destroy();
microui/
├── dist/
│ ├── microui.js # Development build
│ ├── microui.min.js # Production build
│ └── microui.esm.js # ES Module build
├── src/
│ ├── core/
│ │ ├── dom.js # DOM utilities
│ │ ├── events.js # Event system
│ │ ├── ajax.js # AJAX utilities
│ │ └── utils.js # Helper functions
│ ├── modules/
│ │ ├── animation.js # Animation module
│ │ ├── storage.js # Storage utilities
│ │ ├── component.js # Component system
│ │ └── delegate.js # Delegation system
│ └── index.js # Main entry point
├── examples/
│ ├── basic.html # Basic examples
│ └── advanced.html # Advanced UI components (tabs, modals, dropdowns)
├── tests/
│ ├── dom.test.js
│ ├── events.test.js
│ └── ajax.test.js
├── llms.txt # LLM-friendly codebase documentation
├── package.json
├── rollup.config.js # Build configuration
├── README.md
└── LICENSE
- Node.js 14+
- npm or yarn
# Clone repository
git clone https://github.com/lam0819/microui.git
cd microui
# Install dependencies
npm install
# Development build
npm run build:dev
# Production build
npm run build
# Watch mode
npm run watch
# Run tests
npm test
# Run examples server
npm run serve
The project uses Rollup for building:
// rollup.config.js
import { terser } from 'rollup-plugin-terser';
import babel from '@rollup/plugin-babel';
export default [
// Development build
{
input: 'src/index.js',
output: {
file: 'dist/microui.js',
format: 'umd',
name: 'MicroUI'
},
plugins: [
babel({ babelHelpers: 'bundled' })
]
},
// Production build
{
input: 'src/index.js',
output: {
file: 'dist/microui.min.js',
format: 'umd',
name: 'MicroUI'
},
plugins: [
babel({ babelHelpers: 'bundled' }),
terser()
]
},
// ES Module build
{
input: 'src/index.js',
output: {
file: 'dist/microui.esm.js',
format: 'es'
},
plugins: [
babel({ babelHelpers: 'bundled' })
]
}
];
# Run all tests
npm test
# Run specific test file
npm test dom.test.js
# Run with coverage
npm run test:coverage
# Watch mode
npm run test:watch
// tests/dom.test.js
import { describe, it, expect } from '@jest/globals';
import MicroUI from '../src/index.js';
describe('DOM Utilities', () => {
it('should add classes', () => {
const element = document.createElement('div');
MicroUI.addClass(element, 'active highlight');
expect(element.classList.contains('active')).toBe(true);
expect(element.classList.contains('highlight')).toBe(true);
});
it('should query elements', () => {
document.body.innerHTML = '<div class="test"></div>';
const element = MicroUI.$('.test');
expect(element).toBeTruthy();
expect(element.className).toBe('test');
});
});
- Interactive Demo Site - Complete showcase with all features
- Basic Examples - Core functionality demonstrations
- Advanced Components - Tabs, modals, dropdowns, accordions, and more
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/lam0819/MicroUI@latest/dist/microui.min.js"></script>
<style>
.todo { padding: 10px; margin: 5px; background: #f0f0f0; }
.todo.completed { opacity: 0.5; text-decoration: line-through; }
</style>
</head>
<body>
<div class="app">
<h1>Todo List</h1>
<form class="todo-form">
<input type="text" class="todo-input" placeholder="Add todo...">
<button type="submit">Add</button>
</form>
<div class="todos"></div>
</div>
<script>
MicroUI.ready(() => {
// Handle form submission
MicroUI.on('submit', '.todo-form', function(e) {
e.preventDefault();
const input = MicroUI.$('.todo-input');
const text = input.value.trim();
if (text) {
const todoId = Date.now();
MicroUI.append('.todos', `
<div class="todo" data-id="${todoId}">
<input type="checkbox" class="todo-check">
<span class="todo-text">${text}</span>
<button class="todo-delete">Delete</button>
</div>
`);
input.value = '';
// Save to storage
const todos = MicroUI.store.get('todos') || [];
todos.push({ id: todoId, text, completed: false });
MicroUI.store.set('todos', todos);
}
});
// Handle checkbox
MicroUI.on('change', '.todo-check', function() {
const todo = MicroUI.closest(this, '.todo');
MicroUI.toggleClass(todo, 'completed', this.checked);
// Update storage
const todoId = parseInt(todo.dataset.id);
const todos = MicroUI.store.get('todos') || [];
const index = todos.findIndex(t => t.id === todoId);
if (index !== -1) {
todos[index].completed = this.checked;
MicroUI.store.set('todos', todos);
}
});
// Handle delete
MicroUI.on('click', '.todo-delete', function() {
const todo = MicroUI.closest(this, '.todo');
const todoId = parseInt(todo.dataset.id);
// Fade out and remove
MicroUI.fadeOut(todo, 300, () => {
MicroUI.remove(todo);
// Update storage
let todos = MicroUI.store.get('todos') || [];
todos = todos.filter(t => t.id !== todoId);
MicroUI.store.set('todos', todos);
});
});
// Load saved todos
const savedTodos = MicroUI.store.get('todos') || [];
savedTodos.forEach(todo => {
MicroUI.append('.todos', `
<div class="todo ${todo.completed ? 'completed' : ''}" data-id="${todo.id}">
<input type="checkbox" class="todo-check" ${todo.completed ? 'checked' : ''}>
<span class="todo-text">${todo.text}</span>
<button class="todo-delete">Delete</button>
</div>
`);
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/lam0819/MicroUI@latest/dist/microui.min.js"></script>
</head>
<body>
<div id="app"></div>
<script>
// Define counter component
MicroUI.component('counter', {
template: `
<div class="counter" style="padding: 20px; border: 1px solid #ddd; margin: 10px;">
<h3>{{title}}</h3>
<button class="dec">-</button>
<span style="margin: 0 20px; font-size: 24px;">{{count}}</span>
<button class="inc">+</button>
<button class="reset">Reset</button>
</div>
`,
props: {
title: 'Counter',
initial: 0
},
state: {
count: 0
},
methods: {
increment() {
this.state.count++;
this.update();
},
decrement() {
this.state.count--;
this.update();
},
reset() {
this.state.count = this.props.initial;
this.update();
}
},
events: {
'click .inc': 'increment',
'click .dec': 'decrement',
'click .reset': 'reset'
},
lifecycle: {
created() {
this.state.count = this.props.initial;
}
}
});
// Mount multiple counters
MicroUI.mount('#app', 'counter', { title: 'Products', initial: 0 });
MicroUI.mount('#app', 'counter', { title: 'Users', initial: 100 });
MicroUI.mount('#app', 'counter', { title: 'Orders', initial: 50 });
</script>
</body>
</html>
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature
- Make your changes
- Add tests for new functionality
- Run tests:
npm test
- Commit changes:
git commit -m "Add my feature"
- Push to branch:
git push origin feature/my-feature
- Submit a pull request
- Use ES6+ features
- Follow ESLint configuration
- Add JSDoc comments for public APIs
- Keep functions small and focused
- Write tests for new features
- Update README.md for user-facing changes
- Update
llms.txt
for codebase architecture changes - Add examples for new features
- Include JSDoc comments for all public APIs
MIT License - see LICENSE file for details.
Created by MicroUI
Inspired by jQuery's simplicity and modern JavaScript best practices.