Frontend Development 14 min read

Customizing console.log Styles and Building a Console Log Button NPM Library

This article demonstrates how to style console.log output using %c placeholders, outlines the supported CSS properties, and walks through creating a lightweight, Vue‑devtool‑inspired log‑button library with Vite, TypeScript, ESLint, Husky, and ChatGPT‑generated UI color palettes, culminating in publishing the package to npm.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Customizing console.log Styles and Building a Console Log Button NPM Library

By leveraging the console.log , console.info , console.warn , and console.error APIs, developers can apply custom CSS‑like styles to console output using the %c placeholder, allowing multiple styled segments in a single log statement.

The first argument must contain a string template with one or more %c tokens, each of which corresponds to a subsequent style argument written like regular CSS (e.g., background-color: #2196f3; padding: 6px 12px; border-radius: 2px; color: #fff; ). Each %c token consumes one style string, and the number of style arguments must match the number of tokens.

Supported style properties include most visual CSS attributes such as background , border , box-shadow , color , display , font , margin , padding , text-transform , white-space , word-spacing , writing-mode , and others that the browser console permits.

To avoid clutter from numerous logs in large projects, the author created a small NPM library called console‑log‑button . Inspired by Vue‑devtool and arco‑design, the library provides button‑style logs with predefined color schemes and optional emoji symbols, and it can generate additional palettes using ChatGPT.

The project scaffolding uses vite create in library mode with TypeScript, followed by ESLint, Husky, and lint‑staged configuration. Key snippets include the vite.config.ts file that outputs both ES module and CommonJS bundles, and the package.json scripts for development, building, linting, and pre‑commit checks.

import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    target: 'modules',
    outDir: "dist",
    minify: false,
    rollupOptions: {
      input: ['src/index.ts'],
      output: [
        {
          format: 'es',
          entryFileNames: '[name].js',
          preserveModules: true,
          dir: 'es',
          preserveModulesRoot: 'src'
        },
        {
          format: 'cjs',
          entryFileNames: '[name].js',
          preserveModules: true,
          dir: 'lib',
          preserveModulesRoot: 'src'
        }
      ]
    },
    lib: {
      entry: './index.ts',
      formats: ['es', 'cjs'],
    }
  },
});

Core logging functions are provided:

/**
 * Basic log method
 * @param {string} logBy   Text for the first button
 * @param {string} logName Text for the second button
 * @param {any}    data    Additional data to log (rest parameters)
 */
export const buttonLog = (logBy = '', logName = '', ...logData: any[]) =>
  console.log(
    `%c log-by-${logBy} %c ${logName} %c`,
    `background: ${VUE_DEEP_CYAN}; padding: 6px; border-radius: 1px 0 0 1px; color: #fff`,
    `background: ${VUE_BLUE_GRAY}; padding: 6px; border-radius: 0 1px 1px 0; color: #fff`,
    'background: transparent',
    ...logData
  );
const colorMap = new Map([
  ['yellow', '#FFC107'],
  ['orange', '#ff9800'],
  ['red', '#f44336'],
  ['green', '#4caf50'],
  ['cyan', '#00BCD4'],
  ['blue', '#2196f3'],
  ['purple', '#9C27B0'],
]);

const gradientColorMap = new Map([
  ['yellow', 'linear-gradient(to right, #FDB813, #FFAA00)'],
  ['orange', 'linear-gradient(to right, #FFA500, #FF6347)'],
  ['red', 'linear-gradient(to right, #FF416C, #FF4B2B)'],
  ['green', 'linear-gradient(to right, #00b09b, #96c93d)'],
  ['cyan', 'linear-gradient(to right, #1D976C, #93F9B9)'],
  ['blue', 'linear-gradient(to right, #2196F3, #4FC3F7)'],
  ['purple', 'linear-gradient(to right, #DA22FF, #9733EE)'],
]);

/**
 * Material‑UI style log method
 * @param {object} config   Configuration object
 *   - logName: button text
 *   - type: one of 'yellow'|'orange'|'red'|'green'|'cyan'|'blue'|'purple'
 *   - isLinearGradient: whether to use gradient background
 * @param {any[]} data    Additional data to log
 */
export const materialButtonLog = ({ logName = '', type = 'blue', isLinearGradient = false }, ...data: any[]) => {
  if (isLinearGradient) {
    console.log(`%c${logName}`, `background-image: ${gradientColorMap.get(type)}; padding: 6px 12px; border-radius: 2px; font-size: 14px; color: #fff; text-transform: uppercase; font-weight: 600;`, ...data);
  } else {
    console.log(`%c${logName}`, `background-color: ${colorMap.get(type)}; padding: 6px 12px; border-radius: 2px; font-size: 14px; color: #fff; text-transform: uppercase; font-weight: 600;`, ...data);
  }
};

A configurable class ButtonLogClass allows users to define custom colors, padding, border radius, and font color, then emit styled logs via its log method.

export default class ButtonLogClass implements IButtonLogClass {
  logBy;
  logName;
  preButtonColor;
  nextButtonColor;
  padding;
  borderRadius;
  fontColor;
  logTemplate = (logBy = '', logName = '') => `%c log-by-${logBy} %c ${logName} `;

  constructor(config: IButtonLogConfig) {
    this.logBy = config.logBy || '';
    this.logName = config.logName || '';
    this.preButtonColor = config.preButtonColor || VUE_DEEP_CYAN;
    this.nextButtonColor = config.nextButtonColor || VUE_BLUE_GRAY;
    this.padding = config.padding || 6;
    this.borderRadius = config.borderRadius || 1;
    this.fontColor = config.fontColor || '#fff';
  }

  log = (...data: any[]) => {
    const firstButtonStyle = `background: ${this.preButtonColor}; padding: ${this.padding}px; border-radius: ${this.borderRadius}px 0 0 ${this.borderRadius}px; color: ${this.fontColor}`;
    const secondButtonStyle = `background: ${this.nextButtonColor}; padding: ${this.padding}px; border-radius: 0 ${this.borderRadius}px ${this.borderRadius}px 0; color: ${this.fontColor}`;
    console.log(
      this.logTemplate(this.logBy, this.logName),
      firstButtonStyle,
      secondButtonStyle,
      ...data
    );
  };
}

Before publishing, the author reminds readers to register an npm account, set the registry with npm config set registry https://registry.npmjs.org/ , log in via npm login , ensure all changes are committed, bump the version in package.json , run yarn build to generate the ES and CommonJS bundles, and finally execute npm publish .

The article concludes with a link to the npm package and its GitHub repository, encouraging developers to try the library and explore further styling possibilities.

frontendTypeScriptJavaScriptvitenpmconsolelog
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.