Preface#
While browsing the Bu Yi Le Hu Blog, I was deeply attracted by the style of the reader wall on its message page. Additionally, I also saw a unique style on the wys friendly link page, which made me eager to try it out. So, I started searching online for related information and accidentally discovered a plugin previously written by Zhang Ge Blog. Although this plugin is no longer applicable due to its age, I decided to modify its code and implement it on my own blog.
Steps#
- Add code to functions.php
First, find and open the functions.php file in your blog's theme directory. Then, add the following code to the end of the file:
// Register and load the CSS style for the readers wall
function enqueue_readers_wall_styles() {
global $post;
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'readers_wall')) {
wp_enqueue_style('readers-wall-style', get_template_directory_uri() . '/css/readers-wall.css', array(), '1.0.0');
}
}
add_action('wp_enqueue_scripts', 'enqueue_readers_wall_styles');
// Helper function: Generate ranking list
function generate_readers_list($title, $query, $limit) {
global $wpdb;
$output = '';
// Use transient cache for query results
$transient_key = 'readers_wall_' . md5($query);
$wall = get_transient($transient_key);
if (false === $wall) {
$wall = $wpdb->get_results($query);
set_transient($transient_key, $wall, 3600);
}
$output .= '<div class="readers-section">';
$output .= '<h2 class="entry-title">' . esc_html($title) . ' TOP' . esc_html($limit) . '</h2>';
if ($wall) {
$output .= "<ul class='readers-list'>";
foreach ($wall as $comment) {
$avatar = get_avatar($comment->comment_author_email, 64, '', '', array('loading' => 'lazy'));
$url = esc_url($comment->comment_author_url ? $comment->comment_author_url : "#");
$author = esc_html($comment->comment_author);
$count = intval($comment->cnt);
// Use author name instead of email as tooltip ID
$tooltip_id = sanitize_title($author);
$tooltip = "{$author}<br>Number of comments: {$count}";
$output .= "<li>
<a rel='friend' target='_blank' href='{$url}' aria-describedby='tooltip-{$tooltip_id}'>
{$avatar}
<div class='tooltip' id='tooltip-{$tooltip_id}' role='tooltip'>{$tooltip}</div>
</a>
</li>";
}
$output .= "</ul>";
} else {
$output .= "<p>No data found for " . esc_html($title) . ".</p>";
}
$output .= '</div>';
return $output;
}
// Shortcode function: Readers wall
function readers_wall_shortcode() {
global $wpdb;
$output = '';
// Overall comment ranking
$query2 = $wpdb->prepare(
"SELECT COUNT(comment_ID) AS cnt, comment_author, comment_author_url, comment_author_email
FROM $wpdb->comments
LEFT JOIN $wpdb->posts ON ($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
WHERE post_password = ''
AND comment_approved = '1'
AND comment_author != %s
GROUP BY comment_author_email
ORDER BY cnt DESC
LIMIT %d",
'Mr. Duan',
12
);
$output .= generate_readers_list('Overall Comment Ranking', $query2, 12);
// Annual comment ranking
$query1 = $wpdb->prepare(
"SELECT COUNT(comment_ID) AS cnt, comment_author, comment_author_url, comment_author_email
FROM (
SELECT * FROM $wpdb->comments
LEFT JOIN $wpdb->posts ON ($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
WHERE comment_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 YEAR) AND NOW()
AND post_password = ''
AND comment_approved = '1'
AND comment_author != %s
) AS tempcmt
GROUP BY comment_author_email
ORDER BY cnt DESC
LIMIT %d",
'Mr. Duan',
365
);
$output .= generate_readers_list('Annual Comment Ranking', $query1, 365);
// Monthly comment ranking
$query2 = $wpdb->prepare(
"SELECT COUNT(comment_ID) AS cnt, comment_author, comment_author_url, comment_author_email
FROM (
SELECT * FROM $wpdb->comments
LEFT JOIN $wpdb->posts ON ($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
WHERE DATE_FORMAT(comment_date, '%%Y-%%m') = DATE_FORMAT(NOW(), '%%Y-%%m')
AND post_password = ''
AND comment_approved = '1'
AND comment_author != %s
) AS tempcmt
GROUP BY comment_author_email
ORDER BY cnt DESC
LIMIT %d",
'Mr. Duan',
31
);
$output .= generate_readers_list('Monthly Comment Ranking', $query2, 31);
// Weekly comment ranking
$query3 = $wpdb->prepare(
"SELECT COUNT(comment_ID) AS cnt, comment_author, comment_author_url, comment_author_email
FROM (
SELECT * FROM $wpdb->comments
LEFT JOIN $wpdb->posts ON ($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
WHERE YEARWEEK(DATE_FORMAT(comment_date, '%%Y-%%m-%%d')) = YEARWEEK(NOW())
AND post_password = ''
AND comment_approved = '1'
AND comment_author != %s
) AS tempcmt
GROUP BY comment_author_email
ORDER BY cnt DESC
LIMIT %d",
'Mr. Duan',
7
);
$output .= generate_readers_list('Weekly Comment Ranking', $query3, 7);
return $output;
}
add_shortcode('readers_wall', 'readers_wall_shortcode');
- Create CSS file
In your theme directory, find the css folder and create a new file named readers-wall.css. Paste the following style code into that file:
/* readers-wall.css */
/* Container styles */
.readers-section {
margin-bottom: 30px;
}
.readers-section h2.entry-title {
font-size: 24px;
margin-bottom: 15px;
color: #333;
}
/* Avatar list styles */
.readers-list {
display: flex;
flex-wrap: wrap;
list-style: none;
padding: 0;
margin: 0;
}
.readers-list li {
position: relative;
margin: 10px;
width: 50px; /* Adjust avatar size */
height: 50px;
}
.readers-list li a {
display: block;
width: 100%;
height: 100%;
text-align: center;
text-decoration: none;
position: relative;
}
.readers-list li img {
width: 100%;
height: 100%;
border-radius: 50%;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.readers-list li a:hover img,
.readers-list li a:focus img {
transform: scale(1.1);
}
/* Hover information box styles */
.readers-list li .tooltip {
visibility: hidden;
opacity: 0;
width: 160px;
background-color: rgba(0, 0, 0, 0.75);
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px;
position: absolute;
bottom: 60px; /* Above the avatar */
left: 50%;
transform: translateX(-50%);
transition: opacity 0.3s ease;
z-index: 10;
font-size: 14px;
}
.readers-list li .tooltip::after {
content: "";
position: absolute;
top: 100%; /* Arrow pointing to the avatar */
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.75) transparent transparent transparent;
}
.readers-list li:hover .tooltip,
.readers-list li a:focus .tooltip {
visibility: visible;
opacity: 1;
}
/* Responsive design */
@media (max-width: 600px) {
.readers-list li {
width: 40px;
height: 40px;
}
.readers-section h2.entry-title {
font-size: 20px;
}
.readers-list li .tooltip {
width: 140px;
font-size: 12px;
}
}
- Create a page and insert shortcode
In your WordPress backend, create a new page or edit an existing page, and insert the following shortcode:
readers_wall
Conclusion#
The above is the process I followed to implement a custom readers wall feature on my personal blog. If you wish to adjust the styles according to your needs, feel free to modify the CSS code in readers-wall.css.