🚀 Oferta especial: 60% OFF no CrazyStack - Últimas vagas!Garantir vaga →
Design UI

Efeito Visual Moderno Liquid Glass

Crie o efeito de vidro realista com CSS para sites modernos, inspirado no novo visual do iOS

Visual Fluido

Efeito no iOS Liquid Glass

Novo visual da Apple. Um design mais limpo, moderno e realista usando camadas e blur avançado—e o melhor, você pode replicar com CSS.

100%
CSS Puro
Todos
Navegadores Modernos
glass-effect.css
.glass { backdrop-filter: blur(20px) saturate(180%); background-color: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 16px; }

Como funciona o efeito Liquid Glass

Não é só desfoque. É uma combinação de camadas, transparência e contraste para gerar profundidade e realismo visual.

🏗️ Estrutura HTML Base para Liquid Glass

index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Liquid Glass Effect - iOS Style</title>
    <link rel="stylesheet" href="liquid-glass.css">
</head>
<body>
    <!-- 🌌 Container principal com background complexo -->
    <div class="liquid-container">
        <!-- ✨ Card principal com efeito liquid glass -->
        <div class="liquid-glass-card">
            <div class="card-header">
                <h2>Liquid Glass</h2>
                <span class="status-indicator"></span>
            </div>
            
            <div class="card-content">
                <p>Este é o efeito Liquid Glass inspirado no design da Apple.</p>
                <div class="metrics">
                    <div class="metric">
                        <span class="value">98%</span>
                        <span class="label">Transparência</span>
                    </div>
                    <div class="metric">
                        <span class="value">20px</span>
                        <span class="label">Blur Radius</span>
                    </div>
                </div>
            </div>
            
            <div class="card-actions">
                <button class="liquid-button primary">Ação Principal</button>
                <button class="liquid-button secondary">Secundária</button>
            </div>
        </div>
        
        <!-- 🎯 Menu flutuante com liquid glass -->
        <div class="liquid-menu">
            <div class="menu-item active">
                <span class="icon">🏠</span>
                <span class="text">Home</span>
            </div>
            <div class="menu-item">
                <span class="icon">👤</span>
                <span class="text">Profile</span>
            </div>
            <div class="menu-item">
                <span class="icon">⚙️</span>
                <span class="text">Settings</span>
            </div>
        </div>
        
        <!-- 💧 Elementos decorativos fluidos -->
        <div class="liquid-orbs">
            <div class="orb orb-1"></div>
            <div class="orb orb-2"></div>
            <div class="orb orb-3"></div>
        </div>
    </div>
</body>
</html>

🎨 CSS Completo do Liquid Glass

liquid-glass.css
/* 🌌 Container principal com background complexo */
.liquid-container {
    min-height: 100vh;
    background: 
        radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
        radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%),
        radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.2) 0%, transparent 50%),
        linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%);
    padding: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;
}

/* ✨ Card principal com liquid glass effect */
.liquid-glass-card {
    background: rgba(255, 255, 255, 0.02);
    backdrop-filter: blur(20px) saturate(180%) brightness(110%);
    -webkit-backdrop-filter: blur(20px) saturate(180%) brightness(110%);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 24px;
    padding: 2rem;
    max-width: 420px;
    width: 100%;
    position: relative;
    overflow: hidden;
    
    /* 🌈 Gradiente sutil interno */
    box-shadow: 
        inset 0 1px 0 rgba(255, 255, 255, 0.1),
        0 20px 40px rgba(0, 0, 0, 0.3),
        0 1px 3px rgba(255, 255, 255, 0.1);
}

/* 🌟 Reflexo superior liquid */
.liquid-glass-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(
        90deg, 
        transparent, 
        rgba(255, 255, 255, 0.3) 20%, 
        rgba(255, 255, 255, 0.6) 50%, 
        rgba(255, 255, 255, 0.3) 80%, 
        transparent
    );
    border-radius: 24px 24px 0 0;
}

/* 💫 Brilho interno fluido */
.liquid-glass-card::after {
    content: '';
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(
        circle, 
        rgba(255, 255, 255, 0.03) 0%, 
        transparent 70%
    );
    animation: liquidFlow 8s ease-in-out infinite;
    pointer-events: none;
}

@keyframes liquidFlow {
    0%, 100% { transform: translate(-25%, -25%) rotate(0deg); }
    33% { transform: translate(-30%, -20%) rotate(120deg); }
    66% { transform: translate(-20%, -30%) rotate(240deg); }
}

/* 📋 Header do card */
.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.card-header h2 {
    color: white;
    font-size: 1.5rem;
    font-weight: 600;
    margin: 0;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.status-indicator {
    width: 8px;
    height: 8px;
    background: #00ff88;
    border-radius: 50%;
    box-shadow: 0 0 10px rgba(0, 255, 136, 0.5);
    animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.7; transform: scale(1.2); }
}

/* 📄 Conteúdo do card */
.card-content {
    margin-bottom: 2rem;
}

.card-content p {
    color: rgba(255, 255, 255, 0.8);
    font-size: 1rem;
    line-height: 1.6;
    margin: 0 0 1.5rem 0;
}

/* 📊 Métricas */
.metrics {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.metric {
    background: rgba(255, 255, 255, 0.03);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: 12px;
    padding: 1rem;
    text-align: center;
}

.metric .value {
    display: block;
    color: #00ff88;
    font-size: 1.25rem;
    font-weight: 700;
    margin-bottom: 0.25rem;
}

.metric .label {
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* 🎯 Botões liquid glass */
.card-actions {
    display: flex;
    gap: 0.75rem;
}

.liquid-button {
    flex: 1;
    padding: 12px 20px;
    border: none;
    border-radius: 12px;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    transition: all 0.3s ease;
    backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
}

.liquid-button.primary {
    background: rgba(0, 255, 136, 0.15);
    color: #00ff88;
    border: 1px solid rgba(0, 255, 136, 0.3);
}

.liquid-button.primary:hover {
    background: rgba(0, 255, 136, 0.25);
    border-color: rgba(0, 255, 136, 0.5);
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(0, 255, 136, 0.2);
}

.liquid-button.secondary {
    background: rgba(255, 255, 255, 0.05);
    color: rgba(255, 255, 255, 0.8);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.liquid-button.secondary:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.2);
    transform: translateY(-2px);
}

/* 🍽️ Menu flutuante */
.liquid-menu {
    position: fixed;
    bottom: 2rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    background: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(20px) saturate(150%);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 20px;
    padding: 0.5rem;
    gap: 0.25rem;
}

.menu-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    border-radius: 14px;
    cursor: pointer;
    transition: all 0.3s ease;
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.9rem;
}

.menu-item.active {
    background: rgba(255, 255, 255, 0.1);
    color: white;
}

.menu-item:hover:not(.active) {
    background: rgba(255, 255, 255, 0.05);
    color: rgba(255, 255, 255, 0.8);
}

.menu-item .icon {
    font-size: 1.1rem;
}

/* 💧 Orbs decorativos fluidos */
.liquid-orbs {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: -1;
}

.orb {
    position: absolute;
    border-radius: 50%;
    filter: blur(40px);
    animation: float 6s ease-in-out infinite;
}

.orb-1 {
    width: 200px;
    height: 200px;
    background: radial-gradient(circle, rgba(120, 119, 198, 0.3) 0%, transparent 70%);
    top: 10%;
    left: 80%;
    animation-delay: 0s;
}

.orb-2 {
    width: 150px;
    height: 150px;
    background: radial-gradient(circle, rgba(255, 119, 198, 0.2) 0%, transparent 70%);
    bottom: 20%;
    left: 10%;
    animation-delay: 2s;
}

.orb-3 {
    width: 100px;
    height: 100px;
    background: radial-gradient(circle, rgba(120, 219, 255, 0.25) 0%, transparent 70%);
    top: 60%;
    right: 15%;
    animation-delay: 4s;
}

@keyframes float {
    0%, 100% { transform: translate(0, 0) scale(1); }
    33% { transform: translate(-20px, -20px) scale(1.1); }
    66% { transform: translate(20px, -10px) scale(0.9); }
}

/* 📱 Responsividade */
@media (max-width: 768px) {
    .liquid-container {
        padding: 1rem;
    }
    
    .liquid-glass-card {
        padding: 1.5rem;
    }
    
    .metrics {
        grid-template-columns: 1fr;
    }
    
    .card-actions {
        flex-direction: column;
    }
    
    .liquid-menu {
        left: 1rem;
        right: 1rem;
        transform: none;
    }
    
    .menu-item .text {
        display: none;
    }
}

Camadas Visuais

Integrar camadas sem opacidade total deixa o fundo visível e ajuda a criar o efeito realista de profundidade.

Mais que Blur

Usar apenas blur gera um efeito superficial. A chave está na combinação com transparência, brilho e bordas suaves.

Aplicações Versáteis

Use o efeito em qualquer stack web

CSS Puro

Sem bibliotecas externas. Totalmente replicável com propriedades atuais de CSS.

Compatível com Tudo

Adicione em projetos feitos com código puro, WordPress, Framer e outros.

Resultado Realista

Estética refinada que imita materiais translúcidos e objetos sólidos.

Implementação Avançada

Técnicas avançadas para um efeito liquid glass profissional

⚡ JavaScript para Interatividade

liquid-glass-interactions.js
// 📁 liquid-glass-interactions.js
// 🎯 JavaScript para adicionar interações fluidas

class LiquidGlassEffects {
    constructor() {
        this.init();
        this.setupEventListeners();
        this.startAnimations();
    }

    // 🚀 Inicialização
    init() {
        this.container = document.querySelector('.liquid-container');
        this.card = document.querySelector('.liquid-glass-card');
        this.orbs = document.querySelectorAll('.orb');
        this.buttons = document.querySelectorAll('.liquid-button');
        
        // 📱 Check for mobile
        this.isMobile = window.innerWidth <= 768;
        
        console.log('🌊 Liquid Glass Effects initialized');
    }

    // 🎧 Event Listeners
    setupEventListeners() {
        // 🖱️ Mouse tracking para efeitos de paralaxe
        if (!this.isMobile) {
            this.container.addEventListener('mousemove', (e) => {
                this.handleMouseMove(e);
            });
        }

        // 📱 Touch events para mobile
        this.container.addEventListener('touchmove', (e) => {
            this.handleTouchMove(e);
        });

        // 🎯 Button interactions
        this.buttons.forEach(button => {
            button.addEventListener('mouseenter', () => {
                this.enhanceButton(button);
            });
            
            button.addEventListener('mouseleave', () => {
                this.resetButton(button);
            });
        });

        // 🔄 Resize handler
        window.addEventListener('resize', () => {
            this.handleResize();
        });

        // 👀 Intersection Observer para animações
        this.setupIntersectionObserver();
    }

    // 🖱️ Mouse Move Handler
    handleMouseMove(event) {
        const rect = this.container.getBoundingClientRect();
        const x = event.clientX - rect.left;
        const y = event.clientY - rect.top;
        
        // 📊 Calculate percentages
        const xPercent = (x / rect.width) * 100;
        const yPercent = (y / rect.height) * 100;
        
        // 🎨 Apply parallax to card
        this.applyParallax(xPercent, yPercent);
        
        // 💧 Move orbs
        this.moveOrbs(xPercent, yPercent);
        
        // ✨ Update glass reflection
        this.updateReflection(xPercent, yPercent);
    }

    // 📱 Touch Move Handler
    handleTouchMove(event) {
        if (event.touches.length === 1) {
            const touch = event.touches[0];
            const rect = this.container.getBoundingClientRect();
            const x = touch.clientX - rect.left;
            const y = touch.clientY - rect.top;
            
            const xPercent = (x / rect.width) * 100;
            const yPercent = (y / rect.height) * 100;
            
            this.applyParallax(xPercent, yPercent);
        }
    }

    // 🎨 Apply Parallax Effect
    applyParallax(xPercent, yPercent) {
        // 📐 Calculate transform values
        const tiltX = (yPercent - 50) / 10; // -5 to 5
        const tiltY = (50 - xPercent) / 10; // -5 to 5
        const translateX = (xPercent - 50) / 20; // -2.5 to 2.5
        const translateY = (yPercent - 50) / 20; // -2.5 to 2.5
        
        // 🎯 Apply transform to card
        this.card.style.transform = `
            perspective(1000px) 
            rotateX(${tiltX}deg) 
            rotateY(${tiltY}deg) 
            translateX(${translateX}px) 
            translateY(${translateY}px)
        `;
    }

    // 💧 Move Orbs
    moveOrbs(xPercent, yPercent) {
        this.orbs.forEach((orb, index) => {
            const speed = 0.5 + (index * 0.2);
            const x = (xPercent - 50) * speed;
            const y = (yPercent - 50) * speed;
            
            orb.style.transform = `translate(${x}px, ${y}px)`;
        });
    }

    // ✨ Update Glass Reflection
    updateReflection(xPercent, yPercent) {
        const reflection = this.card.querySelector('::before');
        if (reflection) {
            const angle = Math.atan2(yPercent - 50, xPercent - 50) * 180 / Math.PI;
            reflection.style.background = `
                linear-gradient(
                    ${angle}deg, 
                    transparent, 
                    rgba(255, 255, 255, 0.3) 20%, 
                    rgba(255, 255, 255, 0.6) 50%, 
                    rgba(255, 255, 255, 0.3) 80%, 
                    transparent
                )
            `;
        }
    }

    // 🎯 Enhance Button
    enhanceButton(button) {
        // 💫 Add ripple effect
        const ripple = document.createElement('div');
        ripple.className = 'ripple-effect';
        ripple.style.cssText = `
            position: absolute;
            top: 50%;
            left: 50%;
            width: 0;
            height: 0;
            background: rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            transform: translate(-50%, -50%);
            animation: ripple 0.6s ease-out;
            pointer-events: none;
        `;
        
        button.style.position = 'relative';
        button.appendChild(ripple);
        
        // 🗑️ Remove ripple after animation
        setTimeout(() => {
            if (ripple.parentNode) {
                ripple.parentNode.removeChild(ripple);
            }
        }, 600);
    }

    // 🔄 Reset Button
    resetButton(button) {
        // Reset any temporary effects
        button.style.transform = 'translateY(0)';
    }

    // 📱 Handle Resize
    handleResize() {
        this.isMobile = window.innerWidth <= 768;
        
        // 🔄 Reset transforms on resize
        if (this.isMobile) {
            this.card.style.transform = '';
            this.orbs.forEach(orb => {
                orb.style.transform = '';
            });
        }
    }

    // 👀 Intersection Observer
    setupIntersectionObserver() {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    entry.target.classList.add('animate-in');
                }
            });
        }, {
            threshold: 0.1,
            rootMargin: '50px'
        });

        // 🎯 Observe elements
        observer.observe(this.card);
        this.orbs.forEach(orb => observer.observe(orb));
    }

    // 🚀 Start Continuous Animations
    startAnimations() {
        // 🌊 Liquid wave animation
        this.startLiquidWave();
        
        // 💫 Particle system
        this.startParticleSystem();
    }

    // 🌊 Liquid Wave Animation
    startLiquidWave() {
        let time = 0;
        
        const animate = () => {
            time += 0.01;
            
            // 📐 Calculate wave values
            const wave1 = Math.sin(time) * 10;
            const wave2 = Math.cos(time * 1.5) * 15;
            
            // 🎨 Apply to orbs
            this.orbs.forEach((orb, index) => {
                const offset = index * 0.5;
                const x = Math.sin(time + offset) * 20;
                const y = Math.cos(time + offset) * 15;
                
                orb.style.transform = `translate(${x}px, ${y}px) scale(${1 + Math.sin(time + offset) * 0.1})`;
            });
            
            requestAnimationFrame(animate);
        };
        
        animate();
    }

    // 💫 Particle System
    startParticleSystem() {
        const particles = [];
        const particleCount = this.isMobile ? 10 : 20;
        
        // 🎨 Create particles
        for (let i = 0; i < particleCount; i++) {
            const particle = document.createElement('div');
            particle.className = 'liquid-particle';
            particle.style.cssText = `
                position: absolute;
                width: 2px;
                height: 2px;
                background: rgba(255, 255, 255, 0.3);
                border-radius: 50%;
                pointer-events: none;
                z-index: 1;
            `;
            
            this.container.appendChild(particle);
            
            particles.push({
                element: particle,
                x: Math.random() * window.innerWidth,
                y: Math.random() * window.innerHeight,
                vx: (Math.random() - 0.5) * 2,
                vy: (Math.random() - 0.5) * 2,
                opacity: Math.random() * 0.5 + 0.2
            });
        }
        
        // 🔄 Animate particles
        const animateParticles = () => {
            particles.forEach(particle => {
                particle.x += particle.vx;
                particle.y += particle.vy;
                
                // 🔄 Wrap around edges
                if (particle.x < 0) particle.x = window.innerWidth;
                if (particle.x > window.innerWidth) particle.x = 0;
                if (particle.y < 0) particle.y = window.innerHeight;
                if (particle.y > window.innerHeight) particle.y = 0;
                
                // 🎨 Update position
                particle.element.style.transform = `translate(${particle.x}px, ${particle.y}px)`;
                particle.element.style.opacity = particle.opacity;
            });
            
            requestAnimationFrame(animateParticles);
        };
        
        animateParticles();
    }
}

// 🚀 Initialize on DOM load
document.addEventListener('DOMContentLoaded', () => {
    new LiquidGlassEffects();
});

// 💫 CSS for ripple animation
const style = document.createElement('style');
style.textContent = `
    @keyframes ripple {
        to {
            width: 100px;
            height: 100px;
            opacity: 0;
        }
    }
    
    .animate-in {
        animation: fadeInUp 0.8s ease-out forwards;
    }
    
    @keyframes fadeInUp {
        from {
            opacity: 0;
            transform: translateY(30px);
        }
        to {
            opacity: 1;
            transform: translateY(0);
        }
    }
    
    .liquid-particle {
        transition: all 0.3s ease;
    }
`;
document.head.appendChild(style);

⚛️ Implementação com React/Next.js

components/LiquidGlassCard.tsx
// 📁 components/LiquidGlassCard.tsx
'use client';

import React, { useEffect, useRef, useState } from 'react';
import { motion, useMotionValue, useSpring, useTransform } from 'framer-motion';

interface LiquidGlassCardProps {
  children: React.ReactNode;
  className?: string;
  intensity?: number;
  enableParallax?: boolean;
}

export function LiquidGlassCard({ 
  children, 
  className = '', 
  intensity = 1,
  enableParallax = true 
}: LiquidGlassCardProps) {
  const cardRef = useRef<HTMLDivElement>(null);
  const [isHovered, setIsHovered] = useState(false);
  
  // 🎯 Motion values para parallax
  const mouseX = useMotionValue(0);
  const mouseY = useMotionValue(0);
  
  // 🌊 Spring animations
  const rotateX = useSpring(useTransform(mouseY, [-0.5, 0.5], [15 * intensity, -15 * intensity]));
  const rotateY = useSpring(useTransform(mouseX, [-0.5, 0.5], [-15 * intensity, 15 * intensity]));
  
  // 🖱️ Mouse move handler
  const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
    if (!enableParallax || !cardRef.current) return;
    
    const rect = cardRef.current.getBoundingClientRect();
    const x = (event.clientX - rect.left) / rect.width - 0.5;
    const y = (event.clientY - rect.top) / rect.height - 0.5;
    
    mouseX.set(x);
    mouseY.set(y);
  };
  
  // 🔄 Reset on mouse leave
  const handleMouseLeave = () => {
    setIsHovered(false);
    mouseX.set(0);
    mouseY.set(0);
  };

  return (
    <motion.div
      ref={cardRef}
      className={\`liquid-glass-card \${className}\`}
      style={{
        rotateX: enableParallax ? rotateX : 0,
        rotateY: enableParallax ? rotateY : 0,
        transformStyle: 'preserve-3d',
      }}
      onMouseMove={handleMouseMove}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={handleMouseLeave}
      whileHover={{ scale: 1.02 }}
      transition={{ type: 'spring', stiffness: 300, damping: 30 }}
    >
      {/* 🌟 Dynamic reflection */}
      <motion.div
        className="absolute inset-0 rounded-[24px] pointer-events-none"
        style={{
          background: useTransform(
            [mouseX, mouseY],
            ([x, y]) => \`
              linear-gradient(
                \${Math.atan2(y, x) * 180 / Math.PI}deg,
                transparent,
                rgba(255, 255, 255, 0.1) 50%,
                transparent
              )
            \`
          ),
        }}
      />
      
      {/* 💫 Content */}
      <div className="relative z-10">
        {children}
      </div>
      
      {/* ✨ Floating orbs */}
      {isHovered && (
        <>
          <motion.div
            className="absolute w-16 h-16 bg-blue-400/20 rounded-full blur-xl"
            initial={{ scale: 0, x: 0, y: 0 }}
            animate={{
              scale: [0, 1, 0],
              x: [0, 50, -30, 0],
              y: [0, -30, 40, 0],
            }}
            transition={{ duration: 3, repeat: Infinity }}
            style={{ top: '20%', left: '70%' }}
          />
          <motion.div
            className="absolute w-12 h-12 bg-purple-400/20 rounded-full blur-lg"
            initial={{ scale: 0, x: 0, y: 0 }}
            animate={{
              scale: [0, 1, 0],
              x: [0, -40, 20, 0],
              y: [0, 20, -25, 0],
            }}
            transition={{ duration: 2.5, repeat: Infinity, delay: 0.5 }}
            style={{ bottom: '30%', left: '20%' }}
          />
        </>
      )}
    </motion.div>
  );
}

// 📁 components/LiquidButton.tsx
export function LiquidButton({
  children,
  onClick,
  variant = 'primary',
  className = ''
}: {
  children: React.ReactNode;
  onClick?: () => void;
  variant?: 'primary' | 'secondary';
  className?: string;
}) {
  const [ripples, setRipples] = useState<Array<{ id: number; x: number; y: number }>>([]);
  
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    const rect = event.currentTarget.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;
    
    const newRipple = {
      id: Date.now(),
      x,
      y
    };
    
    setRipples(prev => [...prev, newRipple]);
    
    // 🗑️ Remove ripple after animation
    setTimeout(() => {
      setRipples(prev => prev.filter(ripple => ripple.id !== newRipple.id));
    }, 600);
    
    onClick?.();
  };

  return (
    <motion.button
      className={`liquid-button \${variant} \${className}`}
      onClick={handleClick}
      whileHover={{ scale: 1.05, y: -2 }}
      whileTap={{ scale: 0.95 }}
      transition={{ type: 'spring', stiffness: 400, damping: 17 }}
    >
      {/* 💫 Ripple effects */}
      {ripples.map(ripple => (
        <motion.div
          key={ripple.id}
          className="absolute rounded-full bg-white/30 pointer-events-none"
          initial={{
            width: 0,
            height: 0,
            x: ripple.x,
            y: ripple.y,
            opacity: 1
          }}
          animate={{
            width: 100,
            height: 100,
            x: ripple.x - 50,
            y: ripple.y - 50,
            opacity: 0
          }}
          transition={{ duration: 0.6, ease: 'easeOut' }}
        />
      ))}
      
      <span className="relative z-10">{children}</span>
    </motion.button>
  );
}

// 📁 app/liquid-glass-demo/page.tsx
export default function LiquidGlassDemoPage() {
  return (
    <div className="liquid-container">
      <LiquidGlassCard className="max-w-md">
        <div className="card-header">
          <h2>Liquid Glass React</h2>
          <div className="status-indicator" />
        </div>
        
        <div className="card-content">
          <p>Implementação com React, Framer Motion e TypeScript.</p>
          
          <div className="metrics">
            <div className="metric">
              <span className="value">100%</span>
              <span className="label">TypeScript</span>
            </div>
            <div className="metric">
              <span className="value">60fps</span>
              <span className="label">Performance</span>
            </div>
          </div>
        </div>
        
        <div className="card-actions">
          <LiquidButton variant="primary">
            Interagir
          </LiquidButton>
          <LiquidButton variant="secondary">
            Cancelar
          </LiquidButton>
        </div>
      </LiquidGlassCard>
    </div>
  );
}

🎨 CSS Custom Properties para Personalização

liquid-glass-variables.css
/* 📁 liquid-glass-variables.css */
/* 🎯 CSS Custom Properties para fácil personalização */

:root {
  /* 🌈 Cores do Liquid Glass */
  --liquid-glass-bg: rgba(255, 255, 255, 0.02);
  --liquid-glass-border: rgba(255, 255, 255, 0.1);
  --liquid-glass-reflection: rgba(255, 255, 255, 0.3);
  
  /* 💧 Blur e saturação */
  --liquid-blur-radius: 20px;
  --liquid-saturation: 180%;
  --liquid-brightness: 110%;
  
  /* 📐 Dimensões */
  --liquid-border-radius: 24px;
  --liquid-padding: 2rem;
  --liquid-max-width: 420px;
  
  /* 🎭 Animações */
  --liquid-transition-duration: 0.3s;
  --liquid-hover-scale: 1.02;
  --liquid-shadow-intensity: rgba(0, 0, 0, 0.3);
  
  /* 🎨 Temas de cores */
  --liquid-primary-color: rgba(0, 255, 136, 0.15);
  --liquid-primary-border: rgba(0, 255, 136, 0.3);
  --liquid-primary-text: #00ff88;
  
  --liquid-secondary-color: rgba(255, 255, 255, 0.05);
  --liquid-secondary-border: rgba(255, 255, 255, 0.1);
  --liquid-secondary-text: rgba(255, 255, 255, 0.8);
}

/* 🌙 Dark Theme Override */
[data-theme="dark"] {
  --liquid-glass-bg: rgba(0, 0, 0, 0.4);
  --liquid-glass-border: rgba(255, 255, 255, 0.05);
  --liquid-blur-radius: 25px;
  --liquid-saturation: 150%;
}

/* 🌞 Light Theme Override */
[data-theme="light"] {
  --liquid-glass-bg: rgba(255, 255, 255, 0.7);
  --liquid-glass-border: rgba(0, 0, 0, 0.1);
  --liquid-glass-reflection: rgba(255, 255, 255, 0.8);
  --liquid-shadow-intensity: rgba(0, 0, 0, 0.1);
}

/* 🎨 Color Variants */
.liquid-glass-card {
  background: var(--liquid-glass-bg);
  backdrop-filter: blur(var(--liquid-blur-radius)) 
                   saturate(var(--liquid-saturation)) 
                   brightness(var(--liquid-brightness));
  -webkit-backdrop-filter: blur(var(--liquid-blur-radius)) 
                          saturate(var(--liquid-saturation)) 
                          brightness(var(--liquid-brightness));
  border: 1px solid var(--liquid-glass-border);
  border-radius: var(--liquid-border-radius);
  padding: var(--liquid-padding);
  max-width: var(--liquid-max-width);
  transition: all var(--liquid-transition-duration) ease;
}

/* 🔥 Variantes de cor */
.liquid-glass-card.variant-fire {
  --liquid-glass-bg: rgba(255, 69, 0, 0.1);
  --liquid-glass-border: rgba(255, 69, 0, 0.3);
  --liquid-primary-color: rgba(255, 69, 0, 0.2);
  --liquid-primary-text: #ff4500;
}

.liquid-glass-card.variant-ocean {
  --liquid-glass-bg: rgba(0, 150, 255, 0.1);
  --liquid-glass-border: rgba(0, 150, 255, 0.3);
  --liquid-primary-color: rgba(0, 150, 255, 0.2);
  --liquid-primary-text: #0096ff;
}

.liquid-glass-card.variant-forest {
  --liquid-glass-bg: rgba(34, 139, 34, 0.1);
  --liquid-glass-border: rgba(34, 139, 34, 0.3);
  --liquid-primary-color: rgba(34, 139, 34, 0.2);
  --liquid-primary-text: #228b22;
}

.liquid-glass-card.variant-sunset {
  --liquid-glass-bg: rgba(255, 99, 71, 0.1);
  --liquid-glass-border: rgba(255, 99, 71, 0.3);
  --liquid-primary-color: rgba(255, 99, 71, 0.2);
  --liquid-primary-text: #ff6347;
}

/* 📱 Responsive Variables */
@media (max-width: 768px) {
  :root {
    --liquid-padding: 1.5rem;
    --liquid-border-radius: 20px;
    --liquid-blur-radius: 15px;
    --liquid-max-width: 100%;
  }
}

/* 🎯 Utility Classes */
.liquid-glass-sm {
  --liquid-padding: 1rem;
  --liquid-border-radius: 16px;
  --liquid-blur-radius: 15px;
}

.liquid-glass-lg {
  --liquid-padding: 3rem;
  --liquid-border-radius: 32px;
  --liquid-blur-radius: 30px;
}

.liquid-glass-intense {
  --liquid-saturation: 220%;
  --liquid-brightness: 130%;
  --liquid-blur-radius: 30px;
}

.liquid-glass-subtle {
  --liquid-saturation: 120%;
  --liquid-brightness: 105%;
  --liquid-blur-radius: 10px;
}

/* 🔧 JavaScript Integration */
.liquid-glass-card[data-intensity="low"] {
  --liquid-blur-radius: 10px;
  --liquid-saturation: 120%;
}

.liquid-glass-card[data-intensity="medium"] {
  --liquid-blur-radius: 20px;
  --liquid-saturation: 180%;
}

.liquid-glass-card[data-intensity="high"] {
  --liquid-blur-radius: 35px;
  --liquid-saturation: 250%;
}

/* 🎨 Animation Variables */
.liquid-glass-card {
  --liquid-animation-duration: 0.3s;
  --liquid-animation-easing: cubic-bezier(0.4, 0, 0.2, 1);
}

.liquid-glass-card:hover {
  transform: scale(var(--liquid-hover-scale));
  box-shadow: 0 20px 40px var(--liquid-shadow-intensity);
}

/* 🌊 Liquid Flow Animation */
@keyframes liquidFlow {
  0%, 100% { 
    transform: translate(-25%, -25%) rotate(0deg); 
  }
  33% { 
    transform: translate(-30%, -20%) rotate(120deg); 
  }
  66% { 
    transform: translate(-20%, -30%) rotate(240deg); 
  }
}

/* 💫 Pulse Animation */
@keyframes liquidPulse {
  0%, 100% { 
    opacity: 1; 
    transform: scale(1); 
  }
  50% { 
    opacity: 0.7; 
    transform: scale(1.1); 
  }
}

⚡ Trecho Básico Simplificado

liquid-glass-simple.css
/* 💎 Efeito Liquid Glass - Versão Simples */
.liquid-glass {
    /* 🌊 Background translúcido */
    background: rgba(255, 255, 255, 0.02);
    
    /* ✨ Filtros de vidro líquido */
    backdrop-filter: blur(20px) saturate(180%) brightness(110%);
    -webkit-backdrop-filter: blur(20px) saturate(180%) brightness(110%);
    
    /* 🔲 Borda e forma */
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 24px;
    
    /* 🌟 Sombras e profundidade */
    box-shadow: 
        inset 0 1px 0 rgba(255, 255, 255, 0.1),
        0 20px 40px rgba(0, 0, 0, 0.3);
    
    /* 🎯 Posicionamento e overflow */
    position: relative;
    overflow: hidden;
}

/* 🌈 Reflexo superior */
.liquid-glass::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(
        90deg, 
        transparent, 
        rgba(255, 255, 255, 0.3) 20%, 
        rgba(255, 255, 255, 0.6) 50%, 
        rgba(255, 255, 255, 0.3) 80%, 
        transparent
    );
    border-radius: 24px 24px 0 0;
}

/* 🎭 Exemplo de uso */
.exemplo-uso {
    padding: 2rem;
    max-width: 400px;
    color: white;
    text-align: center;
}

/* 📱 Responsividade básica */
@media (max-width: 768px) {
    .liquid-glass {
        border-radius: 20px;
        backdrop-filter: blur(15px) saturate(150%);
        -webkit-backdrop-filter: blur(15px) saturate(150%);
    }
}

Pronto para aplicar o efeito?

Aprenda a construir o efeito vidro com CSS independente da plataforma