David Walsh Blog

5 Ways that CSS and JavaScript Interact That You May Not Know About

CSS and JavaScript:  the lines seemingly get blurred by each browser release.  They have always done a very different job but in the end they are both front-end technologies so they need do need to work closely.  We have our .js files and our .css, but that doesn’t mean that CSS and JS can’t interact more closely than the basic JavaScript frameworks will allow.  Here are five ways that JavaScript and CSS work together that you may not know about!

Get Pseudo-Element Properties with JavaScript

We know that we can get basic CSS style values for an element with the style property, but what about pseudo-element properties?  Yes, JavaScript can even access those too!


// Get the color value of .element:before
var color = window.getComputedStyle(
	document.querySelector('.element'), ':before'
).getPropertyValue('color');

// Get the content value of .element:before
var content = window.getComputedStyle(
	document.querySelector('.element'), ':before'
).getPropertyValue('content');

You can see how I access the content property value in my blog post about Device State Detection.  Incredibly useful if you’re looking to create dynamic, unique sites!

classList API

We’ve all used the addClass, removeClass, and toggleClass methods in our favorite JavaScript libraries.  For the sake of supporting older browsers, each library would grab the element’s className (in its string format) and appending/removing the class, then updates the className string.  There’s a newer API for adding, removing, and toggling classes, and it’s called classList:


myDiv.classList.add('myCssClass'); // Adds a class

myDiv.classList.remove('myCssClass'); // Removes a class

myDiv.classList.toggle('myCssClass'); // Toggles a class

classList has been implemented for a long time in most browsers, but this API hit IE at version 10.

Add and Remove Rules Directly to Stylesheets

We’re all well versed in modifying styles via the element.style.propertyName method, and we’ve used JavaScript toolkits to do it, but did you know you can actually read and write rules within new and existing stylesheets?  The API is actually quite simple too!


function addCSSRule(sheet, selector, rules, index) {
	if(sheet.insertRule) {
		sheet.insertRule(selector + "{" + rules + "}", index);
	}
	else {
		sheet.addRule(selector, rules, index);
	}
}

// Use it!
addCSSRule(document.styleSheets[0], "header", "float: left");

The most common use case is creating a new stylesheet, but if you want to modify an existing stylesheet, go for it.

Load CSS Files with a Loader

Lazy-loading resources like images, JSON, and scripts is a great way to decrease load time.  We can load those external resources with JavaScript loaders like curl.js, but did you know you can lazy load stylesheets and get that notification within the same callback?


curl(
	[
		"namespace/MyWidget",
		"css!namespace/resources/MyWidget.css"
	], 
	function(MyWidget) {
		// Do something with MyWidget
		// The CSS reference isn't in the signature because we don't care about it;
		// we just care that it is now in the page
	}
});

This blog lazy loads PrismJS, the syntax highlighter, based on the presence of pre elements.  Once all resources are loaded, including the stylesheet, I can fire off a callback.  Useful!

CSS pointer-events

CSS’ pointer-events property is interesting in that it almost acts in a JavaScript-like way, effectively disabling an element when the value is none but otherwise allowing the element to function per usual when the value isn’t none.  You may be saying “so what?!” but pointer-events even prevent JavaScript events from firing!


.disabled { pointer-events: none; }

Click on that element and any addEventListener callback you’ve placed on the element will not fire.  A perfect property, really — you don’t need to do a className check before you decide whether or not to fire something based on class presence.

Those are just five ways that CSS and JavaScript interact that you don’t always think of.  Have more ideas?  Please share them!