Skip to main contentSkip to footer

Relevanssi can highlight search terms on the posts. But how about scrolling the page to show the location where the search results are? That is also possible.

It requires a bit of JavaScript on the post page.

This script needs to run on the post page:

<script>
jQuery(document).ready(function($) {
	$.extend($.expr[":"], {
		"containsNC": function(elem, i, match, array) {
			return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
		}
	});

	var mySearchString = getParams("highlight");
	var offsetToWord = $("p:containsNC('" +mySearchString + "'):first").offset().top;
	
	$("html, body").animate({ scrollTop: offsetToWord }, 0);
	
	function getParams(param) {
		var vars = {};
		window.location.href.replace( location.hash, '' ).replace( 
			/[?&]+([^=&]+)=?([^&]*)?/gi, // regexp
			function( m, key, value ) { // callback
				vars[key] = value !== undefined ? value : '';
			}
		);
		return vars[param];
	}
});
</script>

The easiest way is to just add this to the single post template, but the right way is to use wp_enqueue_script(). Now the post page will automatically scroll to the location of the search term, taken from the “highlight” query parameter. The scroll is instant; if you want to make it slower, increase the 0 in $("html, body").animate({ scrollTop: offsetToWord }, 0); to 1000 or 2000 to get a slower animation.

Now all you need is the search term in the highlight parameter. On your search results template, you likely have something like this:

<a href="<?php the_permalink(); ?>"><!--?php _e( 'Read More', 'total' ); ?--></a>

Change it to this to append the search query to the URL:

<a href="<?php if (function_exists('relevanssi_the_permalink')) { relevanssi_the_permalink(); } else { the_permalink(); } ?>"><!--?php _e( 'Read More', 'total' ); ?--></a>

This is a fairly brutal method and probably lacks all sorts of necessary finesse, but it’s a start. Note that this only works when the whole search query is found somewhere on the page; it looks for the whole phrase, not individual words.

Another method

For a simpler and more reliable approach, make sure the in-document highlighting is enabled and set it to use something distinct, like that <mark> tag or a specific CSS classname. Then you can use this script to jump to the first occurrance of the highlighting:

<script>
jQuery(document).ready(function($) {
    var offset = $('mark').first().offset().top // for <mark> tags
    var offset = $('.classname').first().offset().top // for CSS class name
    $("html, body").animate({ scrollTop: offset }, 100);
})
</script>