Frontend Development 12 min read

Creating Styled Console Logs in JavaScript with a PrettyLog Utility

This article explains how to enhance console output in JavaScript by using format specifiers, CSS styling, and a custom prettyLog utility that provides info, error, warning, success, table, and image printing functions, while ensuring the logs run only in development environments.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Creating Styled Console Logs in JavaScript with a PrettyLog Utility

Background

During a recent code review, my supervisor noticed the flashy console output in my local code and liked it, but asked whether it would affect performance in production. I assured that the logs are guarded to run only in development mode.

Console Overview

The console object is built‑in for debugging and logging, offering methods such as log , info , warn , error , and table to output various kinds of information.

Technical Solution

Placeholders

console.log() supports placeholders similar to C's printf :

%s – string

%d or %i – integer

%f – floating‑point number

%o – object

%c – CSS style

Formatted Strings

Example of using placeholders:

const name = 'Alice';
const age = 30;
console.log('Name: %s, Age: %d', name, age); // Name: Alice, Age: 30

Adding Styles

Use the %c placeholder to apply CSS styles to the output:

console.log('%c This is a styled message', 'color: red; font-size: 20px;');

PrettyLog Implementation

The prettyLog factory returns an object with several logging methods. It first checks whether the current environment is production and skips logging if so.

// prettyLog factory
const prettyLog = () => {
  const isProduction = import.meta.env.MODE === 'production';
  const isEmpty = (value) => value == null || value === undefined || value === '';
  const prettyPrint = (title, text, color) => {
    if (isProduction) return;
    console.log(`%c ${title} %c ${text} %c`,
      `background:${color};border:1px solid ${color};padding:1px;border-radius:2px 0 0 2px;color:#fff;`,
      `border:1px solid ${color};padding:1px;border-radius:0 2px 2px 0;color:${color};`,
      'background:transparent');
  };

  const info = (textOrTitle, content = '') => {
    const title = isEmpty(content) ? 'Info' : textOrTitle;
    const text = isEmpty(content) ? textOrTitle : content;
    prettyPrint(title, text, '#909399');
  };

  const error = (textOrTitle, content = '') => {
    const title = isEmpty(content) ? 'Error' : textOrTitle;
    const text = isEmpty(content) ? textOrTitle : content;
    prettyPrint(title, text, '#F56C6C');
  };

  const warning = (textOrTitle, content = '') => {
    const title = isEmpty(content) ? 'Warning' : textOrTitle;
    const text = isEmpty(content) ? textOrTitle : content;
    prettyPrint(title, text, '#E6A23C');
  };

  const success = (textOrTitle, content = '') => {
    const title = isEmpty(content) ? 'Success' : textOrTitle;
    const text = isEmpty(content) ? textOrTitle : content;
    prettyPrint(title, text, '#67C23A');
  };

  const table = () => {
    const data = [
      { id: 1, name: 'Alice', age: 25 },
      { id: 2, name: 'Bob', age: 30 },
      { id: 3, name: 'Charlie', age: 35 }
    ];
    console.log('%c id %c name %c age',
      'color: white; background-color: black; padding: 2px 10px;',
      'color: white; background-color: black; padding: 2px 10px;',
      'color: white; background-color: black; padding: 2px 10px;');
    data.forEach(row => {
      console.log(`%c ${row.id} %c ${row.name} %c ${row.age}`,
        'color: black; background-color: lightgray; padding: 2px 10px;',
        'color: black; background-color: lightgray; padding: 2px 10px;',
        'color: black; background-color: lightgray; padding: 2px 10px;');
    });
  };

  const picture = (url, scale = 1) => {
    if (isProduction) return;
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.onload = () => {
      const c = document.createElement('canvas');
      const ctx = c.getContext('2d');
      if (ctx) {
        c.width = img.width;
        c.height = img.height;
        ctx.fillStyle = 'red';
        ctx.fillRect(0, 0, c.width, c.height);
        ctx.drawImage(img, 0, 0);
        const dataUri = c.toDataURL('image/png');
        console.log(`%c sup?`,
          `font-size: 1px; padding: ${Math.floor((img.height * scale) / 2)}px ${Math.floor((img.width * scale) / 2)}px;`
          + `background-image: url(${dataUri}); background-repeat: no-repeat;`
          + `background-size: ${img.width * scale}px ${img.height * scale}px; color: transparent;`);
      }
    };
    img.src = url;
  };

  return { info, error, warning, success, table, picture };
};

// Usage example
const log = prettyLog();
log.info('This is basic info!');
log.info('Notice', 'A man named XiaoShuai!');
log.error('Error Title', 'Something went wrong');
log.warning('Watch out', 'Potential issue');
log.success('Great', 'Operation succeeded');
log.picture('https://example.com/image.png');

Development‑Only Logging

The utility checks import.meta.env.MODE to determine if the code is running in production; if so, all logging functions return early, preventing any console output in the production build.

Full Code

The complete source code is provided above, ready to be copied into a project and extended as needed.

debuggingFrontendjavascriptLoggingUtilityStylingconsole
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

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.