Skip to content

VSCode extension that modify CSS and JS code in both editor and webview, unify global font family, setup background image and Electron BrowserWindow options, add your custom CSS or JS code, and even patch files in other VSCode extensions.

License

Notifications You must be signed in to change notification settings

subframe7536/vscode-custom-ui-style

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Custom UI Style

Visual Studio Marketplace Version Made with reactive-vscode

Custom UI Style is a VSCode extension that allows you to customize the editor's appearance and behavior by injecting custom CSS and JavaScript. You can unify the global font family, set a background image, modify Electron BrowserWindow options, add your own custom styles and scripts, and even patch files in other VSCode extensions.

  • Works with VSCode 1.103! (Tested on Windows and MacOS)

Warning

This extension works by modifying the VSCode's source css and js files.

âť—CLAIM

Untested on Linux and VSCode forks (like Cursor, WindSurf, etc.), and I currently lack the energy to adapt them. If this extension causes issues in your editor, please consider using these more mature alternative extensions

Features

  • Unify the global font family for the editor and webviews.
  • Set a background image for the editor window.
  • Apply custom stylesheets to both the editor and webviews.
  • Configure Electron BrowserWindow options.
  • Support for restarting VSCode to apply changes.
  • Suppress the "Your Code installation is corrupt" message.
  • Load external CSS and JavaScript files.
  • Patch files in other extensions.

Usage

  1. Backup: When you first install the extension or after a VSCode update, you'll be prompted to create a backup of the original files. This is important for rollback.
  2. Configure: Add your customizations to your settings.json file. See the Example and Configurations sections for details.
  3. Apply: Open the Command Palette (Ctrl+Shift+P or Cmd+Shift+P) and run Custom UI Style: Reload to apply your changes.
  4. Rollback: To revert all changes and restore the original VSCode files, run Custom UI Style: Rollback from the Command Palette.

See details for more information.

Example

Available CSS Variables:

  • --cus-monospace-font: Target monospace font family
  • --cus-sans-font: Target sans-serif font family
{
  // Electron BrowserWindow options
  //  - https://www.electronjs.org/docs/latest/api/base-window
  //  - https://www.electronjs.org/docs/latest/api/browser-window
  "custom-ui-style.electron": {
    // Frameless window (no title bar, no MacOS traffic light buttons)
    //  - "A frameless window removes all chrome applied by the OS, including window controls"
    //  - https://www.electronjs.org/docs/latest/api/base-window#new-basewindowoptions
    //  - https://www.electronjs.org/docs/latest/tutorial/custom-window-styles#frameless-windows
    //  - https://www.electronjs.org/docs/latest/tutorial/custom-title-bar
    "frame": false,
    // Disable rounded corners (MacOS)
    //  - https://www.electronjs.org/docs/latest/api/base-window#new-basewindowoptions
    //  - "Whether frameless window should have rounded corners on MacOS"
    //  - "Setting this property to false will prevent the window from being fullscreenable"
    "roundedCorners": false,
  },
  "custom-ui-style.font.sansSerif": "Maple UI, -apple-system",
  "custom-ui-style.background.url": "file:///D:/image/ide-bg.jpg",
  "custom-ui-style.webview.monospaceSelector": [".codeblock", ".prism [class*='language-']"],
  // Custom stylesheet, support native nest selectors
  "custom-ui-style.stylesheet": {
    "kbd, .statusbar": {
      "font-family": "var(--cus-monospace-font)",
    },
    "span:not([class*='dyn-rule'])+span[class*='dyn-rule']": {
      "border-top-left-radius": "3px",
      "border-bottom-left-radius": "3px"
    },
    "span[class*='dyn-rule']:has(+span[class*='dyn-rule']+span:not([class*='dyn-rule']))": {
      "border-top-right-radius": "3px",
      "border-bottom-right-radius": "3px"
    },
    ".cdr": {
      "border-radius": "3px"
    },
    ".monaco-findInput .monaco-inputbox": {
      "width": "calc(100% + 6px)"
    },
    ".monaco-workbench .activitybar .monaco-action-bar": {
      "& .action-label": {
        "font-size": "21px !important",
        "&::before": {
          "position": "absolute",
          "z-index": 2
        },
        "&::after": {
          "content": "''",
          "width": "75%",
          "height": "75%",
          "position": "absolute",
          "border-radius": "6px",
        },
      },
      "& .action-item:hover .action-label": {
        "color": "var(--vscode-menu-selectionForeground) !important",
        "&::after": {
          "background-color": "var(--vscode-menu-selectionBackground)",
        }
      },
      "& .active-item-indicator:before": {
        "border": "none !important",
        "width": "3px !important",
        "height": "calc(100% - 12px) !important",
        "top": "6px !important",
        "border-radius": "4px"
      },
      "& .action-item.checked .active-item-indicator:before": {
        "background": "var(--vscode-activityBar-activeBorder)",
      }
    },
    ".basepanel .composite-bar-container .actions-container > .action-item": {
      "height": "24px",
      "padding": "0 8px !important",
      "border-radius": "4px",
      "align-items": "center",
      "justify-content": "center",
      "&.checked": {
        "background": "color-mix(in srgb, var(--vscode-foreground) 12%, transparent)",
      },
      "& .active-item-indicator:before": {
        "content": "none !important"
      }
    },
    ".monaco-text-button": {
      "border-radius": "4px !important",
    },
    ".monaco-button-dropdown": {
      "& > .monaco-button.monaco-text-button": {
        "border-radius": "4px 0 0 4px !important",
      },
      "& > .monaco-button.monaco-dropdown-button": {
        "border-radius": "0 4px 4px 0 !important",
      },
    },
    ".monaco-workbench>.notifications-center": {
      "border-radius": "8px !important"
    },
  }
}

External Resources (CSS or JS File)

Starting from v0.4.2, you can load external CSS and JavaScript files from local or remote URLs.

Caution

Loading external resources can introduce security risks or cause runtime crashes. Use this feature with caution.

  • All resources are applied to the editor, not webviews.
  • Resources are fetched and merged during reload. Live-watching of files is not supported.
{
  "custom-ui-style.external.imports": [
    // assume the script is ESM format
    "file://D:/data/test.js",
    "file:///Users/yourname/test.js",

    // Variable supports:
    // Load from user home dir
    "file://${userHome}/test.css",
    // Load from environment variable (with optional fallback value)
    "file://${env:your_env_name:optional_fallback_value}/other.js",

    // Remote resources will be downloaded
    {
      // <link rel="stylesheet" href="./external.css"></link>
      // will load before `custom-ui-style.stylesheet`
      "type": "css",
      "url": "https://fonts.googleapis.com/css?family=Sofia",
    },
    {
      // <script src="./external.js"></script>
      "type": "js",
      "url": "https://example.com/test.js",
    },
    {
      // <script src="./external.module.js" type="module"></script>
      "type": "js-module",
      "url": "https://example.com/test.module.js",
    }
  ]
}

Load Strategy

By default, all resources are re-fetched on every reload, and failed fetches are skipped.

To cache resources and avoid re-fetching when custom-ui-style.external.imports is unchanged, set the load strategy to "cache":

{
  "custom-ui-style.external.loadStrategy": "cache"
}

To disable all external resources, set the load strategy to "disable":

{
  "custom-ui-style.external.loadStrategy": "disable"
}

Patch Extension

Find and replace target string or Regexp in extension's file

{
  // "custom-ui-style.extensions.enable": false,
  "custom-ui-style.extensions.config": {
    // extension id
    "github.copilot-chat": [
      {
        // target file path related to extension root
        "filePath": "dist/extension.js",
        // find string (support JavaScript like regexp)
        "find": "https://generativelanguage.googleapis.com/v1beta/openai",
        // replace string
        "replace": "<path/to/url>"
      }
    ]
  },
}

FAQ

What is modified?

This extension modifies files in your VSCode installation directory. All modified files are backed up with a .custom-ui-style suffix in the same directory. You can see the full list of modified files in path.ts.

When you reload the configuration, the extension restores the original files from the backup, applies your custom patches, and then reloads the window or restarts the application.

No Effect

If your changes don't seem to apply, you may need to fully restart VSCode.

  • Windows/Linux: Close all VSCode windows and restart the application.
  • macOS: Press Command + Q to quit the application, then restart it.

There are also a guide and a video (macOS) available for more detailed instructions.

EROFS: read-only file system

If you see this error, it means VSCode is installed on a read-only filesystem (e.g., via Snap or AppImage). This extension needs to write to the installation directory, so you'll need to install VSCode using a different method.

RangeError: Maximum call stack size exceeded

This error can occur due to system permission restrictions. To fix it, you need to change the ownership of the VSCode installation directory.

First, fully close VSCode (Command + Q</_kbd> on macOS). Then, run the following command:

# macOS
sudo chown -R $(whoami) "/Applications/Visual Studio Code.app"

# Linux
sudo chown -R $(whoami) "/usr/local/code"

See #6 for more details.

Fail to render panel

In some VSCode forks like Cursor, the extension detail panel may not render due to a Content Security Policy (CSP) violation. To work around this, you can disable the webview patch:

{
  "custom-ui-style.webview.enable": false
}

Configurations

Key Description Type Default
custom-ui-style.preferRestart Prefer restarting VSCode after updates (always true for VSCode >= 1.95.0) boolean false
custom-ui-style.reloadWithoutPrompting Reload/restart immediately without a notification prompt boolean false
custom-ui-style.watch Automatically reload window on configuration changes (ignores imports) boolean true
custom-ui-style.electron Electron BrowserWindow options (see Electron documentation) object {}
custom-ui-style.font.monospace Global monospace font family for editor and webviews (falls back to editor's font) string ``
custom-ui-style.font.sansSerif Global sans-serif font family for editor and webviews string ``
custom-ui-style.background.url Full-screen background image URL (e.g., 'https://', 'file://', 'data:') - not synced string ``
custom-ui-style.background.syncURL Full-screen background image URL (synced), supports variables like ${userHome} or ${env:VAR:fallback}. Lower priority than 'url'. string ``
custom-ui-style.background.opacity Background image opacity (0 to 1) number 0.9
custom-ui-style.background.size Background image size (e.g., 'cover', 'contain') string "cover"
custom-ui-style.background.position Background image position string "center"
custom-ui-style.external.loadStrategy Strategy for loading external CSS or JS resources string "refetch"
custom-ui-style.external.imports External CSS or JS resources; supports variables (${userHome}, ${env:VAR:fallback}) and protocols ('https://', 'file://') array ``
custom-ui-style.stylesheet Custom CSS for the editor; supports nested selectors object {}
custom-ui-style.extensions.enable Enable file patching in other extensions boolean true
custom-ui-style.extensions.config Configuration for patching extension files (key: extension ID, value: patch config) object {}
custom-ui-style.webview.enable Enable style patching in webviews boolean true
custom-ui-style.webview.removeCSP Remove Content-Security-Policy restrictions in webviews boolean true
custom-ui-style.webview.monospaceSelector Custom monospace selector for webviews array ``
custom-ui-style.webview.sansSerifSelector Custom sans-serif selector for webviews array ``
custom-ui-style.webview.stylesheet Custom CSS for webviews; supports nested selectors object {}

Commands

Command Title
custom-ui-style.reload Custom UI Style: Reload
custom-ui-style.rollback Custom UI Style: Rollback

Credit

License

MIT

About

VSCode extension that modify CSS and JS code in both editor and webview, unify global font family, setup background image and Electron BrowserWindow options, add your custom CSS or JS code, and even patch files in other VSCode extensions.

Resources

License

Stars

Watchers

Forks