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.
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.
language_attributes to set other attributes in the <html> tag is 'best practice'. As a matter of fact, the article states that the two acceptable parameters to the function are 'xhtml' and 'html', which supports my contention that this is a bit hacky. Anyway, if it works without detrimental side effects and it's the only way, I'll probably go with it.
functions.php file, or 2) place the code in a site-specific Plugin.
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.
/**
* 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);
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";
}
<html>element (see edited question). Also, I need to add it via PHP. "no-js" stands for "No Javascript", so using javascript to set that class is not an option.