I have a very handy, very small CSS Snippet that I use to debug CSS whenever the browser starts starts misbehaving. I figure I’d share with you, in case you, too, needed such a snippet.
The Outlining Snippet
Unlike border, the outline property does not and will never contribute to layout. Not only that, outlines aren’t necessarily rectangular. So what I do is keep a debug class whose job it is to draw outlines around it, and all of its children.
I find this helpful when I’m trying to figure out how big an element is.
/*For the element I'm debugging */
.isDebugging .debug {
outline: 1px solid rgb(200, 100, 50);
}
/*For all of that element's children*/
.isDebugging .debug * {
outline: 1px solid rgb(200, 100, 50);
}
The Backgrounding Snippet
This is my favorite snippet for seeing how many nested things are in a space. I set the background color using some opacity. As we get more nested elements, backgrounds become more opaque.
I find this helpful when I’m trying to figure out how elements are nested inside of each other.
.isDebugging .debug-bg {
outline: 1px solid rgba(200, 100, 50, 0.9);
background: rgba(200, 100, 50, 0.1);
}
.isDebugging .debug-bg * {
background: rgba(200, 100, 50, 0.1);
}
Protect the CSS with some JS
To Err is human, to forgive [shipping to production] is divine
Shakespeare and Frank, Frankspeare if you will
I want to avoid my debugging CSS making it to production at all costs. So what I also keep around for my projects is some JavaScript that turns on debugging. Something that adds a class name to the body. This means that even if a Pull Request doesn’t catch my debug class sitting on an element, and even if our automated tests don’t spot it, it still can’t do any harm because I have to intentionally turn it on.
As a bonus, this means that if something does make it to production, I have the ability to insert this classname with a few inconspicuous keystrokes.
/**
* @class Debug
* @classdesc A small utility for debugging.
*
*/
class Debug {
constructor() {
this.init();
}
/**
* determines if debugging has been unlocked from sessionStorage
* @type {boolean}
*/
get isUnlocked() {
const storageItem = sessionStorage.getItem('isDebugging');
return storageItem === 'true';
}
/** logs an optionally styled message in the console
* @method
* @param {string} message message to be sent to the console
* @param {string} [styles=''] CSS styles to be added to the message
*/
static logMessage(message, styles = '') {
console.log(`${styles && '%c'} ${message}`, styles || ' ');
}
/**
* "unlocks" debugging by adding a classname and putting value in sessionStorage
* @method
* @static
*/
static unlock() {
document.body.classList.add('isDebugging');
sessionStorage.setItem('isDebugging', 'true');
Debug.logMessage('debugging unlocked');
}
/**
* binds any events used by debugging
* This includes event listener that checks for keystrokes
* @method
* @static
*/
static bindEvents() {
// up up down down left right left right b a
const keys = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
let keysIndex = 0;
const keydownTracker = (event) => {
const nextKey = keys[keysIndex++];
if (event.keyCode === nextKey) {
if (keysIndex === keys.length) {
document.removeEventListener('keydown', keydownTracker);
Debug.unlock();
}
}
};
document.body.addEventListener('keydown', keydownTracker);
}
/**
* Initializes the module
*/
init() {
if (this.isUnlocked) {
Debug.unlock();
}
Debug.logMessage('Debugger available', 'color: #ef8c23');
Debug.bindEvents();
}
};
You may notice that my debugger comes with its own logMessage. This is handy from the JavaScript side because it means I can make my debugging console statements obvious— and therefore easier to spot.
So, with all of this I can use my debugger withconst debugger = new Debug();
Try it out
Type ↑ ↑ ↓ ↓ ← → ← → b a anywhere on the page, and you’ll be able to debug this post.
This is also a gist complete with Sass mixin, if that’s your thing.