Tag: Design Systems

  • CSS Border Radius Generator: Per-Corner & Blob [2026]

    CSS Border Radius Generator: Per-Corner & Blob [2026]

    TL;DR: A CSS border radius generator builds rounded-corner styles visually — uniform corners, per-corner radii, or organic “blob” shapes via the elliptical syntax. Modern UI uses 8-16px on cards, 6-10px on buttons, 999px (or 50%) for fully rounded pills. Our free generator produces both the 4-value and 8-value (elliptical) syntaxes with live preview.

    Border radius is the design primitive that shifted UIs from sharp corners (1995-2010) to soft corners (2010-now) and is now the difference between “modern” and “dated” interfaces. Get the value right and your card looks polished; get it wrong and it looks like a bootstrap default. Most CSS border-radius generators only show the simple uniform-corner case; the interesting work is per-corner control and the rarely-used elliptical syntax that produces organic blob shapes.

    Our CSS border radius generator handles all three modes — uniform, per-corner, and elliptical — with a live preview and copy-ready CSS. This guide explains the right values for each UI element, the elliptical syntax that produces blob shapes, and the framework-specific shortcuts.

    Standard border-radius values for UI elements

    Element Recommended radius Notes
    Cards 8-16 px Stripe and Linear use 12px; Apple HIG uses 14px
    Buttons 6-10 px Pills (999 px) for marketing CTAs
    Form inputs 4-8 px Match your buttons to keep visual rhythm
    Avatars 50% (perfect circle) Or 999px which works the same on small elements
    Tags / chips 999 px (pill) Modern look; 4 px reads as old-school
    Modals / dialogs 12-20 px Slightly softer than cards for visual hierarchy
    Code blocks 6-10 px Match cards or buttons in your design system

    The “design system rhythm” rule: use 2-3 distinct radius values across your UI, not one per component. A typical system: 6 px (form inputs, small buttons), 12 px (cards, tags-as-rectangles), 999 px (pills, avatars, dots). Inconsistent radii (6/8/10/14 mixed across components) reads as unintentional.

    Per-corner border radius — when uniform won’t do

    /* Uniform — all four corners */
    border-radius: 12px;
    
    /* Per-corner: top-left, top-right, bottom-right, bottom-left */
    border-radius: 12px 12px 0 0;       /* card with attached top */
    border-radius: 0 12px 12px 0;       /* tab attached to left side */
    border-radius: 12px 12px 12px 4px;  /* speech-bubble pointer */

    Per-corner control is essential for tabs, speech bubbles, attached cards, and any element that visually “connects” to another. The 4-value shorthand follows the same clockwise order as padding and margin — top, right, bottom, left.

    Elliptical border radius — the blob shape secret

    The 8-value border-radius syntax produces elliptical corners, which when used asymmetrically across corners creates organic “blob” shapes:

    /* The full syntax: horizontal-radii / vertical-radii */
    border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
    /*              ^---horizontal--^   ^----vertical---^
       tl, tr, br, bl                 tl, tr, br, bl  */

    Each corner gets two radii (horizontal + vertical), making the corner an ellipse rather than a circle. When the values are deliberately asymmetric, the result reads as organic / hand-drawn — useful for hero illustrations, decorative shapes, and modern “blob” backgrounds. Our generator includes a “blob” mode that randomises asymmetric values for instant organic shapes.

    How to use the browser border radius generator

    1. Open the CSS border radius generator
    2. Pick a mode: Uniform (one slider for all four corners), Per-corner (4 sliders), or Blob (8 values, randomisable)
    3. Drag sliders to shape the preview
    4. Toggle preset (Card, Pill, Avatar, Tab-left, Tab-right, Speech bubble, Blob)
    5. Copy CSS or Tailwind utility output

    Tailwind CSS shortcuts

    rounded-none    /* 0 */
    rounded-sm      /* 2px */
    rounded         /* 4px */
    rounded-md      /* 6px */
    rounded-lg      /* 8px */
    rounded-xl      /* 12px */
    rounded-2xl     /* 16px */
    rounded-3xl     /* 24px */
    rounded-full    /* 9999px */
    
    /* Per-corner */
    rounded-t-lg                    /* top-left + top-right */
    rounded-tl-lg                   /* top-left only */
    rounded-tl-2xl rounded-br-2xl   /* mixed corners */

    Common mistakes

    • Same radius on small + large elements. 8 px reads tight on a small button but looks dated on a large card. Scale radius with element size — small (6 px), medium (10-12 px), large (14-16 px).
    • Forgetting that border-radius: 50% only gives a circle on square elements. On a rectangle, 50% produces an ellipse. For pills, use border-radius: 999px.
    • Inheriting from images on overflow. If a child image overflows a parent with rounded corners, set overflow: hidden on the parent or apply the same border-radius to the image directly.
    • Inconsistent radii across the design system. Pick 2-3 standard values and use them everywhere. Random radii read as unintentional.

    Frequently asked questions

    What’s the difference between border-radius and clip-path for rounded shapes?

    border-radius rounds the corners of the element’s box. clip-path can produce arbitrary shapes (polygons, circles, complex paths). For simple rounding, border-radius is faster (GPU-accelerated, fewer paint cycles). For non-rectangular shapes (heart, star, custom polygon), clip-path is the right tool. They can be combined — a rounded element clipped to a custom path.

    Can I animate border-radius?

    Yes — border-radius animates smoothly via CSS transitions and keyframes. Browsers handle this efficiently. Common use: card hover states that morph from rectangle to slightly-rounded as a “lifted” effect.

    Why do my rounded images have sharp corners?

    Two common causes: (1) the parent has rounded corners but doesn’t have overflow: hidden, so the image overflows; (2) you applied border-radius to the parent but not the image directly. Fix: either apply overflow: hidden + border-radius to the parent, or border-radius directly to the image.

    What’s a good radius for a button?

    6-10 px for standard buttons matches modern design systems (Stripe, Linear, Apple HIG). Pills (999 px or rounded-full) for marketing CTAs and tags. The same value across all your buttons in a design system; don’t vary.

    Will the generator output match the preview exactly?

    Yes — the preview and the generated CSS are computed from the same values. Drop the CSS into your stylesheet and you get pixel-identical results.

    Is my data sent anywhere?

    No. The generator runs entirely in your browser. Slider values, preview, and CSS output stay on your device.

    Related tools and guides

     

  • CSS Box Shadow Generator: Multi-Layer Depth [2026]

    CSS Box Shadow Generator: Multi-Layer Depth [2026]

    TL;DR: A CSS box shadow generator builds box-shadow declarations visually — drag offset, blur, spread, and colour sliders to design the shadow, copy the CSS. Modern UI uses multi-layer shadows (2-3 stacked) for realistic depth: a tight close shadow for grounding plus a soft far shadow for ambient. Our free generator handles inset, multi-layer stacks, and exports paste-ready CSS or Tailwind utilities.

    Shadows are the lazy designer’s depth cue. Drop a 4-pixel grey shadow under any card and the card looks “lifted” off the page. Drop the wrong shadow and the card looks like it’s from 2015. The difference between professional and amateur UI in 2026 isn’t whether you use shadows — it’s whether you stack two or three layers to mimic how real light works. A box-shadow generator with multi-layer support is the fastest way to get there.

    Our CSS box shadow generator ships with a live preview, multi-layer support, inset toggle, and export as either vanilla CSS or Tailwind arbitrary-value classes. This guide explains the five box-shadow parameters, why multi-layer shadows look more realistic than single-layer ones, the modern Material Design 3 elevation tokens, and the performance gotchas that make heavy-shadow pages laggy on mobile.

    The five parameters that define a box-shadow

    Parameter Effect Typical range
    Horizontal offset (x) Shadow shifted right (positive) or left (negative) −2 to 2 px (subtle), 0 for centred
    Vertical offset (y) Shadow shifted down (positive) — typical for “lifted” cards 2-30 px depending on elevation
    Blur radius How soft / diffuse the shadow edge is 2× the y-offset for natural softness
    Spread Expands or contracts the shadow before blur. Negative = tight; positive = halo −10 to 5 px typically
    Colour Shadow’s RGBA value rgba(0,0,0,0.04-0.18) for natural shadows

    The single most common mistake: using rgba(0,0,0,0.5) for the shadow colour. Real shadows are far more subtle — 0.04 to 0.18 alpha is the right range. Heavy shadows look like a 2008 web aesthetic. Use multi-layer composition for depth, not a single dark shadow.

    Multi-layer shadows — the modern technique

    Single shadows look flat. Real-world depth has two characteristics: a tight close shadow (the ambient occlusion right next to the object) and a soft far shadow (the diffused fall-off). Modern UI mimics this by stacking 2-3 shadow layers in one box-shadow declaration:

    /* Single shadow (looks flat) */
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    
    /* Two-layer (realistic depth) */
    box-shadow:
      0 1px 2px 0 rgba(10, 37, 64, 0.04),     /* close, tight */
      0 4px 12px -2px rgba(10, 37, 64, 0.08); /* far, soft */
    
    /* Three-layer (premium look — Stripe, Linear, Vercel use this) */
    box-shadow:
      0 1px 1px 0 rgba(10, 37, 64, 0.05),
      0 2px 4px -1px rgba(10, 37, 64, 0.08),
      0 12px 24px -8px rgba(10, 37, 64, 0.12);

    The progression from one to three layers is what separates default-looking buttons from premium-looking buttons. Most modern design systems (Material 3, Apple HIG, Tailwind’s shadow-xl) ship multi-layer shadows out of the box.

    Material Design elevation system — six standard levels

    Material Design’s elevation system maps real-world depth to six numerical levels. Each level uses a specific multi-layer shadow stack tuned for the apparent height. Useful as a starting point for your own design system:

    • Elevation 0: no shadow (flat surfaces, page background)
    • Elevation 1: subtle lift (cards at rest, table rows)
    • Elevation 2: raised (cards on hover, primary buttons)
    • Elevation 3: floating (FABs, contextual menus)
    • Elevation 4: overlaid (dialogs, drawers)
    • Elevation 5: very prominent (modal cover, navigation drawer)

    Pick three or four of these for your design system rather than letting designers invent custom shadows per component. Consistency is what makes a UI look polished.

    How to use the browser box-shadow generator

    1. Open the box shadow generator
    2. Drag the x, y, blur, spread sliders. Watch the live preview update
    3. Adjust the colour picker (alpha matters — keep it subtle)
    4. Toggle inset for inner shadows (useful for pressed-button states or “carved” effects)
    5. Click + Add layer to stack a second or third shadow for realistic depth
    6. Pick a preset (Material elevations 1-5, “Stripe-style” multi-layer, “carved”, “neon glow”)
    7. Copy CSS or Tailwind output

    Performance — when shadows hurt page speed

    Shadows are GPU-rendered, which is fast — but not free. A handful of shadows on hero elements is invisible cost. Hundreds of shadows in a feed-style listing produces visible jank on mid-range mobile devices.

    • Don’t apply heavy multi-layer shadows on 50+ scrolling cards. Use a single subtle shadow per card, save the multi-layer treatment for hero elements.
    • Avoid animating shadows. Animating the box-shadow property forces re-layout on every frame. Animate a wrapper’s transform: scale or translateZ instead, with a static shadow.
    • Inset shadows on text-heavy elements. Inset shadows trigger a different rendering path. Avoid stacking many on form inputs or text areas.
    • Use will-change: box-shadow sparingly. Promotes the element to its own layer, which uses memory. Reserve for elements you’ll definitely animate.

    Common box-shadow mistakes

    • Heavy single shadows. box-shadow: 0 8px 32px rgba(0,0,0,0.4) looks like a 2010 lightbox. Use multi-layer with low alpha for modern depth.
    • Coloured shadows by default. Black or near-black shadows are correct for ~95% of cases. Coloured shadows (matching the element) work for hero/marketing elements but look weird on body content.
    • Wrong blur-to-offset ratio. Blur should be roughly 2× the y-offset for natural softness. 0 4px 4px (1:1) looks tight and harsh; 0 4px 8px (1:2) looks natural; 0 4px 24px (1:6) looks dreamy/soft.
    • No spread on outset shadows. Negative spread tightens the shadow and prevents it bleeding past the element bounds — useful for cards in tight grids.
    • Forgetting dark mode. Black shadows on a dark background are invisible. Use slightly lighter shadows or rely on borders + brightness for depth in dark mode.

    Frequently asked questions

    What’s the difference between box-shadow and drop-shadow?

    box-shadow draws a shadow that follows the element’s bounding box (rectangle, even if the element has rounded corners). filter: drop-shadow() follows the element’s actual visual shape, including transparency in PNG images and SVG paths. For UI cards, box-shadow is correct. For PNG icons or SVG logos, drop-shadow is correct.

    Can I animate box-shadow smoothly?

    Browsers can transition box-shadow but it’s expensive. For smooth hover-state lifts, animate a wrapper’s transform: translateY(-2px) with a static shadow instead. The visual effect is identical but the GPU cost is much lower.

    Why does my shadow look pixelated on retina displays?

    This usually happens when blur is too small relative to retina pixel density. Increase blur to at least 4px (which becomes 8 retina pixels) for smooth edges. Sub-pixel blur is interpreted differently across browsers.

    How many shadow layers should I stack?

    Two for most cases (close + far). Three for hero/premium elements where realistic depth matters. Four+ rarely improves the visual and adds GPU cost. Material Design’s heaviest elevation uses three.

    Will the generator output Tailwind utilities?

    Yes — the tool exports both vanilla CSS and Tailwind arbitrary-value class strings. Tailwind v3 also has built-in shadow utilities (shadow-sm, shadow-md, shadow-lg, shadow-xl, shadow-2xl) that approximate Material elevations 1-5.

    Is the box-shadow data sent anywhere?

    No. The generator runs entirely in your browser — slider values, preview rendering, and the CSS output all stay on your device.

    Related tools and guides

     

  • Color Shades Generator: Build a Tailwind 50-950 Ramp [2026]

    Color Shades Generator: Build a Tailwind 50-950 Ramp [2026]

    TL;DR: A color shades generator turns one base colour into an 11-step ramp — 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 — the same scale Tailwind CSS, Material Design, and most modern design systems use. Our free generator outputs HEX, RGB, HSL, and (modern) OKLCH for every step, with Tailwind config and CSS variable export ready to paste.

    The single most useful primitive in modern UI design is the colour ramp — a series of related shades from one base colour, evenly spaced by perceived lightness. Tailwind ships ~22 of them out of the box (slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose). When you build a custom design system on top of Tailwind — or any token-based design system — you need ramps for your brand colours that match Tailwind’s spacing exactly, so they slot into the same components without rewriting CSS.

    Our color shades generator takes any HEX input and produces an 11-step ramp aligned to the Tailwind 50-950 scale. The output exports as a Tailwind config block, CSS custom properties, or a flat HEX list. This guide explains the math behind perceptually uniform ramps, the reason naive lighten/darken produces bad mid-tones, and the workflows that turn one brand colour into a complete usable palette.

    What does each step on the 50-950 scale represent?

    Step Lightness Typical use
    50 Near-white tint Page backgrounds, subtle alternating-row stripes
    100 Very light tint Hover states for tertiary buttons, light card backgrounds
    200 Light tint Borders, dividers, disabled-state fills
    300 Soft tint Placeholder text on dark backgrounds, secondary borders
    400 Medium-light Secondary text, subtitles, captions
    500 Base / brand Primary buttons, links, brand accents — your starting colour
    600 Slightly darker Button hover states, focus rings
    700 Dark Active button states, secondary headings
    800 Deep Body text on light backgrounds, primary headings
    900 Very deep Dark-mode backgrounds, deepest text
    950 Near-black Maximum-contrast text, dark-mode primary surfaces

    The 11-step scale isn’t arbitrary — it’s perceptually-spaced so each adjacent pair has roughly the same WCAG contrast ratio against a fixed reference. That means you can swap one ramp for another (your brand purple for Tailwind’s indigo, say) and existing components keep working without contrast failures.

    Why naive lighten/darken produces bad ramps

    The intuitive way to build a ramp is “blend my base colour with white for tints, blend with black for shades”. This works for grey but fails for any saturated hue. Mixing pure red with white in RGB produces washed-out pink, not a brighter red. Mixing red with black produces a muddy maroon, not a darker red. The shifts happen because RGB blending traverses the colour cube linearly — but human perception of “lighter” and “darker” doesn’t follow the cube’s diagonal.

    Three approaches, increasing fidelity:

    • HSL lightness adjustment. Convert to HSL, change only the L value. Better than RGB blending — preserves hue. The default approach for most older tools.
    • HCL / OKLCH adjustment. Convert to OKLCH (perceptually uniform colour space), change only the L value. Produces ramps where each step looks like an equal step to your eye, regardless of hue. The modern best practice.
    • Manually-tuned per-hue. What Tailwind does internally — each step in their ramps is hand-adjusted for chroma and hue alongside lightness, so deeply saturated reds and pale yellows both produce balanced ramps. Hard to reproduce automatically; our tool gets close with OKLCH.

    Our generator uses OKLCH interpolation by default, which produces ramps that match Tailwind’s hand-tuned ramps within ~5% perceived lightness at every step. For 99% of design system work, that’s indistinguishable from manual tuning.

    How to use the browser color shades generator

    1. Open the color shades generator
    2. Type or paste your base HEX (e.g., #635BFF) into the input. The 11-step ramp renders instantly
    3. Switch the output format between HEX, RGB, HSL, and OKLCH — the values for every step update live
    4. Click any swatch to copy its HEX value to your clipboard
    5. Click Copy Tailwind config to get a paste-ready block:
      colors: { brand: { 50: '#...', 100: '#...', ... 950: '#...' } }
    6. Or click Copy CSS variables for a custom-property block ready to drop into :root

    Adjust the optional ramp-strength slider for tighter or looser tonal spread. The default produces a Tailwind-aligned ramp; pushing strength higher makes the 50 and 950 steps more extreme.

    Generating ramps in code

    JavaScript / TypeScript (colord library):

    import { colord } from "colord";
    
    function buildRamp(baseHex) {
      const base = colord(baseHex);
      const steps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
      const ramp = {};
      steps.forEach((step, i) => {
        const offset = (i - 5) / 5; // -1 (lightest) to +1 (darkest)
        const c = offset === 0
          ? base
          : offset < 0
            ? base.lighten(Math.abs(offset) * 0.5)
            : base.darken(offset * 0.45);
        ramp[step] = c.toHex();
      });
      return ramp;
    }
    
    console.log(buildRamp("#635BFF"));
    // => { 50: "#f4f3ff", 100: "#e7e5ff", ..., 950: "#1a1849" }

    Python (with the colormath library):

    from colormath.color_objects import sRGBColor, LCHabColor
    from colormath.color_conversions import convert_color
    
    def hex_to_ramp(hex_color):
        base = sRGBColor.new_from_rgb_hex(hex_color)
        lch = convert_color(base, LCHabColor)
        ramp = {}
        for i, step in enumerate([50,100,200,300,400,500,600,700,800,900,950]):
            # Adjust L (lightness) channel; keep C and H constant
            new_l = max(5, min(95, lch.lch_l + (5 - i) * 9))
            new = LCHabColor(new_l, lch.lch_c, lch.lch_h)
            ramp[step] = convert_color(new, sRGBColor).get_rgb_hex()
        return ramp

    Building a multi-colour design system from ramps

    One ramp is a primary brand colour. A complete design system needs at least four ramps:

    • Primary (your brand): the colour everyone associates with your product. Used for CTAs, links, hero accents.
    • Neutral (gray ramp): for body text, borders, surfaces. Most products use Tailwind’s slate or zinc directly.
    • Success (green): for confirmation states, completed actions. Tailwind’s emerald ramp is a sensible default.
    • Danger / error (red): for destructive actions, validation errors. Tailwind’s red works.

    Optional but useful: a warning ramp (yellow/amber), an info ramp (blue), and a “muted” surface ramp distinct from neutral. Most polished design systems land at 6-8 named ramps, with each ramp providing the full 50-950 scale.

    The four mistakes that produce bad ramps

    • Using a base that’s too dark. If your brand HEX is #0A2540 (very dark navy), the lightening process produces washed-out 50-100 steps that all look essentially grey-white. Pick a brand colour around the 500 range (mid-saturation, mid-lightness) for the cleanest ramps.
    • Mixing colour spaces inside one design system. If your primary ramp uses OKLCH and your neutral uses HSL, the perceived spacing between steps differs subtly across colours. Pick one method and apply it to all ramps.
    • Forgetting accessibility at the extremes. The 50 step might fail contrast against pure white; the 900 step might have less than 4.5:1 against another dark colour. Always test the actual contrast ratios in real component contexts.
    • Hard-coding HEX values everywhere instead of variables. Once your ramps are defined, reference them via Tailwind utility classes or CSS custom properties. Hard-coding lets the next designer quietly drift away from the system.

    When NOT to auto-generate a ramp

    • For brand-critical primary colours. If your brand identity is built around a specific shade, hand-tune the entire ramp in OKLCH to match the brand book exactly. Auto-generators are starting points, not final palettes.
    • For greyscale neutrals. Auto-generated grey ramps from a base often produce blue-tinged or warm-tinged greys. Use Tailwind’s pre-tuned slate, gray, zinc, neutral, or stone directly.
    • For accessibility-strict environments. Government, healthcare, education sites need ramps where every step pair passes WCAG AAA contrast. Auto-generated ramps need manual nudging at the extremes.
    • For print colour systems. Print uses CMYK, has different contrast behaviour, and benefits from Pantone-matched ramps designed in print-aware tools.

    Frequently asked questions

    Why does Tailwind use 50-950 instead of 100-1000?

    Tailwind inherited the 50-900 scale from Google Material Design, which originally used 50, 100-900 in 100-step increments. Tailwind v3 added 950 (a near-black step, useful for dark-mode primary surfaces). The scale is convention more than precise math — what matters is consistency across your design system.

    Can I export the ramp directly into my Tailwind config?

    Yes. Click “Copy Tailwind config” in the tool — it produces a paste-ready colors: { brand: {...} } object. Drop it into your tailwind.config.js under theme.extend.colors. The values become available as utilities (bg-brand-500, text-brand-700, etc.) immediately after a build.

    Should I use HEX, RGB, HSL, or OKLCH for my ramp output?

    HEX for compatibility — every system understands it. RGB if you’re integrating with a tool that requires RGB values explicitly. HSL if you’ll be making programmatic tweaks (changing all your ramps’ lightness in tandem). OKLCH if you’re targeting modern browsers exclusively and want the most perceptually-uniform colour math available — supported in Chrome 111+, Safari 16.4+, Firefox 113+.

    How does the tool handle very light or very dark base colours?

    For very light bases (e.g., a pastel yellow), the 50-100 steps clip to near-white because there’s nowhere lighter to go. For very dark bases (deep navy, near-black), the 800-950 steps clip toward solid black. The cleanest ramps come from base colours in the mid-lightness range (HSL L between 40-60). If your brand colour is at an extreme, the tool produces the best ramp possible but it’ll be compressed at one end.

    What’s the difference between tints, shades, and tones?

    Tints are mixes with white (lighter versions of the base). Shades are mixes with black (darker versions). Tones are mixes with gray (less saturated versions). Most “shades generators” produce a combination of all three implicitly via OKLCH lightness adjustment, which traverses both tint and shade directions while preserving saturation.

    Can the generator handle dark-mode ramps?

    Yes — the same ramp works for both light and dark mode. You typically use lower steps (50-200) as backgrounds in light mode, and higher steps (800-950) as backgrounds in dark mode. Switch with CSS @media (prefers-color-scheme: dark) or a class toggle. One ramp, two modes.

    Related tools and guides