Apple Liquid Glass-inspired glass effects for the web
A WebGL-powered library bringing sophisticated glass JS components with real-time refraction, blur, and masking
- ๐ฏ Three Shape Types: Rounded rectangles, perfect circles, and pill/capsule shapes
- ๐ Real-time Refraction: Advanced WebGL shaders with multi-layer glass effects
- ๐ Nested Glass System: Child elements sample parent container outputs
- โก Live Parameter Control: Real-time adjustment of all glass properties
- ๐ฑ Responsive Design: Automatic sizing and viewport adaptation
- ๐จ Customizable Tinting: Per-instance opacity and gradient control
- ๐ Cross-browser: Modern browser support with WebGL
- ๐ฆ Zero Dependencies: Pure JavaScript (except html2canvas for page sampling)
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="glass.css" />
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
<script src="container.js"></script>
<script src="button.js"></script>
<script>
// Create a glass button
const button = new Button({
text: 'Click Me!',
size: 32,
type: 'rounded',
onClick: () => alert('Hello Glass!')
})
document.body.appendChild(button.element)
</script>
</body>
</html>// Create a glass container
const container = new Container({
borderRadius: 24,
type: 'pill',
tintOpacity: 0.3
})
// Add glass buttons to container
const button1 = new Button({
text: 'Action',
size: 24,
type: 'pill'
})
const button2 = new Button({
text: 'โ',
size: 24,
type: 'circle'
})
container.addChild(button1)
container.addChild(button2)
document.body.appendChild(container.element)| Option | Type | Default | Description |
|---|---|---|---|
borderRadius |
number |
48 |
Corner radius in pixels |
type |
string |
'rounded' |
Shape type: 'rounded', 'circle', or 'pill' |
tintOpacity |
number |
0.2 |
Tint overlay opacity (0-1) |
// Add child element (enables nested glass)
container.addChild(childElement)
// Remove child element
container.removeChild(childElement)
// Force size update from DOM
container.updateSizeFromDOM()Extends Container with button-specific functionality.
| Option | Type | Default | Description |
|---|---|---|---|
text |
string |
'Button' |
Button text content |
size |
number |
48 |
Font size in pixels |
type |
string |
'rounded' |
Shape type: 'rounded', 'circle', or 'pill' |
onClick |
function |
null |
Click event handler |
warp |
boolean |
false |
Enable center distortion effect |
tintOpacity |
number |
0.2 |
Tint overlay opacity (0-1) |
const button = new Button({
text: 'Save Changes',
size: 28,
type: 'pill',
tintOpacity: 0.4,
warp: true,
onClick: text => {
console.log(`${text} was clicked!`)
}
})The library provides fine-grained control over glass rendering:
| Parameter | Range | Description |
|---|---|---|
| Edge Intensity | 0-0.1 | Refraction strength at shape edges |
| Rim Intensity | 0-0.2 | Intensity of rim lighting effects |
| Base Intensity | 0-0.05 | Center distortion strength |
| Edge Distance | 0.05-0.5 | Falloff curve for edge effects |
| Rim Distance | 0.1-2.0 | Falloff curve for rim effects |
| Base Distance | 0.05-0.3 | Falloff curve for base effects |
| Corner Boost | 0-0.1 | Additional corner enhancement |
| Ripple Effect | 0-0.5 | Surface texture simulation |
| Blur Radius | 1-15 | Background blur amount |
| Tint Opacity | 0-1.0 | Gradient overlay strength |
// Global glass parameters
window.glassControls = {
edgeIntensity: 0.02,
rimIntensity: 0.08,
blurRadius: 7.0,
tintOpacity: 0.3
}
// Update all instances
function updateAllGlassInstances() {
Container.instances.forEach(instance => {
if (instance.gl_refs && instance.gl_refs.gl) {
const gl = instance.gl_refs.gl
gl.uniform1f(instance.gl_refs.edgeIntensityLoc, window.glassControls.edgeIntensity)
// ... update other uniforms
if (instance.render) instance.render()
}
})
}const rounded = new Button({
type: 'rounded',
borderRadius: 16 // Custom radius
})const circle = new Button({
type: 'circle',
size: 32 // Determines circle diameter
})const pill = new Button({
type: 'pill',
text: 'Elongated Button' // Auto-sizing
})The library provides semantic CSS classes:
/* Glass containers */
.glass-container {
/* Base container styles */
}
.glass-container-circle {
/* Circle-specific styles */
}
.glass-container-pill {
/* Pill-specific styles */
}
/* Glass buttons */
.glass-button {
/* Base button styles */
}
.glass-button-circle {
/* Circle button styles */
}
.glass-button-text {
/* Button text overlay */
}/* Dark theme example */
.glass-button {
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.4);
}
.glass-button-text {
color: #ffffff;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}- Multi-layer refraction: Separate edge, rim, and base calculations
- Shape-aware normals: Different algorithms per shape type
- Gaussian blur sampling: 13ร13 adaptive kernel
- Real-time page capture: html2canvas integration
- Dynamic uniforms: Live parameter updates
liquid-glass-js/
โโโ container.js # Core Container class
โโโ button.js # Button class (extends Container)
โโโ demo.js # Demo setup and controls
โโโ styles.css # Base styling
โโโ glass.css # Glass component styles
โโโ demo.css # Demo layout styles
โโโ controls.css # Control panel styles
โโโ index.html # Demo page
| Browser | Version | Status |
|---|---|---|
| Chrome | 80+ | โ Full support |
| Firefox | 75+ | โ Full support |
| Safari | 14+ | โ Full support |
| Edge | 80+ | โ Full support |
Requirements:
- WebGL 2.0 support
- ES6+ JavaScript features
- HTML5 Canvas API
# Clone the repository
git clone https://github.com/your-username/liquid-glass-js.git
cd liquid-glass-js
# Open in browser (requires local server for WebGL)
# For example, using serve
npx serve .No build step required! The library uses vanilla JavaScript and can be used directly.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow existing code style
- Add comments for complex WebGL operations
- Test across different browsers
- Update documentation for new features
const navContainer = new Container({
type: 'rounded',
borderRadius: 20,
tintOpacity: 0.1
})
;['Home', 'About', 'Contact'].forEach(text => {
const navButton = new Button({
text: text,
size: 16,
type: 'pill',
onClick: text => navigate(text)
})
navContainer.addChild(navButton)
})const controlPanel = new Container({
type: 'rounded',
borderRadius: 12,
tintOpacity: 0.6
})
const playButton = new Button({
text: 'โถ',
size: 24,
type: 'circle',
onClick: () => player.play()
})
controlPanel.addChild(playButton)- Bundle for NPM
- TypeScript rewrite
- React/Vue component wrappers
- Animation system
- Accessibility improvements
- Performance optimizations
- Mobile touch optimizations
This project is licensed under the MIT License - see the LICENSE file for details.
- Inspired by Apple's Liquid Glass design language
- WebGL techniques from various computer graphics resources
- html2canvas library for page capture functionality
Built with โค๏ธ for the future of web interfaces
Demo โข Issues โข Discussions
