Skip to content

Glassmorphism Generator — Java source

Create frosted-glass CSS - backdrop-blur, translucent background, subtle border, and soft shadow - with a copy-ready snippet and live preview.

This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.

// =============================================================================
//  GlassmorphismGenerator.java — CosmoDev polyglot showcase port of the
//  `glassmorphism-generator` tool
//  -----------------------------------------------------------------------------
//  Language : Java (Java 17, standard library only)
//  Source:   ported from src/lib/glassmorphism.ts (the canonical, live
//             TypeScript lib); mirrors
//             src/tool-sources/glassmorphism-generator/{python.py,rust.rs}
//  License  : display source — part of CosmoDev's polyglot tool pages
//             (dev.cosmolabs.org). Shown verbatim alongside the JS/TS/Go/Rust/
//             Python ports and the other language ports.
//  -----------------------------------------------------------------------------
//  Builds a frosted-glass CSS block from blur / opacity / tint / radius /
//  borderOpacity (+ optional saturation). Hex tints (#rgb / #rrggbb) are
//  validated by hand (no regex — stdlib only); opacity is clamped to [0,1];
//  the alpha channel is rounded with Math.floor(x*100 + 0.5)/100 — JS
//  Math.round (half-up) semantics — and numbers render like JS template
//  literals: Double.toString is already the shortest round-tripping decimal,
//  but it keeps a trailing ".0" on whole values, so those go through a long
//  cast instead. The output therefore matches the live TypeScript lib
//  byte-for-byte.
// =============================================================================

package com.cosmolabs.cosmodev;

/** Pure glassmorphism CSS builder — deterministic, no DOM. */
public final class GlassmorphismGenerator {
    private GlassmorphismGenerator() {}

    /** Configuration for one glassmorphism declaration block. */
    public record GlassConfig(
            double blur,
            double opacity,
            String tint,
            double radius,
            double borderOpacity,
            Double saturation) {  // null => 180.0 (lib default)
        public GlassConfig {
            if (tint == null) tint = "#ffffff";
        }
    }

    /** The rendered glassmorphism block plus its full CSS text. */
    public record GlassCss(
            String background,
            String backdropFilter,
            String webkitBackdropFilter,
            String border,
            String borderRadius,
            String boxShadow,
            String fullCss) {}

    /**
     * Render a number like a JS template literal (10.0 -> "10", 0.3 -> "0.3").
     * Double.toString is the shortest round-tripping decimal but keeps ".0"
     * on whole values, so those render through a long instead (safe within
     * ±9.2e18 — far beyond any blur/radius/saturation value).
     */
    private static String fmt(double x) {
        if (x == Math.floor(x) && Double.isFinite(x) && Math.abs(x) < 9.2e18) {
            return Long.toString((long) x);
        }
        return Double.toString(x);
    }

    /** True when every character is an ASCII hex digit (0-9, a-f, A-F). */
    private static boolean isHexRun(String s) {
        if (s.isEmpty()) {
            return false;
        }
        for (int i = 0; i < s.length(); i++) {
            if (Character.digit(s.charAt(i), 16) < 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * Parse a #rgb or #rrggbb hex color into {r, g, b}; null if invalid.
     * A 3-char hex expands each digit (e.g. "abc" -> "aabbcc"), like CSS.
     * Exactly one leading '#' is stripped, matching the lib's /^#/ replace.
     */
    public static int[] hexToRgb(String hex) {
        String h = hex == null ? "" : hex.trim();
        if (h.startsWith("#")) {
            h = h.substring(1);
        }
        if (h.length() == 3 && isHexRun(h)) {
            // "a" -> 0xaa — each digit doubles into a pair, like CSS.
            return new int[] { expand(h.charAt(0)), expand(h.charAt(1)), expand(h.charAt(2)) };
        }
        if (h.length() == 6 && isHexRun(h)) {
            return new int[] {
                Integer.parseInt(h.substring(0, 2), 16),
                Integer.parseInt(h.substring(2, 4), 16),
                Integer.parseInt(h.substring(4, 6), 16)
            };
        }
        return null;
    }

    private static int expand(char c) {
        int d = Character.digit(c, 16);
        return d * 16 + d;
    }

    /**
     * Format rgba(), clamping + 2-decimal-rounding the alpha with JS
     * Math.round (half-up) semantics: floor(x*100 + 0.5)/100.
     */
    public static String rgba(int r, int g, int b, double a) {
        double c = Math.max(0.0, Math.min(1.0, a));
        return "rgba(" + r + ", " + g + ", " + b + ", "
                + fmt(Math.floor(c * 100.0 + 0.5) / 100.0) + ")";
    }

    /** Build the full glassmorphism CSS for a config. */
    public static GlassCss buildGlassmorphism(GlassConfig cfg) {
        double blur = Math.max(0.0, cfg.blur());
        double opacity = Math.max(0.0, Math.min(1.0, cfg.opacity()));
        double radius = Math.max(0.0, cfg.radius());
        double borderOpacity = Math.max(0.0, Math.min(1.0, cfg.borderOpacity()));
        double saturation = cfg.saturation() == null ? 180.0 : cfg.saturation();
        int[] rgb = hexToRgb(cfg.tint());
        int r = rgb == null ? 255 : rgb[0];
        int g = rgb == null ? 255 : rgb[1];
        int b = rgb == null ? 255 : rgb[2];

        String background = rgba(r, g, b, opacity);
        String backdropFilter = "blur(" + fmt(blur) + "px) saturate(" + fmt(saturation) + "%)";
        String border = "1px solid " + rgba(255, 255, 255, borderOpacity);
        String borderRadius = fmt(radius) + "px";
        String boxShadow = "0 8px 32px 0 rgba(31, 38, 135, 0.37)";

        String fullCss = String.join("\n",
                "background: " + background + ";",
                "-webkit-backdrop-filter: " + backdropFilter + ";",
                "backdrop-filter: " + backdropFilter + ";",
                "border-radius: " + borderRadius + ";",
                "border: " + border + ";",
                "box-shadow: " + boxShadow + ";");

        // Both prefixed and unprefixed backdrop-filter carry the same value.
        return new GlassCss(background, backdropFilter, backdropFilter, border,
                borderRadius, boxShadow, fullCss);
    }

    public static void main(String[] args) {
        GlassConfig cfg = new GlassConfig(10.0, 0.3, "#ffffff", 12.0, 0.2, null);
        System.out.println(buildGlassmorphism(cfg).fullCss());
    }
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →