Skip to main content
Ben Nadel at InVision Office 2011 (New York City) with: Lindsey Root and Adam Root and Clark Valberg
Ben Nadel at InVision Office 2011 (New York City) with: Lindsey Root Adam Root Clark Valberg

Styling console.log() Output With A Chalk-Inspired Formatter Using JavaScript Proxies

By
Published in , Comments (3)

Yesterday, I had a lot of fun using CSS to style my console.log() output in Chrome and Firefox. And while I haven't done much programming with Node.js in a while, yesterday's experiment made me nostalgic for Chalk - an npm package that provides string styling for the terminal. One of the coolest things about the Chalk module is that you can arbitrarily chain different "style modifiers" together to create custom formats. As a follow-up to yesterday's experiment, I wanted to see if I could create a Chalk-inspired console.log() formatter using JavaScript Proxies.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

To do this, I'm going to build off of yesterday's echo object. Only, instead of having just the two custom stylers - asWarning and asAlert - I'm going to allow any set of arbitrary styles to be used to format the console.log() output. And, each of these stylers can be chained off of each other.

So, for example, to output white text on a black background, you could do this:

echo.log( echo.white.bgBlack( "Hello wordl!" ) );

Just as with Chalk, different modifiers affect different styles. In this case, these modifiers are adding these CSS snippets to the output formatting:

  • white: color: white
  • bgBlack: background-color: black

Chalk is fairly limited in what it can do because it has to work with the terminal which is also fairly limited. But, as I demonstrated yesterday, the Console can handle quite a bit of CSS shenanigans. So, instead of relying on a static set of modifiers, I'd like people to be able add custom modifiers as well. Something like:

echo.defineStyler( "wootSauce", "color: magenta ; font-size: 30px ;" );

... and then, be able to use those custom modifier in their logging right alongside the built-in modifiers:

echo.log( echo.wootSauce.bold.strikethrough( "Coolest" ) );

Before we look at how I am going to implement this, let's take a look at how we can consume it. In this demo, notice that I am pulling in two JavaScript files: echo.js and echo-colors.js. Then, I'm echo.log()'ing a bunch of stuff:

<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>
		Styling console.log() Output With A Chalk-Inspired Formatter Using JavaScript Proxies
	</title>
</head>
<body>

	<h1>
		Styling console.log() Output With A Chalk-Inspired Formatter Using JavaScript Proxies
	</h1>

	<script type="text/javascript" src="./echo.js"></script>
	<script type="text/javascript" src="./echo-colors.js"></script>
	<script type="text/javascript">

		echo
			// The "root" styler is the raw CSS that will be inherited by all other
			// stylers, custom and internal.
			.defineRootStyler( "color: red ;" )
			.defineStyler( "asTag", echo.bold.padded.rounded )
			// Notice that the next two stylers are building off of "asTag", a previously
			// defined custom styler.
			.defineStyler( "asWarning", echo.asTag.bgGold.black )
			.defineStyler( "asAlert", echo.asTag.bgRed.white )
			// Custom stylers can also just be raw CSS.
			.defineStyler( "asMarquee", "font-size: 30px ; padding: 20px 30px 20px 30px ; display: inline-block ; border: 3px solid gold ;" )
		;

		// Once our custom stylers are defined, we can now use them in combination with
		// the core stylers and the echo-log functions.
		echo.log( echo.bgMagenta.white.lighter.large( "hello world" ) );
		echo.log( echo.bgBlack.white.bold.larger( "hello world" ) );
		echo.log( echo.bgCyan.black.largest.asTag( "hello world" ) );
		echo.log( echo.bgMagenta.white.lighter.massive.asTag( "hello world" ) );
		echo.log( echo.cyan.bgBlack( "hello world" ) );
		echo.log( echo.asWarning.strikethrough( "hello world" ) );
		echo.log( echo.asAlert.underline( "hello world" ) );
		echo.log( echo.asMarquee( "hello world" ) );

		// Using the extended colors.
		echo.log(
			echo.bgDodgerblue.white.largest.asTag.lighter( "Hot" ),
			echo.bgDimgray.white.largest.asTag( "Diggity" ),
			echo.bgRebeccapurple.white.largest.asTag.lighter( "Dog" ),
			echo.bgYellowgreen.white.largest.asTag( "That's" ),
			echo.bgTomato.white.largest.asTag.lighter( "Cool!" )
		);

		// And, of course, these stylers can be mixed with "raw" values as well.
		echo.log(
			"Raw value",
			echo.bgGray.white.asTag( "Styled value" ),
			[ "Raw value" ]
		);

	</script>

</body>
</html>

While this is just a bunch of "log statements", there's some cool stuff happening here:

  • I can alias a set of CSS properties using defineStyler().

  • I can alias a set of chained modifiers using defineStyler().

  • I can intermingle my aliased stylers with the built-in stylers.

And, when we run this JavaScript code, we get the following Console output:

Custom console.log() output using echo and proxies.

Under the hood, the .defineStyler() method is really just augmenting a hash of named values. And, because these values are being accessed "just in time" using a Proxy, it means that we can alter the set of styles at any time during the execution of the JavaScript application:

Custom echo stylers being created on-the-fly.

To get this all to work, I need every styler to "hang off" the echo object. But then, I also need every styler "hang off" of every other styler so that these formatters can be arbitrarily chained. I'm sure there is some way that I could do this using lots of dynamic programming; but, it seems like a task perfectly suited to a Proxy.

CAUTION: I've barely every used the Proxy class in JavaScript; so, take everything I say after this with a grain of salt.

A Proxy is a wrapper for an arbitrary target that can intercept calls to that target. These calls might be setters, getters, method invocations, and a few other types of operations. During each interception, the Proxy can decide to alter the behavior of the operation; or, it can decide to pass the operation through to the target.

In this experiment, all I'm going to do is intercept the getter. And, if the developer appears to be trying to access one of the "stylers", my Proxy will return a styler. But, of course, since every styler needs to hang off of every other styler, each styler is - itself - returned as a Proxy that can intercept styler getters.

Here's what I came up with:

window.echo = (function echoFactory() {
	"use strict";

	var stylers = {
		// Text colors.
		black: "color: black",
		red: "color: red",
		green: "color: green",
		blue: "color: blue",
		yellow: "color: yellow",
		magenta: "color: magenta",
		cyan: "color: cyan",
		white: "color: white",
		gray: "color: gray",
		gold: "color: gold",

		// Background colors.
		bgBlack: "background-color: black",
		bgRed: "background-color: red",
		bgGreen: "background-color: green",
		bgBlue: "background-color: blue",
		bgYellow: "background-color: yellow",
		bgMagenta: "background-color: magenta",
		bgCyan: "background-color: cyan",
		bgWhite: "background-color: white",
		bgGray: "background-color: gray",
		bgGold: "background-color: gold",

		// Text modifiers.
		bold: "font-weight: bold",
		lighter: "font-weight: lighter",
		italic: "font-style: italic",
		strikethrough: "text-decoration: line-through",
		underline: "text-decoration: underline",
		large: "font-size: 16px",
		larger: "font-size: 22px",
		largest: "font-size: 26px",
		massive: "font-size: 36px",

		// Block modifiers.
		padded: "display: inline-block ; padding: 4px 6px",
		rounded: "display: inline-block ; border-radius: 4px"
	};

	var rootStyler = "";

	// As "styler" functions are called, they are going to push values and CSS onto this
	// queue. Then, when the "log" functions are called, this queue will be processed and
	// cleared (for the next set of styler invocations).
	var logItemQueue = [];

	// When the "styler" functions are called, they populate the queue (above). As such,
	// their return value isn't directly consumable. Therefore, they return this token
	// which helps our queue-processor differentiate from a styler value vs. a raw value.
	// And, the embedded warning helps the developer understand where / if they made a
	// mistake in how the styler return value was used.
	var ECHO_TOKEN = {
		warning: "This value should not be used directly - it should be an argument to an echo invocation."
	};
	var RESET_INPUT = "%c ";
	var RESET_CSS = "";

	var coreApi = {
		log: wrapConsoleFunction( console.log ),
		warn: wrapConsoleFunction( console.warn ),
		error: wrapConsoleFunction( console.error ),
		trace: wrapConsoleFunction( console.trace ),
		group: wrapConsoleFunction( console.group ),
		groupEnd: wrapConsoleFunction( console.groupEnd ),
		defineStyler: defineStyler,
		defineRootStyler: defineRootStyler
	};

	// We want all of our "stylers" to hang off the core API. And, since the collection
	// of stylers can change over time (using aliases and customizations), we have to
	// proxy the core API such that we can dynamically see if a styler is being accessed.
	var coreApiProxy = new Proxy(
		coreApi,
		{
			get: function( target, prop, receiver ) {

				// Intercept styler access.
				if ( prop in stylers ) {

					return( createStylerProxy( prop ) );

				}

				return( target[ prop ] );

			}
		}
	);

	return( coreApiProxy );

	// ---
	// PUBLIC METHODS.
	// ---

	// I define the root CSS that all other styles will start with.
	// --
	// NOTE: This method should be called before any other stylers are created.
	function defineRootStyler( rawCSS ) {

		rootStyler = rawCSS;
		return( this );

	}


	// I allow new stylers to be defined. The "newStyler" can be a string of raw CSS; or,
	// it can be a reference to another styler.
	function defineStyler( name, newStyler ) {

		if ( typeof( newStyler ) === "string" ) {

			stylers[ name ] = newStyler;
			return( this );

		} else {

			stylers[ name ] = newStyler.proxyCSS;
			return( this );

		}

	}

	// ---
	// PRIVATE METHODS.
	// ---

	// Every "styler" needs to hang off of very other styler. And, as each styler is
	// accessed, it needs to aggregate the pending CSS from all of the previous stylers
	// in the access path. To do this, we're going to use a Proxy object.
	function createStylerProxy( rootProp, rootCSS = "" ) {

		var proxyCSS = ( rootCSS + ";" + stylers[ rootProp ] );

		// Every "styler" ultimately needs to be a Function call that applies the
		// aggregate CSS to the given value.
		var applyAggregateCSS = function( value ) {

			logItemQueue.push({
				value: value,
				css: ( rootStyler + ";" + proxyCSS )
			});

			return( ECHO_TOKEN );

		};

		var stylerProxy = new Proxy(
			applyAggregateCSS,
			{
				get: function( target, prop ) {

					// Since we can alias styler proxies, we need a way to return the
					// aggregated CSS for any given proxy.
					if ( prop === "proxyCSS" ) {

						return( proxyCSS );

					}

					if ( prop in stylers ) {

						return( createStylerProxy( prop, proxyCSS ) );

					}

				}
			}
		);

		return( stylerProxy );

	}


	// I provide an echo-based wrapper for the given Console Function. This uses an
	// internal queue to aggregate values before calling the underlying Console Function
	// with the desired CSS formatting.
	function wrapConsoleFunction( consoleFunction ) {

		function consoleFunctionWrapper() {

			// As we loop over the arguments, we're going to aggregate a set of inputs
			// and modifiers. The Inputs will ultimately be collapsed down into a single
			// string that acts as the first console.log parameter while the modifiers
			// are then SPREAD into console.log as 2...N.
			// --
			// NOTE: After each input/modifier pair, I'm adding a RESET pairing. This
			// implicitly resets the CSS after every formatted pairing.
			var inputs = [];
			var modifiers = [];

			for ( var rawArg of arguments ) {

				// When the styler methods are called, they return a special token. This
				// token indicates that we should pull the corresponding value out of the
				// QUEUE instead of trying to consume the given argument directly.
				if ( rawArg === ECHO_TOKEN ) {

					var item = logItemQueue.shift();

					inputs.push( ( "%c" + item.value ), RESET_INPUT );
					modifiers.push( item.css, RESET_CSS );

				// For every other argument type, output the value directly.
				} else {

					if (
						( typeof( rawArg ) === "object" ) ||
						( typeof( rawArg ) === "function" )
						) {

						inputs.push( "%o", RESET_INPUT );
						modifiers.push( rawArg, RESET_CSS );

					} else {

						inputs.push( ( "%c" + rawArg ), RESET_INPUT );
						modifiers.push( RESET_CSS, RESET_CSS );

					}

				}

			}

			consoleFunction( inputs.join( "" ), ...modifiers );

			// Once we output the aggregated value, reset the queue. This should have
			// already been emptied by the .shift() calls; but the explicit reset here
			// acts as both a marker of intention as well as a fail-safe.
			logItemQueue = [];

		}

		return( consoleFunctionWrapper );

	}

})();

The coolest part of this whole thing is this part right here, where we create a styler proxy:

var stylerProxy = new Proxy(
	applyAggregateCSS,
	{
		get: function( target, prop ) {

			// Since we can alias styler proxies, we need a way to return the
			// aggregated CSS for any given proxy.
			if ( prop === "proxyCSS" ) {

				return( proxyCSS );

			}

			if ( prop in stylers ) {

				return( createStylerProxy( prop, proxyCSS ) );

			}

		}
	}
);

As I mentioned above, every styler is, itself, a Proxy. And that's because it has to intercept the get operation such that all stylers can be chained off of all other styles. And, when a chained styler is requested, we create a new Proxy and pass-in the aggregated CSS of the current styler as the "root CSS" of the next styler. This creates a new styler that concatenates its own CSS on top of every previous styler in the chain.

This was a lot of fun to build. Which is great because I woke up at 3am this morning for some reason and couldn't fall back to sleep. It was great to try out the Proxy class, and pay homage to Chalk - one of my favorite npm modules.

Epilogue: echo-colors.js

As I mentioned above, the demo includes two files: the main echo.js file and a "colors" file. The echo-colors.js file just uses the .defineStyler() method to define color and background color stylers for the named web colors:

// The list of colors taken from MDN
// --
// https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
echo.defineStyler( "black", "color: #000000" );
echo.defineStyler( "bgBlack", "background-color: #000000" );

echo.defineStyler( "silver", "color: #c0c0c0" );
echo.defineStyler( "bgSilver", "background-color: #c0c0c0" );

echo.defineStyler( "gray", "color: #808080" );
echo.defineStyler( "bgGray", "background-color: #808080" );

echo.defineStyler( "white", "color: #ffffff" );
echo.defineStyler( "bgWhite", "background-color: #ffffff" );

echo.defineStyler( "maroon", "color: #800000" );
echo.defineStyler( "bgMaroon", "background-color: #800000" );

echo.defineStyler( "red", "color: #ff0000" );
echo.defineStyler( "bgRed", "background-color: #ff0000" );

echo.defineStyler( "purple", "color: #800080" );
echo.defineStyler( "bgPurple", "background-color: #800080" );

echo.defineStyler( "fuchsia", "color: #ff00ff" );
echo.defineStyler( "bgFuchsia", "background-color: #ff00ff" );

echo.defineStyler( "green", "color: #008000" );
echo.defineStyler( "bgGreen", "background-color: #008000" );

echo.defineStyler( "lime", "color: #00ff00" );
echo.defineStyler( "bgLime", "background-color: #00ff00" );

echo.defineStyler( "olive", "color: #808000" );
echo.defineStyler( "bgOlive", "background-color: #808000" );

echo.defineStyler( "yellow", "color: #ffff00" );
echo.defineStyler( "bgYellow", "background-color: #ffff00" );

echo.defineStyler( "navy", "color: #000080" );
echo.defineStyler( "bgNavy", "background-color: #000080" );

echo.defineStyler( "blue", "color: #0000ff" );
echo.defineStyler( "bgBlue", "background-color: #0000ff" );

echo.defineStyler( "teal", "color: #008080" );
echo.defineStyler( "bgTeal", "background-color: #008080" );

echo.defineStyler( "aqua", "color: #00ffff" );
echo.defineStyler( "bgAqua", "background-color: #00ffff" );

echo.defineStyler( "orange", "color: #ffa500" );
echo.defineStyler( "bgOrange", "background-color: #ffa500" );

echo.defineStyler( "aliceblue", "color: #f0f8ff" );
echo.defineStyler( "bgAliceblue", "background-color: #f0f8ff" );

echo.defineStyler( "antiquewhite", "color: #faebd7" );
echo.defineStyler( "bgAntiquewhite", "background-color: #faebd7" );

echo.defineStyler( "aquamarine", "color: #7fffd4" );
echo.defineStyler( "bgAquamarine", "background-color: #7fffd4" );

echo.defineStyler( "azure", "color: #f0ffff" );
echo.defineStyler( "bgAzure", "background-color: #f0ffff" );

echo.defineStyler( "beige", "color: #f5f5dc" );
echo.defineStyler( "bgBeige", "background-color: #f5f5dc" );

echo.defineStyler( "bisque", "color: #ffe4c4" );
echo.defineStyler( "bgBisque", "background-color: #ffe4c4" );

echo.defineStyler( "blanchedalmond", "color: #ffebcd" );
echo.defineStyler( "bgBlanchedalmond", "background-color: #ffebcd" );

echo.defineStyler( "blueviolet", "color: #8a2be2" );
echo.defineStyler( "bgBlueviolet", "background-color: #8a2be2" );

echo.defineStyler( "brown", "color: #a52a2a" );
echo.defineStyler( "bgBrown", "background-color: #a52a2a" );

echo.defineStyler( "burlywood", "color: #deb887" );
echo.defineStyler( "bgBurlywood", "background-color: #deb887" );

echo.defineStyler( "cadetblue", "color: #5f9ea0" );
echo.defineStyler( "bgCadetblue", "background-color: #5f9ea0" );

echo.defineStyler( "chartreuse", "color: #7fff00" );
echo.defineStyler( "bgChartreuse", "background-color: #7fff00" );

echo.defineStyler( "chocolate", "color: #d2691e" );
echo.defineStyler( "bgChocolate", "background-color: #d2691e" );

echo.defineStyler( "coral", "color: #ff7f50" );
echo.defineStyler( "bgCoral", "background-color: #ff7f50" );

echo.defineStyler( "cornflowerblue", "color: #6495ed" );
echo.defineStyler( "bgCornflowerblue", "background-color: #6495ed" );

echo.defineStyler( "cornsilk", "color: #fff8dc" );
echo.defineStyler( "bgCornsilk", "background-color: #fff8dc" );

echo.defineStyler( "crimson", "color: #dc143c" );
echo.defineStyler( "bgCrimson", "background-color: #dc143c" );

echo.defineStyler( "cyan", "color: #00ffff" );
echo.defineStyler( "bgCyan", "background-color: #00ffff" );

echo.defineStyler( "darkblue", "color: #00008b" );
echo.defineStyler( "bgDarkblue", "background-color: #00008b" );

echo.defineStyler( "darkcyan", "color: #008b8b" );
echo.defineStyler( "bgDarkcyan", "background-color: #008b8b" );

echo.defineStyler( "darkgoldenrod", "color: #b8860b" );
echo.defineStyler( "bgDarkgoldenrod", "background-color: #b8860b" );

echo.defineStyler( "darkgray", "color: #a9a9a9" );
echo.defineStyler( "bgDarkgray", "background-color: #a9a9a9" );

echo.defineStyler( "darkgreen", "color: #006400" );
echo.defineStyler( "bgDarkgreen", "background-color: #006400" );

echo.defineStyler( "darkgrey", "color: #a9a9a9" );
echo.defineStyler( "bgDarkgrey", "background-color: #a9a9a9" );

echo.defineStyler( "darkkhaki", "color: #bdb76b" );
echo.defineStyler( "bgDarkkhaki", "background-color: #bdb76b" );

echo.defineStyler( "darkmagenta", "color: #8b008b" );
echo.defineStyler( "bgDarkmagenta", "background-color: #8b008b" );

echo.defineStyler( "darkolivegreen", "color: #556b2f" );
echo.defineStyler( "bgDarkolivegreen", "background-color: #556b2f" );

echo.defineStyler( "darkorange", "color: #ff8c00" );
echo.defineStyler( "bgDarkorange", "background-color: #ff8c00" );

echo.defineStyler( "darkorchid", "color: #9932cc" );
echo.defineStyler( "bgDarkorchid", "background-color: #9932cc" );

echo.defineStyler( "darkred", "color: #8b0000" );
echo.defineStyler( "bgDarkred", "background-color: #8b0000" );

echo.defineStyler( "darksalmon", "color: #e9967a" );
echo.defineStyler( "bgDarksalmon", "background-color: #e9967a" );

echo.defineStyler( "darkseagreen", "color: #8fbc8f" );
echo.defineStyler( "bgDarkseagreen", "background-color: #8fbc8f" );

echo.defineStyler( "darkslateblue", "color: #483d8b" );
echo.defineStyler( "bgDarkslateblue", "background-color: #483d8b" );

echo.defineStyler( "darkslategray", "color: #2f4f4f" );
echo.defineStyler( "bgDarkslategray", "background-color: #2f4f4f" );

echo.defineStyler( "darkslategrey", "color: #2f4f4f" );
echo.defineStyler( "bgDarkslategrey", "background-color: #2f4f4f" );

echo.defineStyler( "darkturquoise", "color: #00ced1" );
echo.defineStyler( "bgDarkturquoise", "background-color: #00ced1" );

echo.defineStyler( "darkviolet", "color: #9400d3" );
echo.defineStyler( "bgDarkviolet", "background-color: #9400d3" );

echo.defineStyler( "deeppink", "color: #ff1493" );
echo.defineStyler( "bgDeeppink", "background-color: #ff1493" );

echo.defineStyler( "deepskyblue", "color: #00bfff" );
echo.defineStyler( "bgDeepskyblue", "background-color: #00bfff" );

echo.defineStyler( "dimgray", "color: #696969" );
echo.defineStyler( "bgDimgray", "background-color: #696969" );

echo.defineStyler( "dimgrey", "color: #696969" );
echo.defineStyler( "bgDimgrey", "background-color: #696969" );

echo.defineStyler( "dodgerblue", "color: #1e90ff" );
echo.defineStyler( "bgDodgerblue", "background-color: #1e90ff" );

echo.defineStyler( "firebrick", "color: #b22222" );
echo.defineStyler( "bgFirebrick", "background-color: #b22222" );

echo.defineStyler( "floralwhite", "color: #fffaf0" );
echo.defineStyler( "bgFloralwhite", "background-color: #fffaf0" );

echo.defineStyler( "forestgreen", "color: #228b22" );
echo.defineStyler( "bgForestgreen", "background-color: #228b22" );

echo.defineStyler( "gainsboro", "color: #dcdcdc" );
echo.defineStyler( "bgGainsboro", "background-color: #dcdcdc" );

echo.defineStyler( "ghostwhite", "color: #f8f8ff" );
echo.defineStyler( "bgGhostwhite", "background-color: #f8f8ff" );

echo.defineStyler( "gold", "color: #ffd700" );
echo.defineStyler( "bgGold", "background-color: #ffd700" );

echo.defineStyler( "goldenrod", "color: #daa520" );
echo.defineStyler( "bgGoldenrod", "background-color: #daa520" );

echo.defineStyler( "greenyellow", "color: #adff2f" );
echo.defineStyler( "bgGreenyellow", "background-color: #adff2f" );

echo.defineStyler( "grey", "color: #808080" );
echo.defineStyler( "bgGrey", "background-color: #808080" );

echo.defineStyler( "honeydew", "color: #f0fff0" );
echo.defineStyler( "bgHoneydew", "background-color: #f0fff0" );

echo.defineStyler( "hotpink", "color: #ff69b4" );
echo.defineStyler( "bgHotpink", "background-color: #ff69b4" );

echo.defineStyler( "indianred", "color: #cd5c5c" );
echo.defineStyler( "bgIndianred", "background-color: #cd5c5c" );

echo.defineStyler( "indigo", "color: #4b0082" );
echo.defineStyler( "bgIndigo", "background-color: #4b0082" );

echo.defineStyler( "ivory", "color: #fffff0" );
echo.defineStyler( "bgIvory", "background-color: #fffff0" );

echo.defineStyler( "khaki", "color: #f0e68c" );
echo.defineStyler( "bgKhaki", "background-color: #f0e68c" );

echo.defineStyler( "lavender", "color: #e6e6fa" );
echo.defineStyler( "bgLavender", "background-color: #e6e6fa" );

echo.defineStyler( "lavenderblush", "color: #fff0f5" );
echo.defineStyler( "bgLavenderblush", "background-color: #fff0f5" );

echo.defineStyler( "lawngreen", "color: #7cfc00" );
echo.defineStyler( "bgLawngreen", "background-color: #7cfc00" );

echo.defineStyler( "lemonchiffon", "color: #fffacd" );
echo.defineStyler( "bgLemonchiffon", "background-color: #fffacd" );

echo.defineStyler( "lightblue", "color: #add8e6" );
echo.defineStyler( "bgLightblue", "background-color: #add8e6" );

echo.defineStyler( "lightcoral", "color: #f08080" );
echo.defineStyler( "bgLightcoral", "background-color: #f08080" );

echo.defineStyler( "lightcyan", "color: #e0ffff" );
echo.defineStyler( "bgLightcyan", "background-color: #e0ffff" );

echo.defineStyler( "lightgoldenrodyellow", "color: #fafad2" );
echo.defineStyler( "bgLightgoldenrodyellow", "background-color: #fafad2" );

echo.defineStyler( "lightgray", "color: #d3d3d3" );
echo.defineStyler( "bgLightgray", "background-color: #d3d3d3" );

echo.defineStyler( "lightgreen", "color: #90ee90" );
echo.defineStyler( "bgLightgreen", "background-color: #90ee90" );

echo.defineStyler( "lightgrey", "color: #d3d3d3" );
echo.defineStyler( "bgLightgrey", "background-color: #d3d3d3" );

echo.defineStyler( "lightpink", "color: #ffb6c1" );
echo.defineStyler( "bgLightpink", "background-color: #ffb6c1" );

echo.defineStyler( "lightsalmon", "color: #ffa07a" );
echo.defineStyler( "bgLightsalmon", "background-color: #ffa07a" );

echo.defineStyler( "lightseagreen", "color: #20b2aa" );
echo.defineStyler( "bgLightseagreen", "background-color: #20b2aa" );

echo.defineStyler( "lightskyblue", "color: #87cefa" );
echo.defineStyler( "bgLightskyblue", "background-color: #87cefa" );

echo.defineStyler( "lightslategray", "color: #778899" );
echo.defineStyler( "bgLightslategray", "background-color: #778899" );

echo.defineStyler( "lightslategrey", "color: #778899" );
echo.defineStyler( "bgLightslategrey", "background-color: #778899" );

echo.defineStyler( "lightsteelblue", "color: #b0c4de" );
echo.defineStyler( "bgLightsteelblue", "background-color: #b0c4de" );

echo.defineStyler( "lightyellow", "color: #ffffe0" );
echo.defineStyler( "bgLightyellow", "background-color: #ffffe0" );

echo.defineStyler( "limegreen", "color: #32cd32" );
echo.defineStyler( "bgLimegreen", "background-color: #32cd32" );

echo.defineStyler( "linen", "color: #faf0e6" );
echo.defineStyler( "bgLinen", "background-color: #faf0e6" );

echo.defineStyler( "magenta", "color: #ff00ff" );
echo.defineStyler( "bgMagenta", "background-color: #ff00ff" );

echo.defineStyler( "mediumaquamarine", "color: #66cdaa" );
echo.defineStyler( "bgMediumaquamarine", "background-color: #66cdaa" );

echo.defineStyler( "mediumblue", "color: #0000cd" );
echo.defineStyler( "bgMediumblue", "background-color: #0000cd" );

echo.defineStyler( "mediumorchid", "color: #ba55d3" );
echo.defineStyler( "bgMediumorchid", "background-color: #ba55d3" );

echo.defineStyler( "mediumpurple", "color: #9370db" );
echo.defineStyler( "bgMediumpurple", "background-color: #9370db" );

echo.defineStyler( "mediumseagreen", "color: #3cb371" );
echo.defineStyler( "bgMediumseagreen", "background-color: #3cb371" );

echo.defineStyler( "mediumslateblue", "color: #7b68ee" );
echo.defineStyler( "bgMediumslateblue", "background-color: #7b68ee" );

echo.defineStyler( "mediumspringgreen", "color: #00fa9a" );
echo.defineStyler( "bgMediumspringgreen", "background-color: #00fa9a" );

echo.defineStyler( "mediumturquoise", "color: #48d1cc" );
echo.defineStyler( "bgMediumturquoise", "background-color: #48d1cc" );

echo.defineStyler( "mediumvioletred", "color: #c71585" );
echo.defineStyler( "bgMediumvioletred", "background-color: #c71585" );

echo.defineStyler( "midnightblue", "color: #191970" );
echo.defineStyler( "bgMidnightblue", "background-color: #191970" );

echo.defineStyler( "mintcream", "color: #f5fffa" );
echo.defineStyler( "bgMintcream", "background-color: #f5fffa" );

echo.defineStyler( "mistyrose", "color: #ffe4e1" );
echo.defineStyler( "bgMistyrose", "background-color: #ffe4e1" );

echo.defineStyler( "moccasin", "color: #ffe4b5" );
echo.defineStyler( "bgMoccasin", "background-color: #ffe4b5" );

echo.defineStyler( "navajowhite", "color: #ffdead" );
echo.defineStyler( "bgNavajowhite", "background-color: #ffdead" );

echo.defineStyler( "oldlace", "color: #fdf5e6" );
echo.defineStyler( "bgOldlace", "background-color: #fdf5e6" );

echo.defineStyler( "olivedrab", "color: #6b8e23" );
echo.defineStyler( "bgOlivedrab", "background-color: #6b8e23" );

echo.defineStyler( "orangered", "color: #ff4500" );
echo.defineStyler( "bgOrangered", "background-color: #ff4500" );

echo.defineStyler( "orchid", "color: #da70d6" );
echo.defineStyler( "bgOrchid", "background-color: #da70d6" );

echo.defineStyler( "palegoldenrod", "color: #eee8aa" );
echo.defineStyler( "bgPalegoldenrod", "background-color: #eee8aa" );

echo.defineStyler( "palegreen", "color: #98fb98" );
echo.defineStyler( "bgPalegreen", "background-color: #98fb98" );

echo.defineStyler( "paleturquoise", "color: #afeeee" );
echo.defineStyler( "bgPaleturquoise", "background-color: #afeeee" );

echo.defineStyler( "palevioletred", "color: #db7093" );
echo.defineStyler( "bgPalevioletred", "background-color: #db7093" );

echo.defineStyler( "papayawhip", "color: #ffefd5" );
echo.defineStyler( "bgPapayawhip", "background-color: #ffefd5" );

echo.defineStyler( "peachpuff", "color: #ffdab9" );
echo.defineStyler( "bgPeachpuff", "background-color: #ffdab9" );

echo.defineStyler( "peru", "color: #cd853f" );
echo.defineStyler( "bgPeru", "background-color: #cd853f" );

echo.defineStyler( "pink", "color: #ffc0cb" );
echo.defineStyler( "bgPink", "background-color: #ffc0cb" );

echo.defineStyler( "plum", "color: #dda0dd" );
echo.defineStyler( "bgPlum", "background-color: #dda0dd" );

echo.defineStyler( "powderblue", "color: #b0e0e6" );
echo.defineStyler( "bgPowderblue", "background-color: #b0e0e6" );

echo.defineStyler( "rosybrown", "color: #bc8f8f" );
echo.defineStyler( "bgRosybrown", "background-color: #bc8f8f" );

echo.defineStyler( "royalblue", "color: #4169e1" );
echo.defineStyler( "bgRoyalblue", "background-color: #4169e1" );

echo.defineStyler( "saddlebrown", "color: #8b4513" );
echo.defineStyler( "bgSaddlebrown", "background-color: #8b4513" );

echo.defineStyler( "salmon", "color: #fa8072" );
echo.defineStyler( "bgSalmon", "background-color: #fa8072" );

echo.defineStyler( "sandybrown", "color: #f4a460" );
echo.defineStyler( "bgSandybrown", "background-color: #f4a460" );

echo.defineStyler( "seagreen", "color: #2e8b57" );
echo.defineStyler( "bgSeagreen", "background-color: #2e8b57" );

echo.defineStyler( "seashell", "color: #fff5ee" );
echo.defineStyler( "bgSeashell", "background-color: #fff5ee" );

echo.defineStyler( "sienna", "color: #a0522d" );
echo.defineStyler( "bgSienna", "background-color: #a0522d" );

echo.defineStyler( "skyblue", "color: #87ceeb" );
echo.defineStyler( "bgSkyblue", "background-color: #87ceeb" );

echo.defineStyler( "slateblue", "color: #6a5acd" );
echo.defineStyler( "bgSlateblue", "background-color: #6a5acd" );

echo.defineStyler( "slategray", "color: #708090" );
echo.defineStyler( "bgSlategray", "background-color: #708090" );

echo.defineStyler( "slategrey", "color: #708090" );
echo.defineStyler( "bgSlategrey", "background-color: #708090" );

echo.defineStyler( "snow", "color: #fffafa" );
echo.defineStyler( "bgSnow", "background-color: #fffafa" );

echo.defineStyler( "springgreen", "color: #00ff7f" );
echo.defineStyler( "bgSpringgreen", "background-color: #00ff7f" );

echo.defineStyler( "steelblue", "color: #4682b4" );
echo.defineStyler( "bgSteelblue", "background-color: #4682b4" );

echo.defineStyler( "tan", "color: #d2b48c" );
echo.defineStyler( "bgTan", "background-color: #d2b48c" );

echo.defineStyler( "thistle", "color: #d8bfd8" );
echo.defineStyler( "bgThistle", "background-color: #d8bfd8" );

echo.defineStyler( "tomato", "color: #ff6347" );
echo.defineStyler( "bgTomato", "background-color: #ff6347" );

echo.defineStyler( "turquoise", "color: #40e0d0" );
echo.defineStyler( "bgTurquoise", "background-color: #40e0d0" );

echo.defineStyler( "violet", "color: #ee82ee" );
echo.defineStyler( "bgViolet", "background-color: #ee82ee" );

echo.defineStyler( "wheat", "color: #f5deb3" );
echo.defineStyler( "bgWheat", "background-color: #f5deb3" );

echo.defineStyler( "whitesmoke", "color: #f5f5f5" );
echo.defineStyler( "bgWhitesmoke", "background-color: #f5f5f5" );

echo.defineStyler( "yellowgreen", "color: #9acd32" );
echo.defineStyler( "bgYellowgreen", "background-color: #9acd32" );

echo.defineStyler( "rebeccapurple", "color: #663399" );
echo.defineStyler( "bgRebeccapurple", "background-color: #663399" );

Want to use code from this post? Check out the license.

Reader Comments

15,848 Comments

@All,

As a follow-up, I wanted to see if I could package my echo library up and inject it as a Chrome browser extension:

www.bennadel.com/blog/3945-attempting-to-inject-my-echo-log-css-styled-logger-as-a-chrome-extension.htm

I've never tried building a browser extension before; and, ironically, the one that I need to do - modify the window object - is the one thing that a browser extension really doesn't want you to do :D But, I was able to get an MVP working using a programmatically-injected Script tag.

15,848 Comments

@Danny,

Oh, that's an interesting idea. My one concern, though, with overriding the default console.log() functionality is that it actually functions a bit differently in terms of how it implements the string interpolation. Whereas echo can have variadic arguments (multiple styles arguments), console can only do that for the first argument, using 2..N arguments specifically for the styling and interpolation.

Trying to wedge the new functionality into the console might not be quite as "drop in replacement" as I would like. But, it would also make things a bit more "obvious" -- and, to your point, might get automatically stripped-out by a compiler so I don't accidentally ship to production :D

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel