Last updated September 8th, 2023 at 12:07 pm
I’m currently working on a Web site that offers online courses. I’m using the MemberPress Membership Plugin to restrict course content to registered members, and I’m using MemberPress’ Courses LMS addon for developing the course curriculums.
In the future, I may publish a full review of MemberPress and MemberPress Courses (hint: it will be positive). For now, however, I just want to share one small but nagging problem I encountered with Courses and how I solved it.
The Problem/My Goal:
Icons which appear in front of lesson names (both in the main body of the page and in the lesson navigation sidebar) are all the same: little document graphics. What I wanted — partly because I’ve seen and like this in online courses I have taken — is for different icons to appear for different kinds of lessons.
I want custom lesson icons.
If the lesson includes a video, I want an icon representing a video to appear. If the lesson includes downloadable assets, I want an icon representing downloads (like a paper clip) to appear. If the lesson includes a quiz, I want an appropriate icon to appear. And so on.
Here’s what I was getting by default (click to enlarge):

Close-up of Default Icons:

More before images here (click to enlarge):
Here’s my goal (click to enlarge):

Close-up of Custom Lesson Icons:

More images showing custom lesson icons here (click to enlarge):
My idea was that if I could assign categories or tags to Lessons (which one can do with Courses), I could then use theme customizations and custom CSS to display the icons I wanted.
Good idea. But I quickly discovered that there were two major challenges I had to overcome to achieve my goal:
- By default, MemberPress Lessons (CPT
mpcs-lesson
do not have taxonomies registered to them. (MemberPress Courses do support Course Categories and Course Tags.) - The MemberPress Courses theme (“Classroom Mode”) is not lesson-taxonomy-aware, which makes sense since MemberPress Lessons don’t support taxonomies.
Solution Overview – Using Custom Lesson Icons:
The solution required several tasks and involved several tools:
Tasks:
- Register a custom taxonomy for lessons (I wanted tags)
- Create an admin interface for assiging lesson tags to lessons
- Create a function for adding appropriate lesson-tag names to the
body
class - Override and customize the default MemberPress Courses template that generates the sidebar lesson navigation
- Include Fontawesome
- Create appropriate CSS rules
Tools:
These are the tools that helped me achieve my goal.
Solution Details – Custom Lesson Icons:
Step 1:Register the taxonomy.
By default, MemberPress Lessons cannot have taxonomies assigned to them. This step will fix that “problem”.
Here’s the code, which I added to the functions.php
file in my mu-plugins
folder.
function fto_tax_lesson_tags() { $labels = array( ` 'name' => 'Lesson Tags', 'singular_name' => 'Lesson Tag', 'menu_name' => 'Lesson Tags', 'all_items' => 'All Lesson Tags', 'parent_item' => 'Parent Item', 'parent_item_colon' => 'Parent Item:', 'new_item_name' => 'New Lesson Tag', 'add_new_item' => 'Add New Lesson Tag', 'edit_item' => 'Edit Lesson Tag', 'update_item' => 'Update Lesson Tag', 'view_item' => 'View Lesson Tag', 'separate_items_with_commas' => 'Separate items with commas', 'add_or_remove_items' => 'Add or remove Lesson Tags', 'choose_from_most_used' => 'Choose from the most used', 'popular_items' => 'Popular Lesson Tags', 'search_items' => 'Search Lesson Tag', 'not_found' => 'Not Found', 'no_terms' => 'No items', 'items_list' => 'Lesson Tags list', 'items_list_navigation' => 'Lesson Tags list navigation', `); $args = array( 'labels' => $labels, 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_admin_column' => true, 'show_in_nav_menus' => true, 'show_tagcloud' => true, ); register_taxonomy( 'lesson_tags', array( 'mpcs-lesson' ), $args ); } add_action( 'init', 'fto_tax_lesson_tags', 0 );
Step 2:Create Admin Interface for Lessons
The default MemberPress Courses admin interface requires the block editor for adding Lesson content. And since MemberPress Courses addon does not natively support custom taxonomies for Lessons, I knew that I wouldn’t be able to assign lesson tags to lessons using that default interface — and I had no interest in hacking the code to make it possible.
Also, truth be told, I still prefer the Classic Editor for some editing purposes, especially course lessons.
Using the Admin Menu Editor plugin, I was able to add a custom menu to the WordPress dashboard, effectively adding a new browse screen for Lessons.
Here’s the URL for the new menu:
edit.php?post_type=mpcs-lesson.
Now that I could browse Lessons like any other post, I wanted to simplify the process of adding lesson tags to lessons. Using the Admin Columns Pro plugin, I was able to add a columm for Lesson Tags to the browse screen, which allowed me to inline-edit each lesson and add the Lesson Tags. Going a step further, I enabled the Bulk Editing feature of Admin Columns Pro so that I could assign lesson tags to multiple lessons at one time.
Step 3:Add Lesson Tag(s) to body class.
So let’s recap what’s already been done:
- I’ve registered lesson tags for MemberPress Lessons.
This allows me to assign tags to lessons. - I’ve created an admin interface for assigning lesson tags to lessons.
That is, “Lessons” now shows up as a MemberPress sub-menu, and I can browse lessons just like I can browse so many other post types. This means I can use “Quick Edit” to assign tags. Also, thanks to Admin Columns Pro, I can bulk edit lessons and add a tag to many at one time.
Now what I need to do is customize WordPress so that the class attribute of the body element includes the slug of each lesson tag assigned in step 2. This will enable me to use CSS rules to target lesson content based on each lesson’s lesson tag(s).
Here is an example of what the body element for a lesson with the tag “Script” looks like when viewing source. Line 3 is the class name I need. (I added line breaks and removed some class values for simplicity.)
<body class="mpcs-lesson-template-default single single-mpcs-lesson postid-1455 lesson-tag-script this-post-type_mpcs-lesson">
Here’s the code to accomplish my objective:
add_action('after_setup_theme', 'nwb_add_tax_to_single_action'); function nwb_add_tax_to_single_action($classes) { add_filter('body_class','nwb_add_tax_to_single'); function nwb_add_tax_to_single($classes) { $this_post_type = get_post_type(get_the_ID()); $post_type_cos = 'this-post-type_' . $this_post_type; if ( is_single() ) { global $post; $taxonomy_terms = get_the_terms($post->ID, 'lesson_tags'); // change to your taxonomy if ( $taxonomy_terms ) { foreach((get_the_terms($post->ID, 'lesson_tags')) as $term) { // *** Add category slug to the $classes array $classes[] = 'lesson-tag-' . $term->slug; } } $classes[] = $post_type_cos; // *** return the $classes array return $classes; } } }
Notice that on Line 13 I prepended ‘lesson-tag-‘ to the lesson tag slug, just to make it unique.
Step 4:Customize MemberPress Course template.
Everything I’ve done to this point is well and good.
However, the default MemberPress Courses template won’t work out of the box.
This step requires overriding a default MemberPress Courses template in order for the sidebar lesson navigation to display custom lesson icons based on lesson tags.
(Here is the official documentation for the basic steps for overriding MemberPress template files. And here is an article I published in September which attempts to simplify the instructions while also pointing out a gotcha that I encountered when following the official documentation.)
The template files I needed to override was courses_classroom_section_lessons.php
which is located in the /{child_theme}/memberpress/courses/
folder.
Here is what I added right after the foreach loop on line #13 of courses_classroom_section_lessons.php
:
$lesson_tags = get_the_terms($lesson->ID, 'lesson_tags'); if (is_array($lesson_tags) || is_object($lesson_tags) ) { $tag_classes = array(); foreach( $lesson_tags as $term ) { // *** Add category slug to the $classes array $tag_classes[] = 'lesson-tag-' . $term->slug; } $tag_classes_cos = ' ' . implode(' ', $tag_classes); } else { $tag_classes_cos = ''; }
I prepended the string lesson-tag- to the actual slug for the lesson tag to make CSS targeting easier and to avoid any naming conflicts.
Finally, I added an i
tag to the lesson link div so that I could target it with a CSS rule that sets the ::before
content to the appropriate Fontawesome icon:
<div class="mpcs-lesson-link"> <i class="mpcs-doc-text-inv<?php echo $tag_classes_cos;?>"></i> <?php echo $lesson->post_title; ?> </div>
Step 5:Include Fontawesome.
The easiest way to do this is to use the Fontawesome plugin!
Step 6:Create CSS rules.
Here is the pertinent CSS markup. This is from when I had created three lesson tags: intro
for introductory lessons, video
, for lessons that included videos, and reading
, for lessons that were text-only.
.lesson-tag-intro #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-intro::before { content: '\f05a'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-video #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-video::before { content: '\f03d'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-reading #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-reading::before { content: '\f518'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-download #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-download::before { content: '\f56d'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-challenge #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-challenge::before { content: '\f733'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-audio #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-audio::before { content: '\f028'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-discussion #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-discussion::before { content: '\f086'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .lesson-tag-summary #mpcs-main .mpcs-doc-text-inv::before, .mpcs-lesson-link i.lesson-tag-summary::before { content: '\f31a'; font-family: 'Fontawesome'; font-size: var(--icon-size-large); color: black; } .mpcs-lesson i[class*="lesson-tag"]::before { font-size: var(--icon-size-small); }
I’m using two selectors for each of the first eight rules because I am targeting the lesson name classes in both the main body of the lesson (first selector) and the the sidebar lesson navigation (the second selector). The final rule (using an attribute selector with a contains operator) resets the font size of each icon for the sidebar lesson navigation (I wanted it smaller here). Note also that I’m using custom properties (defined at the top of the file) for the icon sizes:
:root { --icon-size-large: 1.5rem; --icon-size-small: 0.75rem; }
And here again is a close-up of the final result, with custom lesson icons:

In Closing
If you found this article, please let me know by commenting below and/or by sharing it on your own blog or on social media. If you have questions or other ideas for how to solve the problem, I’d like to hear about those also.
Leave a Reply