Optimizing Jetpack Custom CSS

Jetpack adds a lot of features and performance options to self-hosted WordPress sites, along with it’s own built-in CSS styling. Most of this styling is fairly universal, but some of the top/bottom margins and other elements don’t always blend smoothly with existing site styling. Adding Jetpack-specific styling to an existing stylesheet is fine, but it can be a bit bloated and unneeded if Jetpack isn’t installed on a site. The method below optimizes a custom Jetpack CSS stylesheet to only load if Jetpack is installed and active.

First register and enqueue a CSS file specifically for Jetpack in the theme’s functions.php file using the code below. Note that this conditionally enqueues the CSS file only if Jetpack is active.

<?php
// register optimized styles 
function evo_register_optimized_styles() {
    wp_register_style( 'jetpack-optimized', get_template_directory_uri() . '/assets/css/jetpack.css' );
}
add_action('init', 'evo_register_optimized_styles');
// enqueue optimized styles 
function evo_enqueue_optimized_styles() {
    if ( in_array( 'jetpack/jetpack.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
		wp_enqueue_style( 'jetpack-optimized' );
	}
}
add_action( 'wp_enqueue_scripts', 'evo_enqueue_optimized_styles' );

Then create a jetpack.css file in the directory as registered in the function above. Below is a basic example of some Jetpack-specific custom CSS.

*[class^="wp-block-jetpack-"] {
	margin-top: 2rem !important;
	margin-bottom: 2rem !important;
}
.wp-block-jetpack-slideshow {
	margin-bottom: calc(2rem - 36px) !important;
}
*[class^="wp-block-jetpack-"] *[class^="wp-block-jetpack-"],
*[class^="wp-block-"] *[class^="wp-block-jetpack-"],
.wp-block-jetpack-markdown {
	margin-top: initial !important;
	margin-bottom: initial !important;
}
.wp-block-jetpack-contact-info *[class^="wp-block-jetpack-"] {
	margin-bottom: 0.5rem !important;
}
.sharedaddy {
	padding-top: 0.75rem !important;
}
.jetpack-likes-widget-wrapper iframe {
	margin-top: 0.5rem !important;
}
.sd-title {
	margin-bottom: 0 !important;
}
.sd-content ul li {
	line-height: 0 !important;
	margin-right: 0.25rem !important;
}
.jetpack-comment-likes-widget-wrapper {
	margin-bottom: 0.25rem;
}
.jetpack-comment-likes-widget-wrapper iframe {
	background: #f8f8f8;
	border: 1px solid #cccccc;
	box-shadow: 0 1px 0 rgba(0,0,0,.08);
	border-radius: 3px;
	height: 26px;
	width: 62px;
	margin-top: 3px;
    padding: 1px 0 0 5px;
}
.jetpack-comment-likes-widget-wrapper span.comment-like-feedback {
	display: block;
	font-size: 11px;
}
View Post

Optimizing Comments in WordPress

Comments are a versatile feature for allowing discussions on posts and pages in WordPress. I currently don’t have comments open on my blog posts, but I want my themes to support them dynamically. The method below optimizes comments to conditionally display and enqueue styles on posts/pages only when comments are open or exist.

First add or update the theme support for comments in the theme’s functions.php file, within the after_setup_theme hook, with the code below.

add_theme_support( 'html5', array(
	'search-form',
	'comment-form', // support for the comment form
	'comment-list', // support for the comment list
	'gallery',
	'caption',
	'script',
	'style',
) );

Then register and enqueue a CSS file specifically for the comments in the theme’s functions.php file using the code below. Note that this conditionally enqueues the CSS file on each post/page only if comments are open, or if comments exist after comments are closed.

<?php
// register optimized styles 
function evo_register_optimized_styles() {
    wp_register_style( 'comments-optimized', get_template_directory_uri() . '/assets/css/comments.css' );
}
add_action('init', 'evo_register_optimized_styles');
// enqueue optimized styles 
function evo_enqueue_optimized_styles() {
    if ( is_singular() && comments_open() || is_singular() && get_comments_number() ) {
        wp_enqueue_style( 'comments-optimized' );
    }
}
add_action( 'wp_enqueue_scripts', 'evo_enqueue_optimized_styles' );

Then create a comments.css file in the directory as registered in the function above. A simplified example of the CSS uses the styles below.

.comments-area {
	margin: 2rem 0;
}
.comment-body {
	margin: 1.5rem 0;
}
.comment-metadata,
.comment-reply-link,
.comment-notes,
.logged-in-as {
	font-size: 0.875rem;
}
.comment-author .avatar {
	border-radius: 18px;
}
.children {
	margin-left: 3rem;
}
.comment-form label {
	display: block;
}

Then create a comments.php file in root theme directory like the example below. Note that this conditionally displays the comments section to each post/page only if comments are open, or if comments exist after comments are closed.

<?php if ( comments_open() || get_comments_number() ) { ?>
<?php if ( post_password_required() ) { return; } ?>
<div id="comments" class="comments-area">
	<?php if ( have_comments() ) : ?>
		<h3 class="comments-title">
			<?php comments_number( 'No Comments', 'One Comment', '% Comments' ); ?>
		</h3>
		<ol class="comment-list">
			<?php wp_list_comments( array( 'style' => 'ol', 'avatar_size' => 36, ) ); ?>
		</ol>
		<?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : ?>
			<nav class="comment-navigation">
				<h5><?php previous_comments_link( 'Older Comments ❯' ); ?></h5>
				<h5><?php next_comments_link( '❮ Newer Comments' ); ?></h5>
			</nav>
		<?php endif; ?>
		<?php if ( ! comments_open() && get_comments_number() ) : ?>
			<h4 class="no-comments"><?php _e( 'Comments are closed.' ); ?></h4>
		<?php endif; ?>
	<?php endif; ?>
	<?php comment_form(); ?>
</div>
<?php } ?>

Finally, add comments in the loop on single/page PHP files with the standard template tag below, typically at the bottom of the main content area.

<?php comments_template(); ?>
View Post

Optimizing the WordPress Head Tag Section

The initial WordPress head tag section is a bit bloated. There are some quick optimizations via the functions.php file that will improve a WordPress site’s loading time and increase security. The key elements the method below addresses:

• Remove Query Strings from Static Resources – This can improve caching and fix some speed test warnings – Note that this can break how some external resources load (ex: enqueuing a Google Fonts CSS link)

• Header Cleanup – This removes all the unnecessary tags: RSD link, WordPress version number (increasing site’s security), wlwmanifest link, shortlink, and extra feed links (primary RSS feed still functions correctly)

• Disable the Emojis – This removes the emoji support WordPress has built-in for older browsers that isn’t needed for modern browsers

// Remove query strings from static resources 
function _remove_script_version( $src ) {
	$parts = explode( '?', $src );
	return $parts[0];
}
add_filter( 'script_loader_src', '_remove_script_version', 15, 1 );
add_filter( 'style_loader_src', '_remove_script_version', 15, 1 );

// Header cleanup 
add_action( 'do_feed_rss2_comments', 'disable_feeds', -1 );
add_action( 'do_feed_atom_comments', 'disable_feeds', -1 );
add_action( 'feed_links_show_comments_feed', '__return_false', -1 );
remove_action( 'wp_head', 'feed_links_extra', 3 );
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wp_generator' );
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );

// Disable the emojis 
function disable_emojis() {
	remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
	remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
	remove_action( 'wp_print_styles', 'print_emoji_styles' );
	remove_action( 'admin_print_styles', 'print_emoji_styles' ); 
	remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
	remove_filter( 'comment_text_rss', 'wp_staticize_emoji' ); 
	remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
	add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
	add_filter( 'wp_resource_hints', 'disable_emojis_remove_dns_prefetch', 10, 2 );
}
add_action( 'init', 'disable_emojis' );
function disable_emojis_tinymce( $plugins ) {
	if ( is_array( $plugins ) ) {
		return array_diff( $plugins, array( 'wpemoji' ) );
	} else {
		return array();
	}
}
function disable_emojis_remove_dns_prefetch( $urls, $relation_type ) {
	if ( 'dns-prefetch' == $relation_type ) {
		$emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/' );
		$urls = array_diff( $urls, array( $emoji_svg_url ) );
	}
	return $urls;
}
View Post

Optimizing Sites with the .htaccess File

Slow websites suck. Luckily, there are some quick optimizations via the .htaccess file that will improve a site’s loading time and boost your speed score. This is a good opportunity to increase the site’s security too. The key elements the method below addresses:

• Force HTTPS – This requires that you have an active SSL Certificate on your domain (Let’s Encrypt is a good free option) and forces all requests to use HTTPS for stronger encryption

• Accept-Encoding – This tells the browser whether or not the client can handle compressed versions of the content

• Expires Caching – This sets the time duration files will stay cached on visitor’s browsers, so when they revisit the site it loads much faster

• Gzip Compression – This compresses the website files reducing the overall size of the site

# FORCE HTTPS
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# ACCEPT-ENCODING
<IfModule mod_headers.c>
<FilesMatch ".(js|css|xml|png|gz|html|woff2|slim.min.js)$">
Header append Vary: Accept-Encoding
</FilesMatch>
</IfModule>

# EXPIRES CACHING
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 90 days"
ExpiresByType image/jpeg "access plus 90 days"
ExpiresByType image/gif "access plus 90 days"
ExpiresByType image/png "access plus 90 days"
ExpiresByType image/svg "access plus 90 days"
ExpiresByType image/x-icon "access plus 90 days"
ExpiresByType video/mp4 "access plus 90 days"
ExpiresByType video/mpeg "access plus 90 days"
ExpiresByType text/css "access plus 1 week"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/pdf "access plus 90 days"
ExpiresDefault "access plus 1 week"
</IfModule>

# GZIP COMPRESSION
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
</IfModule>

View Post