Modernizr and WordPress – How can I add a CSS class to the html element?

The instructions for implementing Modernizr state that I should add class="no-js" to the <html> element.

Is there a way to do this in WordPress using a hook or filter? If at all possible, I’d prefer to do this without editing the theme files.

Solutions Collecting From Web of "Modernizr and WordPress – How can I add a CSS class to the html element?"

This is not exactly the answer, but you can use a hook for language_attributes filter. This action is fired at <html> tag and what it does is simply echo the lang=en string, for ex. You can hook to that and replace the string with your CSS class, like this:

add_filter('language_attributes', 'modernizr');
function modernizr($output) {
    return $output . ' class="no-js"';
}

This works only when your theme follows the WordPress Theme Development Checklist. Sometimes people don’t follow this and that breaks the technique.

A little late to the game here, but just to add to @Rilwis answer you could add the script to a function that checks if the no-js language attributes are added or not.

While I don’t use Modernizr, I do use the no-js detection script from twenty-sixteen so inclusion is pretty much the same. Doing it this way, you don’t have to worry about removing the function added to wp_head or wp_enqueue_scripts since it happens automatically when you remove the filter.

Adding Removing Filter Approach

/** 
 * Javascript Detection Filter
 * 
 * remove_filter( 'language_attributes', 'lang_atts_js_detect' ); 
 */ 
add_filter( 'language_attributes', 'lang_atts_js_detect' );
function lang_atts_js_detect($output) {
    return $output . ' class="no-js"';
}
add_action( 'wp_head', function() {
    if ( has_filter( 'language_attributes', 'lang_atts_js_detect' ) ) {
        echo "<script>(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);</script>\n";
    }
}, 0);

Theme Support Approach

Another option could be to do this using current_theme_supports.

/** 
 * Javascript Detection Theme Support
 * 
 * add_theme_support( 'js-detect' ); 
 */ 
add_action( 'init', function() {
    if ( current_theme_supports( 'js-detect' ) && !is_admin() )
        add_filter( 'language_attributes', 'lang_atts_js_detect_class' );
        add_action( 'wp_head', 'lang_atts_js_detect_script', 0 );
}
function lang_atts_js_detect_class($output) {
    return $output . ' class="no-js"';
}
function lang_atts_js_detect_script() {
    echo "<script>(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);</script>\n";
}