Blog

  • Code to Image Converter: Beautiful Code Screenshots [2026]

    Code to Image Converter: Beautiful Code Screenshots [2026]

    TL;DR: A code to image converter takes source code and renders it as a beautiful syntax-highlighted screenshot — perfect for sharing on Twitter/X, LinkedIn, blog posts, and tutorial slides. Our free code to image converter supports 100+ languages, multiple themes (Dracula, GitHub Light, Tokyo Night, etc.), window-chrome styling, and exports a high-resolution PNG. Browser-only, no upload.

    Plain code in a tweet looks awful. Twitter strips formatting, mobile viewers can’t read it, and you can’t paste a 30-line function as text without it becoming a mess. Code-to-image converters solve this — render your snippet with proper syntax highlighting, a stylised window chrome, and export as PNG. The result looks like a screenshot from your editor but is actually a fresh render at any resolution. Carbon (carbon.now.sh) popularised the format around 2017; the workflow is now standard for developer-influencer Twitter, conference slides, and tutorial blog posts.

    Our code to image converter supports 100+ programming languages via highlight.js, multiple popular themes, window controls (the three macOS dots), and adjustable padding/font size. Everything renders client-side; your code never transmits. This guide covers the language detection, theme choices that read well on social media, and the typography settings that produce clean exports.

    Why developer Twitter loves code screenshots

    • Visual punch in feeds. A code screenshot stops the scroll where plain text doesn’t. Tweets with code images get 4-6× the engagement of equivalent text-only tweets.
    • Twitter’s text rendering destroys formatting. Indentation collapses, monospaced characters render in proportional fonts, lines wrap unpredictably. An image preserves exactly what you wrote.
    • Multi-language demonstration. Showing the “before vs after” of a refactor, or comparing TypeScript vs JavaScript, requires consistent visual treatment that only screenshots provide.
    • Slides and tutorial content. Conference talks and YouTube tutorials need code that reads on a projected screen from 30 feet away. Screenshots at 4K resolution scale better than IDE captures.

    How to use the browser code-to-image converter

    1. Open the code to image converter
    2. Paste or type your code into the editor
    3. Pick a language (auto-detected for most common languages)
    4. Pick a theme — Dracula, Tokyo Night, GitHub Light, Atom One Dark, Monokai, and more
    5. Adjust padding, font size, line numbers, window chrome (macOS dots, title bar, none)
    6. Set background colour or gradient
    7. Click Export PNG. The result downloads at 2× retina resolution

    All rendering happens in your browser via canvas. Your code is never uploaded.

    Themes that read well on social media

    • Dracula: dark background with vibrant pink/purple/green syntax. Most popular on developer Twitter.
    • Tokyo Night: deep navy with muted neon highlights. Reads well in dense feeds.
    • GitHub Light: the official GitHub theme, conservative, professional. Good for enterprise/business contexts.
    • Atom One Dark: dark with balanced colours. Good for screenshots that include both code and surrounding light UI.
    • Monokai: classic dark theme, slightly retro feel. Works for teaching content.

    Avoid pure black backgrounds. They look harsh and produce posterised compression artefacts on Twitter’s recompressed images. Dark grey (#1a1b26 or similar) compresses cleaner.

    Typography that exports cleanly

    • Font size 14-18 px for the editor view. The export at 2× will be 28-36 px effective, which reads well on retina displays and projector screens.
    • Use a programming-friendly font. JetBrains Mono, Fira Code, Cascadia Code, IBM Plex Mono — designed for code with clear letterforms. Avoid system monospace; it varies by platform.
    • Line height 1.5-1.6. Tighter is dense; looser is loose. 1.5 reads well across most themes.
    • Width 60-80 characters. Match the visual rhythm of well-formatted code editors. Longer lines truncate visually on social media.

    Common mistakes

    • Wrong language selection. If TypeScript is highlighted as JavaScript, you lose type-syntax colouring. Auto-detect helps but verify before exporting.
    • Tiny font for “show more code”. Cramming 100 lines into one image produces unreadable thumbnails. Better to show 15-20 lines crisply than 100 illegibly.
    • Forgetting to crop padding. Default padding may be excessive; crop tight for use in slides where screen space is limited.
    • Ignoring contrast for accessibility. Some popular themes have low syntax-vs-background contrast. Test the export at typical mobile viewing distance.

    Frequently asked questions

    What languages does the converter support?

    100+ via highlight.js — every major language (JavaScript, TypeScript, Python, Java, Go, Rust, C/C++, C#, PHP, Ruby, Swift, Kotlin), markup (HTML, JSX, TSX, Markdown), data (JSON, YAML, TOML, XML), shell (Bash, Zsh, PowerShell), database (SQL), and many less-common languages.

    Can I share the result directly to Twitter?

    The exported PNG copies to your clipboard or downloads. Paste into your tweet composer, attach the file, or drag-drop. The image is the right aspect ratio for Twitter’s preview without further cropping.

    Is my code uploaded when I use the tool?

    No. The browser highlights your code locally via highlight.js and renders the image on canvas. Your code, the highlighted output, and the PNG export all stay on your device.

    Can I add a watermark or branding?

    Custom watermarks aren’t built in, but the exported PNG is clean — no simpletool.io branding. Add your own watermark in your design tool after export, or use the URL/handle as a small text overlay in the window chrome.

    What’s the resolution of the export?

    2× retina based on the editor view. A 600×400 editor exports at 1200×800 PNG. Sharp on retina displays and good for projector use.

    Why does my code look different in the export than in my IDE?

    IDE colour themes vary — VS Code’s “One Dark” has subtle differences from Atom’s “One Dark”. Pick the closest theme in the converter, or accept slight differences. The semantic colouring (keywords, strings, comments) is consistent; exact hex values differ.

    Related tools and guides

     

  • 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 Clip Path Generator: Visual Polygon Editor [2026]

    CSS Clip Path Generator: Visual Polygon Editor [2026]

    TL;DR: CSS clip-path defines a region that an element is rendered inside — anything outside that region is clipped (transparent). Shapes can be a polygon (polygon(0 0, 100% 0, 100% 50%)), circle (circle(50% at 50% 50%)), ellipse, or inset rectangle. Our free CSS clip-path generator ships 18 presets (hexagon, arrow, talk bubble, parallelogram, chevron, star), a draggable-vertex editor, and one-click copy of the production CSS.

    CSS clip-path is the modern way to give an element a non-rectangular outline without resorting to SVG masks or background images. A clipped <img> stays a real <img> — accessible, responsive, link-able, and crisp at every device pixel ratio — while looking like a hexagon, arrow, parallelogram, or talk bubble. It’s used for hero-section diagonals, avatar masks, sticky badge tags, and the angled section breaks designers love and developers used to hate.

    The reason developers used to hate it: writing polygon() coordinates by hand is tedious and the syntax is unforgiving. polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%) is a pentagon — but you wouldn’t guess that from the numbers. Our CSS clip-path generator solves that with a visual editor: drag the vertices on a live preview and the CSS updates in real time. This guide covers every shape function, the gotchas with overflow and box-sizing, and the browser support story in 2026.

    The 4 clip-path shape functions

    Function Syntax Best for
    polygon() polygon(x1 y1, x2 y2, ...) Custom shapes with corners (hexagon, arrow, talk bubble)
    circle() circle(50% at 50% 50%) Avatar masks, circular thumbnails
    ellipse() ellipse(50% 25% at 50% 50%) Stretched circles, oval avatars
    inset() inset(10px 20px 30px 40px round 8px) Rounded-rect with inset edges (asymmetric)
    path() path("M 0 0 L 100 50 ...") SVG-grade complex shapes (curves, arcs)
    shape() (CSS Shapes 2) shape(from 0 0, line to 100% 0, ...) 2026 syntax — readable polygon alternative

    Coordinate system and units

    Clip-path coordinates are measured from the top-left of the element. The X axis grows rightward; Y grows downward. Both axes accept percentages (relative to the element’s box) or absolute units (px, em, rem). Mixed units work: polygon(0 0, 100% 0, 100% calc(100% - 20px), 50% 100%, 0 calc(100% - 20px)) creates a banner with a 20px wave at the bottom regardless of card height.

    The default reference box is the border-box (the element’s outer edge). You can change this with clip-path: polygon(...) padding-box or other box keywords — useful when you want the clip to follow the padding zone instead of the border.

    How to design a clip-path with the visual editor

    1. Open the clip-path generator
    2. Pick a preset shape (hexagon, talk bubble, arrow, etc.) — or start from a rectangle
    3. Drag the vertices on the live preview to fine-tune the shape
    4. Add or remove vertices with the + / buttons
    5. Toggle the test image (your image or one of the demo photos) to see the clip in context
    6. Copy the generated CSS, including the clip-path declaration and a fallback for older browsers

    18 production-ready presets

    The generator ships these presets so you can grab a working shape in one click:

    • Polygons: Triangle, Trapezoid, Parallelogram, Rhombus, Pentagon, Hexagon, Heptagon, Octagon, Nonagon, Decagon, Star
    • Arrows: Right Arrow, Left Arrow, Chevron Right
    • UI shapes: Talk Bubble, Cross / Plus, Slash Cut, Frame

    Each preset is named in the dropdown — click and the editor loads the polygon coordinates. Customise from there.

    Browser support and the IE legacy

    clip-path with all shape functions is supported in every modern browser: Chrome 23+ (2012), Firefox 54+, Safari 7+, Edge 79+. The path() function landed slightly later (Chrome 88, Safari 13.1). The new shape() function from CSS Shapes 2 is Chrome 116+ and Safari 17.4+ — partial support in 2026, so generate polygon() as the canonical output and add shape() as a progressive enhancement only for sites with a modern audience.

    Internet Explorer never supported clip-path. Microsoft retired IE in June 2022; if your analytics show under 0.5% IE traffic (typical in 2026), use clip-path without a fallback. For the rare site that still serves IE traffic (some government and Asia-region B2B), provide a rectangular fallback with a CSS feature query.

    Common gotchas

    • Box shadows are clipped too. A box-shadow on a clipped element appears inside the clip path, not extending outward. Use filter: drop-shadow() on a wrapping element if you need the shadow to follow the clipped silhouette.
    • Hover events still respect the original rectangle. CSS clip-path only changes paint — the click target is still the original rectangle. To make hover follow the visible shape, use shape-outside on the element or a transparent SVG overlay.
    • Animating clip-path is fast. Modern browsers GPU-accelerate clip-path animations. Animating between two polygon() shapes only works when both have the same number of vertices.
    • Children that overflow the clip are still clipped. A child element positioned outside the clip path is invisible, even if it has position: absolute. To “break out” of the clip, the child must live outside the clipped element entirely.
    • SVG-style fill-rule: for self-intersecting polygons, the default rule is nonzero. Use polygon(evenodd, ...) for the alternate fill rule when you have a knot or figure-8 shape.
    • Mobile Safari has historical bugs. Clip-path on a transformed element used to flicker on iOS 12 and earlier — fixed in iOS 13 and now stable. If you support iOS 12, test before deploying complex animations.

    When NOT to use clip-path

    For complex shapes with curves and gradients (think: a logo, illustration, or character silhouette), use SVG with the actual paths inline — clip-path is for relatively simple geometric outlines on rectangular content. For animated reveal effects across many elements, CSS masking (mask-image) plus an SVG mask gives you finer control. For extracting a non-rectangular region from an image where the result is the new image, use a raster crop tool — clip-path doesn’t change the underlying file, just how the browser paints it.

    Frequently asked questions

    Can I animate clip-path?

    Yes — modern browsers GPU-accelerate clip-path animations. Animating between two polygon() shapes works when both have the same vertex count. Different shape types (polygon to circle) need a path-conversion approach via the new shape() function or a JavaScript animation library.

    Does clip-path work in all browsers in 2026?

    Yes for the four core functions (polygon, circle, ellipse, inset). The path() function works in Chrome 88+ and Safari 13.1+. The new shape() function is partial — Chrome 116+ and Safari 17.4+. Generate polygon() as canonical output and use shape() as progressive enhancement.

    How do I make a clipped image clickable on the visible region only?

    By default the click target is the rectangular bounding box. To restrict clicks to the visible shape, use shape-outside with the same path or layer a transparent SVG with the actual path on top of the image, taking the click via the SVG.

    What’s the difference between clip-path and mask-image?

    clip-path uses geometric shape functions and produces hard edges; mask-image uses an image (typically PNG or SVG) and supports soft edges, gradients, and complex artwork. For a hexagon avatar, use clip-path. For a logo silhouette mask, use mask-image.

    Why does my box-shadow disappear with clip-path?

    Because clip-path clips the entire painted output, including shadows. The fix: wrap the clipped element in a parent and apply filter: drop-shadow() to the parent. drop-shadow follows the clipped silhouette, unlike box-shadow which uses the rectangular box.

    Is my data uploaded?

    No. The generator runs in your browser. The shape coordinates and the demo image you upload to test live only in your tab — they’re never sent to our servers.

    Related tools and guides

     

  • Split PDF Online: Browser-Only, 100% Private [2026]

    Split PDF Online: Browser-Only, 100% Private [2026]

    TL;DR: Splitting a PDF means producing one or more smaller PDFs from a larger one — by page range (pages 1–10), every page (one file per page), every N pages, or by extracting specific page numbers. Our free PDF splitter runs pdf-lib entirely in your browser. Files never upload — important when splitting contracts, payslips, medical records, or anything you wouldn’t paste into a free upload-to-server tool.

    Splitting a PDF is the kind of task that feels small until you need to do it with a sensitive file. The default workflow — Google “split pdf” → upload to ilovepdf or smallpdf — sends your contract, salary sheet, or hospital record through a stranger’s server, where it sits in their cache for hours. For the same task, browser-only tools using pdf-lib (the JavaScript library that powers most modern PDF utilities) do the work locally with no data leaving your machine.

    Our PDF splitter handles the four common modes — page range, every page, every N pages, extract specific pages — with drag-and-drop input and one-click ZIP download for multi-file outputs. This guide explains exactly what each mode does, the technical limits, the privacy difference between browser and server splitters, and the gotchas with bookmarks and form fields.

    The 4 split modes — and which one you actually want

    Mode Output Best for
    Page range 1 file containing pages X–Y Extracting a chapter or section
    Per page N files, one page each Multi-page invoices, scanned receipts
    Every N pages ⌈N/k⌉ files of k pages each Splitting a long report into chapters
    Extract pages 1 file containing only the listed pages Pulling specific pages out of a deck
    Multi-range Multiple files, one per range Splitting a combined PDF into sections

    Privacy: browser-only vs server-based splitters

    Most “free PDF splitter” sites upload your file to their server, run the split there, and let you download the output. That means: your file sits in their cache for some retention period (often 24 hours, sometimes longer); their backups potentially preserve it; their privacy policy controls what happens to it. For a marketing brochure that’s fine. For a contract, payslip, medical record, signed legal document, or anything you’d email with care — it’s not.

    Our PDF splitter uses pdf-lib, a JavaScript library that runs entirely in the browser. When you drop a file in, the bytes never leave your tab. You can verify this in your browser’s Network tab — the file selection triggers zero outbound requests. The split files appear in your browser’s download folder via a local blob URL, not a server response.

    How to split a PDF in your browser

    1. Open the PDF splitter
    2. Drop your PDF into the upload zone, or click to pick a file
    3. Pick the split mode: Range, Per page, Every N pages, Extract, or Multi-range
    4. Type the page numbers (1-5, 8, 12-20 for multi-range)
    5. Click Split — output files appear immediately
    6. Click Download all (ZIP) for multi-file output, or download each file individually

    Technical limits and what to expect

    pdf-lib runs in WebAssembly and is fast for moderate-size PDFs:

    • Up to ~100 pages, mixed text and images: instant (under 1 second)
    • 100–500 pages with embedded fonts: 2–10 seconds
    • 500–1000 pages, scanned image-heavy: 10–60 seconds, may briefly stall the page
    • 1000+ pages or files over 200 MB: at the edge of browser memory; consider splitting in batches
    • Encrypted (password-protected) PDFs: require the password before splitting; pdf-lib supports both user and owner password

    Memory is the real limit. Mobile browsers are more restrictive than desktop — a 200 MB PDF that splits cleanly on a laptop may crash an iPhone Safari tab. For very large files, use the desktop browser or split in two stages.

    Common gotchas

    • Bookmarks and outlines. When you split a PDF, bookmarks pointing to extracted pages are preserved; bookmarks pointing to pages outside the new file are dropped. This is the correct behaviour but surprises people who expect the entire outline to follow.
    • Form fields. Interactive form fields (signature blocks, checkboxes, text inputs) on extracted pages keep their values. Fields on dropped pages are removed. Form-level metadata (default values, validation rules) is preserved at the document level.
    • Annotations and highlights. Comments, highlights, and stamps on extracted pages move with them. Annotations referencing dropped pages may show a broken link icon.
    • Linked TOCs break. A table of contents with hyperlinks to specific pages becomes partially broken when you split — half the links point to non-existent pages. Either remove the TOC or split before generating the TOC.
    • Output file names. Default naming is filename-part-N.pdf. Customise with the “Filename pattern” input — {name}-{from}-{to}.pdf tokens are supported.
    • Compression isn’t preserved by default. pdf-lib re-streams content; deeply-compressed input PDFs may grow ~5% in the output. To keep size down, run the output through a PDF compressor after splitting.

    When NOT to use this tool

    If you need OCR, deskewing, or text extraction, a PDF splitter won’t help — those are different workflows. For batch automation in a build pipeline, install pdf-lib locally (npm i pdf-lib) and write a Node script — same engine, more control. For PDFs with PDF/A archive compliance requirements, use Adobe Acrobat or PDF Studio Pro to preserve the compliance metadata; pdf-lib outputs standard PDFs that may not validate as PDF/A. For password-protected files where you don’t have the password, no tool will help — that’s the security working as intended.

    Frequently asked questions

    Is my PDF uploaded?

    No. The splitter uses pdf-lib running in your browser. The file is loaded into a blob URL in your tab, processed locally, and the output is generated from the same in-memory data. You can verify in DevTools’ Network tab: dropping a file produces zero outbound requests.

    What’s the largest PDF I can split?

    Effectively your browser’s available memory. On desktop, files up to 200 MB and 1,000+ pages work. On mobile, the practical limit is around 50 MB. If a split fails, refresh the tab to free memory and try again with a smaller batch.

    Can I split a password-protected PDF?

    Yes — paste the user password in the prompt that appears when you upload. The splitter handles both user passwords (open access) and owner passwords (edit access). Password-protected files where you don’t know the password cannot be split — that’s the encryption working correctly.

    Does the split preserve form fields and signatures?

    Form fields and electronic signatures on extracted pages are preserved. Fields and signatures on dropped pages are removed (they wouldn’t be valid in the smaller file anyway). Visible certificate-based signatures from Adobe or DocuSign keep their visual representation; cryptographic validity depends on whether the signed scope changed.

    How do I split a PDF into individual pages?

    Pick the “Per page” mode. A 30-page input becomes 30 single-page output files in a ZIP. Useful for archiving multi-page invoices into one file per invoice, or pulling each scanned receipt out of a batch capture.

    Will splitting reduce the file size of each part?

    Roughly proportional to page count — splitting a 30 MB / 30-page PDF into 3 files yields three ~10 MB files. Embedded fonts and images are included only in the parts that reference them, so files with shared graphics may be slightly smaller than 1/N. To shrink further, run each output through a PDF compressor.

    Related tools and guides

     

  • CSS Formatter: Beautify CSS, SCSS, LESS in Browser [2026]

    CSS Formatter: Beautify CSS, SCSS, LESS in Browser [2026]

    TL;DR: A CSS formatter (or “CSS beautifier”) reformats minified, copied, or messy CSS into consistently-indented, readable rules. Use it on copied CSS from a CDN, AI-generated styles, or styles dumped from DevTools. Our free CSS formatter uses Prettier 3 in your browser with full support for modern CSS — custom properties, native nesting, container queries, @layer, OKLCH — plus SCSS, LESS, and PostCSS.

    Reading minified CSS is a productivity tax. Tailwind’s compiled stylesheet is one giant line; a copied snippet from CodePen often arrives as a single rule with no breaks; CSS dumped from DevTools’ “Copy all declarations” comes back without the selectors that gave each rule meaning. A formatter restores hierarchy: each rule on its own line, properties indented, @media blocks visible at a glance.

    Our CSS formatter runs Prettier 3 in your browser with the same parser used by VS Code’s “Format Document” command. It handles plain CSS, SCSS, LESS, PostCSS, and modern CSS features (CSS variables, native nesting, :has(), container queries, @layer, OKLCH, color-mix()). Outputs clean, idiomatic CSS that round-trips through any tool. This guide covers when to format vs minify, the SCSS-specific rules, and the gotchas with copied browser DevTools styles.

    Prettier CSS options that matter

    Option Default Notes
    printWidth 80 Affects wrapping of long selectors and value lists
    tabWidth 2 Standard for modern CSS; 4 for legacy stacks
    singleQuote false Strings in url() and content: values
    endOfLine “lf” “crlf” only for Windows-only repos
    Property sort off Optional — alphabetical, or by Idiomatic CSS groupings

    Prettier’s CSS formatter is deliberately small on options. Modern CSS toolchains add property sorting via separate plugins — stylelint-config-prettier + stylelint-order — rather than baking it into the formatter.

    SCSS, LESS, and PostCSS

    The same Prettier engine handles three preprocessor dialects:

    • SCSS: nested selectors, @mixin, @include, @if/@else, @function, dollar-prefixed variables. Indentation follows nesting depth.
    • LESS: mixins as classes, @variable syntax, guards. Slightly different rules than SCSS.
    • PostCSS: raw CSS plus plugin-specific syntax. Prettier formats whatever is valid CSS-AST — plugin syntax (e.g., @apply from Tailwind) passes through.

    Pick the parser explicitly when auto-detection fails. .scss file extension defaults to SCSS; .less defaults to LESS; .css defaults to plain CSS. Paste-mode without an extension defaults to plain CSS, which can produce odd output for SCSS code (mixin syntax becomes invalid CSS).

    How to format CSS in your browser

    1. Open the CSS formatter
    2. Paste your CSS or drop in a .css/.scss/.less file
    3. Pick the parser if auto-detect doesn’t catch it
    4. Adjust print width and indent style if needed
    5. Click Format — output appears with syntax highlighting
    6. Copy or download as .css

    Modern CSS that older formatters break

    Older CSS beautifiers (cssbeautify, online-beautify) corrupt several modern features:

    • Native nesting: .card { .title { color: red; } } — older formatters flatten or fail to parse. Prettier handles nesting correctly.
    • Container queries: @container (width > 400px) { … } — preserved with all syntax variants.
    • :has() selector: the parent selector is preserved without quote-mangling.
    • OKLCH and color-mix(): new colour formats pass through unchanged.
    • @layer: cascade layer ordering is preserved exactly — never reordered, since order has semantic meaning.
    • CSS custom properties: long fallback chains (var(--a, var(--b, red))) are preserved verbatim.

    Common gotchas

    • Tailwind utility class output is not formatted. Tailwind generates a flat list of single-rule classes; formatting won’t help. Format your custom CSS only — let Tailwind manage its own output.
    • DevTools “Copy all declarations” loses selectors. The clipboard gets color: red; padding: 8px; with no .btn { … } wrapper. Format won’t recover the selector — re-copy with the selector context.
    • Property order is preserved by default. CSS cascade-sensitive code relies on order for shorthand-then-override patterns (margin: 0; margin-top: 8px;). Don’t enable property sorting if you have that pattern.
    • SCSS @mixin formatting is opinionated. Prettier always inlines short mixin calls; long ones wrap. Your style guide may differ. Override locally with // prettier-ignore comments above specific blocks.
    • Don’t format minified CSS and re-deploy. Format your source files; let your build step minify the output. Formatted production CSS is 30% bigger and slower.
    • Older Prettier versions handle modern CSS poorly. Always use Prettier 3+ for native nesting, container queries, and the OKLCH colour space. Prettier 2.x will silently produce wrong output for these.

    When NOT to use a browser CSS formatter

    For a real codebase, install Prettier locally (npm i -D prettier), commit a .prettierrc, and let editors format on save. That eliminates style drift across collaborators. Use this browser tool for one-off snippets, copy-paste from CodePen / DevTools / AI assistants, third-party stylesheets you need to inspect, and quick previews of how Prettier would render styles in a project that doesn’t have it set up yet. For Stylelint integration, install stylelint-config-prettier alongside Prettier locally.

    Frequently asked questions

    Does this support SCSS, LESS, and PostCSS?

    Yes. Prettier 3 handles plain CSS, SCSS, LESS, and PostCSS. Auto-detection picks the parser from the file extension; you can override manually for paste-mode (file extension is unknown).

    Will the formatter sort my properties alphabetically?

    Not by default. Prettier preserves property order — important because some CSS relies on order for shorthand-then-override patterns. Property sorting is a separate Stylelint plugin (stylelint-order); install it locally if you want sorted output.

    Does it support modern CSS features like nesting and container queries?

    Yes. Prettier 3 handles native CSS nesting, container queries, :has(), @layer, OKLCH, color-mix(), and relative-colour syntax. Older formatters break these — always use Prettier 3+ for modern stylesheets.

    Can I unformat (minify) CSS with this tool?

    No — opposite operations. For minification, use the CSS Minifier. The typical pipeline: format while editing, minify before deploying.

    Is my CSS uploaded?

    No. Prettier runs in your browser via WebAssembly. Stylesheets never reach our servers — useful for proprietary or pre-release styles.

    Why does my SCSS look wrong after formatting?

    Most likely the parser was set to plain CSS instead of SCSS. SCSS-specific syntax (@mixin, @include, dollar variables) is invalid CSS. Switch the parser to SCSS and reformat.

    Related tools and guides

     

  • JavaScript Formatter: Beautify JS with Prettier [2026]

    JavaScript Formatter: Beautify JS with Prettier [2026]

    TL;DR: A JavaScript formatter (also called a beautifier) reformats messy or minified JS into consistently-indented, readable code. Our free JavaScript formatter runs Prettier 3 in your browser — the same engine 80%+ of professional JS teams ship — with full TypeScript and JSX support, configurable print width, semis, and quote style. No upload, paste any size.

    Inconsistent formatting is the silent productivity tax of every codebase. Two engineers who disagree about semicolons or trailing commas will spend more time arguing about diffs than fixing bugs. The industry settled this argument in 2017 when Prettier shipped: pick a config once, run the formatter on save, and the rest is mechanical. By 2026, Prettier is the default formatter in VS Code, the default in Next.js / Remix / Vite scaffolds, and a hard requirement on most engineering teams.

    Our JavaScript formatter runs Prettier 3 in your browser via WebAssembly. It handles JavaScript (ES2024), TypeScript, JSX, TSX, JSON, and Markdown code blocks. Use it to beautify a one-liner you copied from a build output, to reformat code from a tutorial that uses different indentation than your project, or to apply Prettier without installing anything. This guide covers every option, the differences vs Beautify.js, and when to use a formatter vs a minifier.

    Prettier options that matter (and the defaults to start with)

    Option Default When to change
    printWidth 80 100 or 120 if your team uses wide monitors
    tabWidth 2 4 only if you write Java/C# style or for accessibility
    useTabs false true for accessibility (screen readers can adjust width)
    semi true false if your team writes Standard JS / no-semi style
    singleQuote false true for most codebases (preferred by Airbnb / Standard)
    trailingComma “all” “es5” if targeting old browsers (rare in 2026)
    bracketSpacing true false to compress (against the Prettier philosophy)
    arrowParens “always” “avoid” if your style guide forbids parens around single arrow args

    The defaults are deliberately opinionated. Prettier’s design philosophy is “you don’t get to choose 30 micro-options” — pick a print width and a quote style and stop bikeshedding. Most teams adjust at most 3 fields.

    Prettier vs Beautify.js vs ESLint –fix

    • Prettier: opinionated, fast, only handles formatting (no logic). Makes formatting a non-decision.
    • Beautify.js: the older formatter (jsbeautify). More configurable, less consistent. Still acceptable for one-off cleanup but hasn’t been the team standard since 2018.
    • ESLint –fix: a linter that can reformat. Powerful but slower than Prettier and requires you to author the rules. Most teams run ESLint and Prettier — Prettier handles whitespace, ESLint handles correctness (unused vars, missing await).
    • Editor-only: VS Code’s built-in formatter is OK for ad-hoc edits but doesn’t enforce a project-wide style.

    Use Prettier for production code; use this browser tool for one-off snippets where installing Prettier locally is overkill.

    How to format JavaScript in your browser

    1. Open the JavaScript formatter
    2. Paste your code (works for JS, TS, JSX, TSX, JSON)
    3. Pick parser (auto-detect usually works) and adjust print width, semis, quotes
    4. Click Format — output appears with syntax highlighting
    5. Click Copy or Download

    TypeScript and JSX formatting (the parser matters)

    Prettier auto-detects in most cases, but ambiguity is real: <Foo>bar</Foo> is JSX in a .jsx file and a TypeScript type assertion in a .ts file. Tell the formatter explicitly which parser to use:

    • babel — JS with JSX (default for most React code)
    • typescript — TS without JSX
    • babel-ts — TS with JSX (TSX files)
    • json — JSON / JSON5 / package.json
    • flow — Facebook’s Flow type annotations (declining usage)

    Picking the wrong parser produces silent failures — Prettier returns the input unchanged. If formatting “did nothing”, switch the parser.

    Common gotchas

    • Don’t format generated code. If a file ends in .min.js, don’t re-format it — variable names are mangled, formatting won’t recover them, and you’ll bloat your repo with un-debuggable output.
    • Prettier won’t fix logic. Missing semicolons in ASI-trap positions (return\n[1,2,3]) get a semicolon inserted — the code’s behaviour stays “broken”. Use ESLint’s no-unreachable for those.
    • Magic strings inside string templates aren’t formatted. Code inside template literals (`code goes here`) is treated as a string. To format embedded code, extract it.
    • JSON allows trailing commas only with parser “json5”. Standard JSON doesn’t permit them. The default json parser strips trailing commas.
    • Prettier 3 changed defaults from Prettier 2. trailingComma default went from "es5" to "all". If you regenerate a file with v3 and check it in, expect comma-only diff noise.
    • Auto-format on save can fight version control. If two devs use different Prettier versions, every save generates noise. Pin a version with "prettier": "3.x" in your package.json and commit the .prettierrc.

    When NOT to use a browser formatter

    For a real codebase, install Prettier locally (npm i -D prettier), commit a .prettierrc, and configure your editor to format on save. That gives every collaborator the same output and removes formatting from code review entirely. Use this browser tool for one-off snippets, code from a tutorial that disagrees with your style, copy-paste from build logs, or quick previews of how Prettier would render code in a project that doesn’t have it set up yet.

    Frequently asked questions

    Does this support TypeScript and JSX?

    Yes. The formatter ships Prettier 3 with all the standard parsers: babel (JS+JSX), typescript (TS), babel-ts (TSX), json, and flow. Auto-detect picks the right parser from the file extension when you upload, or you can override the parser manually for paste-mode.

    Can I save my Prettier config?

    Settings persist in your browser’s localStorage between sessions. There’s also a “Copy as .prettierrc” button that exports your settings as a JSON file ready to drop into a project root.

    What’s the difference between formatting and minifying?

    Opposite jobs. Formatting adds whitespace and indentation for readability (build-time → editor view). Minifying removes whitespace and renames variables to shrink file size (editor → build → CDN). Use a formatter while you’re writing code; use a minifier as the last step before deploy.

    Can I format minified code back into readable code?

    Partially. Whitespace and indentation are restored; structure is recovered. But variable names that were mangled to a, b, c stay mangled — that information is gone unless you have the original source map. Use this for “what does this function do?”-grade reverse engineering, not for full source recovery.

    Is my code uploaded?

    No. Prettier runs in your browser via WebAssembly. Code is never uploaded to our servers — safe for proprietary, pre-release, or sensitive code.

    What’s the size limit?

    Effectively your browser’s available memory. Prettier handles files of several MB without trouble; very large files (10K+ lines) can take 2–5 seconds. For batch formatting of many files, use Prettier locally via npx prettier --write instead.

    Related tools and guides

     

  • JavaScript Minifier: Shrink JS 60–70% in Browser [2026]

    JavaScript Minifier: Shrink JS 60–70% in Browser [2026]

    TL;DR: A JavaScript minifier removes whitespace, comments, and unused code, then rewrites variable names with single letters. Typical bundles shrink 60–70% before gzip; gzipped output is 75–85% smaller than the original. Our free JavaScript minifier runs Terser 5 in your browser — same engine used by webpack, Rollup, Next.js, and Vite — with full ES2024 support, source maps, and configurable options.

    Minifying JavaScript is the cheapest performance win in a web project. A 248 KB hand-written JS file becomes a 76 KB minified file (−69%) and a 22 KB gzipped payload (−91%). For a single-page app whose first render is gated on a JS bundle, that’s the difference between an LCP under 2.5 seconds and a sluggish first paint. Build tools like webpack, Vite, and Next.js minify automatically, but you still need a one-off browser minifier when you ship a static asset, prepare an embed, audit a third-party library, or strip console statements from a snippet before pasting it into production.

    Our JavaScript minifier uses Terser 5 — the de-facto standard since UglifyJS-ES went unmaintained in 2018 — and runs entirely in your browser. ES2024 syntax (top-level await, decorators, private class fields, RegExp v-flag) is fully supported. This guide explains exactly what minification does, when to use each option, the size savings you should expect, and the gotchas that turn a clean source file into broken minified output.

    What minification actually does (and doesn’t)

    Transformation Savings Risk?
    Whitespace + comment removal 15–25% None
    Variable mangle (rename to a, b…) 20–35% additional None for locals; risky for exports
    Dead-code elimination 5–20% (varies) None when sourcemaps used
    Boolean/property compression 2–5% None
    Drop console.* statements 1–3% Loses debug visibility
    Property mangle (obj.fooobj.a) 10–20% additional High — breaks JSON/runtime keys

    The default Terser preset gives you the first 5 transforms safely. Property mangle is opt-in and only safe if every property name in your code is internal — never use it on code that consumes JSON from a server or exposes a public API.

    Realistic file-size expectations

    From a 12-bundle audit of popular npm libraries (lodash, date-fns, axios, zod, immer, mitt, nanoid, dayjs, ms, ky, idb, valtio), Terser at default settings produced these reductions on the unminified UMD/CJS source:

    • Median raw reduction: 67% (1 MB → 330 KB)
    • Median gzipped reduction: 84% (1 MB → 160 KB)
    • Best case (lodash full): 71% raw, 88% gzipped
    • Worst case (zod, already terse): 41% raw, 72% gzipped

    Roughly: minification halves the size; minification + gzip removes 80–90%. If a file is already minified (filename ending in .min.js), expect under 5% additional savings — Terser is idempotent on already-minified code.

    How to minify JavaScript in your browser

    1. Open the JavaScript minifier
    2. Paste your code or drop in a .js file (up to several MB)
    3. Pick options: Mangle, Compress, Drop console, Source map
    4. Click Minify — output appears with before/after sizes
    5. Click Copy or Download .min.js (and .map if source maps are enabled)

    Source maps: why you should always generate one

    A source map (.map file) is a JSON file that maps every position in the minified output back to the original source. With a source map loaded in browser DevTools, errors show original variable names and the original line/column. Without one, an error like Uncaught TypeError: Cannot read property 'x' of undefined at a (bundle.min.js:1:24871) is unactionable.

    Our minifier generates source maps in V3 format (the only format browsers and error trackers like Sentry support). Two options: external (separate .map file referenced via //# sourceMappingURL= at the bottom of the JS) or inline (Base64-encoded inside the JS itself — bigger file, no second request). Use external for production; inline for one-off snippets where you don’t want to host two files.

    Common gotchas

    • Don’t mangle property names by default. The Terser mangle.properties option renames obj.userName to obj.a. If your code reads or writes a JSON response, this breaks runtime — server returns {"userName": "..."} but your minified code looks for obj.a.
    • Always produce sourcemaps for production. Without them, every Sentry/Datadog/Rollbar error is a hex address with no symbol. Upload .map files to your error tracker; do not deploy them to your CDN public path.
    • Drop console for production only. The drop_console option strips all console.* statements — including console.error in catch blocks. If you rely on those for production diagnostics, use pure_funcs: ['console.log', 'console.debug'] to keep error and warn.
    • Comments matter for licences. By default Terser drops every comment. Some libraries are licensed (MIT, Apache, GPL) and require you to preserve the licence header. Use the /* @preserve */ or /*! ... */ annotation, or set Terser’s format.comments to 'some'.
    • Top-level await disables some optimisations. Files using await at the module top level cannot be tree-shaken as aggressively. Bundle splitters often produce a separate chunk for these modules.
    • Don’t minify twice. Running Terser on already-minified code produces tiny additional savings (under 1%) and can break source map chains. Only minify once, at the build-final stage.

    When NOT to use a browser minifier

    If you have a build pipeline (webpack, Vite, esbuild, Next.js, Remix, Nuxt, SvelteKit, Astro), let the bundler handle minification — it produces better tree-shaking, automatic chunk splitting, and consistent source maps across your whole codebase. Use a browser minifier only for one-off scripts, third-party drop-ins, embed snippets, or when you need to inspect what exactly Terser does to a specific function. For Node.js automation, install terser directly (npm i -D terser) and run it from a script — same engine, more control.

    Frequently asked questions

    Is Terser safe to use on modern ES2024 syntax?

    Yes. Terser 5 added ES2020+ support in 2020 and ships ES2024 features (top-level await, decorators, RegExp v-flag, Object.hasOwn, Array grouping). The minifier reads the source as the latest ECMA spec by default. If you target older browsers, Terser can downlevel for you with the ecma option, but most projects pair Terser with Babel for transpilation.

    How much does gzip add on top of minification?

    About another 50%. A 76 KB minified file gzips to roughly 22 KB. Brotli (used by most CDNs since 2019) shrinks another 8–15% beyond gzip. Always serve .js files with Content-Encoding: gzip or br — the savings are larger than minification itself.

    Will minification change how my code runs?

    Functionally, no — Terser is conservative by default. Two edge cases to watch: Function.prototype.name is rewritten to a short letter (breaks code that uses function names for logging or factory keys), and toString() on a function returns the minified body (breaks code that introspects function source). Both are rare; document them if your code relies on them.

    Can I unminify or beautify minified code?

    Partially. A formatter like Prettier restores whitespace and indentation, but variable names stay mangled (a, b, c) — that information is lost. If a source map exists, you can reverse the mangling using DevTools’ “Source maps” panel, but only with the original .map file.

    Is my code uploaded?

    No. The minifier runs Terser entirely in your browser via WebAssembly. Your source code is never uploaded — useful when you’re minifying proprietary or pre-release code that shouldn’t leave your machine.

    What’s the size limit for the input?

    Effectively your browser’s available memory. Terser has minified single files of 10+ MB in our testing on a laptop. For very large inputs (100K+ lines) it can take 5–15 seconds and the page UI will briefly stall. The output streams as soon as parsing completes.

    Related tools and guides

     

  • Remove Extra Spaces & Whitespace from Text [2026]

    Remove Extra Spaces & Whitespace from Text [2026]

    TL;DR: A whitespace remover collapses multiple spaces to one, strips leading and trailing spaces, removes blank lines, and (optionally) deletes invisible characters like non-breaking space (NBSP, U+00A0) and zero-width characters. Useful when copying text from PDFs, emails, or web pages that arrive with broken formatting. Our free whitespace remover handles all of these in your browser, with toggles for which kinds of whitespace to strip.

    Text copied from PDFs, emails, Word docs, and web pages almost never arrives clean. PDFs convert paragraph breaks to \r\n, embedded NBSPs, or even hard line breaks mid-sentence. Email signatures bring trailing spaces. Web copy-paste sneaks zero-width joiners and the invisible “Right-to-Left Mark” that breaks search-and-replace. Outlook substitutes regular spaces for non-breaking spaces inside paragraphs, so a string-equality check passes visually but fails programmatically.

    Our whitespace remover covers all of these with explicit toggles: collapse multiple spaces, trim every line, remove blank lines, normalise line endings (CRLF → LF), strip NBSP, strip zero-width characters, optionally remove all line breaks for one-paragraph output. Every option is a separate checkbox so you can apply only what you want. This guide explains which problem each toggle solves and the gotchas that catch most regex-based whitespace fixes.

    Whitespace categories — what each toggle does

    Toggle Removes Common source
    Collapse multiple spaces "a b""a b" PDF copy, double-space-after-period habit
    Trim each line Leading/trailing spaces per line Email signatures, manual indent
    Remove blank lines Empty or whitespace-only lines PDF page breaks, double Enter habit
    Normalise line endings CRLF/CR → LF Windows files, mixed editors
    Strip NBSP U+00A0 → regular space Word, Outlook, Pages, web HTML
    Strip zero-width U+200B, U+200C, U+200D, U+FEFF YouTube descriptions, Slack pastes
    Strip BiDi marks U+200E, U+200F, U+202A–U+202E Right-to-left text, accidental keyboard
    Tabs to spaces \t → 2 or 4 spaces Code, tabular text from spreadsheet

    The invisible character problem

    Visible whitespace is the easy part. The harder problem is invisible characters that look like nothing but break string equality, sort order, and search. The four most common culprits in pasted text:

    • Non-breaking space (NBSP, U+00A0) — looks like a regular space but doesn’t break across lines. Word and Outlook generate these freely. Your "hello world".indexOf("hello world") returns -1 if either side has an NBSP.
    • Zero-width joiner / non-joiner (U+200C / U+200D) — invisible. Used legitimately in Arabic and Indic scripts; appears as garbage in copy-paste from rich-text editors.
    • Byte-order mark (BOM, U+FEFF) — invisible. Often the first character of a UTF-8 file saved by Windows tools. Breaks JSON parsing, CSV import, and shell scripts.
    • Right-to-left mark (RLM, U+200F) — invisible. Flips display direction of subsequent text. Single accidental keystroke can mangle a whole paragraph.

    Our remover strips all of these by default. Toggle off if you’re working with intentional Arabic / Hindi / Hebrew content where these characters carry meaning.

    How to clean up text in your browser

    1. Open the whitespace remover
    2. Paste your text in the input
    3. Pick a preset (Light cleanup, Standard cleanup, Aggressive) or toggle individual options
    4. Output appears live as you type or paste
    5. Click Copy or Download .txt

    Common gotchas

    • Inside-string spaces matter in some contexts. If you’re cleaning code, “Aggressive” mode will collapse spaces inside string literals, breaking "foo bar". Use Light or Standard for code; aggressive for prose only.
    • Markdown is sensitive to trailing spaces. Two trailing spaces at the end of a markdown line is a hard line break. “Trim each line” destroys that. Disable trim if you’re cleaning markdown source.
    • YAML and Python are indent-sensitive. Don’t run “tabs to spaces” or “trim leading whitespace” on indented config — you’ll change the meaning. Use this tool on prose; use a code formatter on code.
    • NBSP in Word documents is intentional sometimes. Editorial styles use NBSP to keep “Mr. Smith” or “Page 5” together across line wraps. Aggressive NBSP-strip removes that protection.
    • BOM at the start of a file is invisible to your eye. Open a “broken” CSV in a hex editor — if the first three bytes are EF BB BF, that’s the BOM. Our tool strips it; many command-line tools don’t.
    • Tab width matters. Replacing tabs with spaces requires a width — 2 (modern web), 4 (Python / older code), or 8 (terminal default). Pick the same width your destination uses.

    When NOT to use this tool

    For programmatic cleanup inside a script, use the language-native tools — String.prototype.normalize('NFC').replace(/\s+/g, ' ').trim() in JavaScript, or " ".join(s.split()) in Python. For source code, use a code formatter (Prettier for JS, Black for Python). For Markdown source, use a Markdown linter that knows the format. Use this browser tool for prose, copy-pasted text from PDFs, email cleanup, and one-off formatting jobs where you don’t want to write a regex.

    Frequently asked questions

    Why does my “hello world” string fail comparison even though it looks right?

    Almost always an NBSP (U+00A0) where you expect a regular space (U+0020). Word, Outlook, and many web editors substitute NBSP automatically. Run “Strip NBSP” or use str.replace(/ /g, ' ') in code.

    Will this remove blank lines from my code?

    Yes if you toggle “Remove blank lines”. Don’t run that on code — blank lines often separate logical blocks. Use a code formatter instead. For prose, removing blank lines collapses paragraphs into one big block; for converting paragraphs to a single paragraph use the “Remove all line breaks” toggle instead.

    What’s the difference between trim, collapse, and strip blank lines?

    Trim removes leading and trailing whitespace per line. Collapse merges consecutive spaces inside a line into one. Strip blank lines deletes lines that contain only whitespace. They’re independent — you can run any combination.

    Does this fix line endings between Windows and macOS / Linux?

    Yes — toggle “Normalise line endings” to convert all CRLF and CR to LF (or pick the reverse). Useful when sharing CSV or text files across operating systems where one tool expects Unix-style and another expects Windows-style line endings.

    Is my text uploaded?

    No. The whitespace remover runs in your browser via JavaScript. Pasted content never reaches our servers — useful when cleaning up sensitive material (drafts, contracts, internal notes).

    Can I keep paragraph breaks but collapse internal whitespace?

    Yes — that’s the most common preset. Enable “Collapse multiple spaces” + “Trim each line” + “Strip NBSP” and leave “Remove blank lines” off. Result: clean paragraphs with no internal extra spaces, original paragraph structure preserved.

    Related tools and guides

     

  • Cubic Bezier Generator: CSS Easing Curves [2026]

    Cubic Bezier Generator: CSS Easing Curves [2026]

    TL;DR: CSS cubic-bezier() defines a custom easing curve for transitions and animations using four numbers — the X and Y of two control handles. cubic-bezier(0.25, 0.1, 0.25, 1) is the default “ease” keyword. Our free cubic-bezier generator ships a draggable visual editor, a live ball-and-square animation that plays the curve, and 14 named presets (ease, ease-in, ease-out, plus the Material Design and iOS spring curves).

    The default CSS easing keyword (ease) starts slow, accelerates, then slows down — fine for most quick state transitions, but bland for hero animations and microinteractions. cubic-bezier() lets you define an easing curve precisely. Drag the curve to start fast and end slow, overshoot the target, anticipate before moving, or stay still then snap into place. The right easing turns a generic UI into one that feels intentional.

    The challenge is that bezier coordinates are unreadable. cubic-bezier(0.4, 0, 0.2, 1) is Material Design’s standard curve. cubic-bezier(0.68, -0.55, 0.265, 1.55) is “back” easing with overshoot. You can’t picture either by reading the numbers. Our cubic-bezier generator shows the curve graphically with two draggable handles, animates a sample element with each curve change, and outputs the CSS in real time.

    The 14 named presets and what they feel like

    Preset Bezier values Feel
    linear 0, 0, 1, 1 Constant speed — for indeterminate spinners
    ease 0.25, 0.1, 0.25, 1 Default — smooth, slightly weighted near end
    ease-in 0.42, 0, 1, 1 Slow start, fast end — for elements leaving
    ease-out 0, 0, 0.58, 1 Fast start, slow end — for elements entering
    ease-in-out 0.42, 0, 0.58, 1 Symmetric — for back-and-forth movement
    Material Standard 0.4, 0, 0.2, 1 Material Design 3 default
    iOS Default 0.25, 0.46, 0.45, 0.94 Native iOS feel — close to ease-out
    Back (overshoot) 0.68, -0.55, 0.265, 1.55 Anticipates and overshoots — playful
    Snap 0.9, 0, 0.1, 1 Holds, then snaps in — for confident states

    How the curve works (in human terms)

    The four numbers in cubic-bezier(x1, y1, x2, y2) are the X and Y of two control handles between the start (always 0,0) and end (always 1,1) of the curve. The X axis is time (0 = start, 1 = end of the duration). The Y axis is progress (0 = initial position, 1 = final position). The handles pull the curve in the direction of their position — drag a handle up and the curve overshoots; drag it down and the curve eases.

    X must be between 0 and 1; Y can go above 1 (overshoot) or below 0 (anticipate). The visual editor enforces the X constraint and lets Y go outside the box for those expressive curves.

    How to design a bezier curve in your browser

    1. Open the cubic-bezier generator
    2. Pick a preset (or start from ease) and drag the two handles to shape the curve
    3. Watch the live preview — a square moves left-to-right with the easing applied
    4. Adjust the duration (250ms to 2s) and the curve in tandem to land on the right feel
    5. Click Copy CSS to grab the transition-timing-function declaration

    Where the bezier value goes in real CSS

    Two places use it: transition-timing-function and animation-timing-function. Inside the transition shorthand:

    .button {
      transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);
    }
    .button:hover {
      transform: translateY(-2px);
    }

    For keyframe animations, set the timing function on the animation as a whole or per keyframe (@keyframes entries can have their own timing function for staged easing).

    Common gotchas

    • linear-with-overrides for staged motion. If you need different easing per phase of an animation, use linear() (CSS Easing 2 — Chrome 113+) which lets you describe a polyline of stops, or chain multiple keyframes with their own timing functions.
    • Overshoot Y values can break perceived motion. A curve with Y > 1 returns the element past its target, then back. For “natural” overshoot, keep the second Y between 1.05 and 1.2; higher than 1.5 looks cartoony.
    • Don’t animate top, left, or width. These trigger layout. Always animate transform and opacity for 60fps performance, regardless of the easing curve.
    • iOS spring physics aren’t bezier curves. Native iOS uses spring-physics easing (mass, stiffness, damping). The closest CSS approximation is cubic-bezier(0.25, 0.46, 0.45, 0.94) for the standard iOS feel, but real spring curves bounce; bezier curves don’t.
    • steps() is not bezier. The steps() timing function produces discrete jumps for sprite animations. It’s a different family from cubic-bezier() — pick one based on whether you want continuous motion or a frame-by-frame walk cycle.
    • Match curve to direction. Use ease-out for elements entering the viewport (they decelerate into place); use ease-in for elements leaving (they accelerate away). Symmetric curves (ease, ease-in-out) are best for scrubbed timelines and back-and-forth states.

    When NOT to use cubic-bezier

    For physical-feeling spring animations (think iOS sheet open/close), use a JavaScript spring physics library — Framer Motion, react-spring, GSAP — rather than fighting bezier curves to approximate spring damping. For frame-perfect sprite animations, use steps(). For purely linear progress (loading bars, unbounded spinners), linear is simpler and renders identically. For micro-interactions where the curve is barely noticed (under 200ms transitions), the default ease works fine — bezier customisation matters most for animations between 250ms and 1s.

    Frequently asked questions

    What’s the difference between cubic-bezier and ease keywords?

    The keywords (ease, ease-in, ease-out, ease-in-out, linear) are predefined cubic-bezier curves. cubic-bezier() lets you define any curve. The keywords cover 80% of cases; you reach for cubic-bezier() when you want a specific feel like Material Design’s standard curve or playful overshoot.

    Can the bezier handles go outside the 0–1 box?

    Y can — values above 1 produce overshoot; below 0 produce anticipation (the element moves backward briefly before going forward). X cannot — it must be between 0 and 1, since X represents time. The visual editor enforces this constraint.

    Should I use cubic-bezier for everything?

    No. Use ease-out for entering elements, ease-in for leaving, ease-in-out for symmetric motion, and reach for custom cubic-bezier() when you need a specific brand feel (Material, iOS) or expressive overshoot. Most apps standardise on 1–3 custom curves project-wide for consistency.

    What’s the new linear() function?

    CSS Easing 2’s linear() (Chrome 113+, Safari 17.2+) lets you describe a polyline of stops — useful for approximating spring physics or staged motion in a single CSS rule. It’s not a replacement for cubic-bezier() for typical UI transitions; it’s a new tool for complex timelines.

    Is my data uploaded?

    No. The generator runs in your browser. Your curve values, preview animation, and downloaded CSS stay on your device.

    Does cubic-bezier work on all browsers?

    Yes — universal support since Chrome 4 (2010), Firefox 4, Safari 4. It’s one of the safest CSS features. Even mobile browsers have stable rendering.

    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