Learn how to implement a table of contents in WordPress without using a plugin.
This method does not use JQuery and is also the implementation method introduced on this website.
It takes less time and man-hours, if you like.
The following steps are to be implemented.
- Edit functions.php.
- Editing CSS.
- Set display conditions on the Appearance → Customise screen.
- Adjustment of display and non-display within individual articles.
Edit functions.php.
If a child theme is available, use the child theme’s functions.php.
The instructions for each code are given at the top of each code for reference.
※Always make a backup before editing.
//////////////////////////////////////////////////
//Original sanitize_callback
//////////////////////////////////////////////////
// CheckBox
function fit_sanitize_checkbox( $checked ) {
return ( ( isset( $checked ) && true == $checked ) ? true : false );
}
// radio/select
function fit_sanitize_select( $input, $setting ) {
$input = sanitize_key( $input );
$choices = $setting->manager->get_control($setting->id)->choices;
return ( array_key_exists( $input, $choices ) ? $input : $setting->default );
}
// number limit
function fit_sanitize_number_range( $number, $setting ) {
$number = absint( $number );
$atts = $setting->manager->get_control( $setting->id )->input_attrs;
$min = ( isset( $atts['min'] ) ? $atts['min'] : $number );
$max = ( isset( $atts['max'] ) ? $atts['max'] : $number );
$step = ( isset( $atts['step'] ) ? $atts['step'] : 1 );
return ( $min <= $number && $number <= $max && is_int( $number / $step ) ? $number : $setting->default );
}
//////////////////////////////////////////////////
//Post page various setting screens
//////////////////////////////////////////////////
function fit_post_cutomizer( $wp_customize ) {
// Section
$wp_customize->add_section( 'fit_post_section', array(
'title' => 'Post page settings',
'priority' => 1,
));
// Show/hide table of contents Settings
$wp_customize->add_setting( 'fit_post_outline', array(
'default' => 'value1',
'type' => 'option',
'sanitize_callback' => 'fit_sanitize_select',
));
// Show/hide table of contents Controls
$wp_customize->add_control( 'fit_post_outline', array(
'section' => 'fit_post_section',
'settings' => 'fit_post_outline',
'label' => '■Show/hide table of contents',
'description' => 'Select whether to display a table of contents on the post page<br>
(It is automatically inserted before the first h-tag in the article.※
Can be displayed in any position with a shortcode.)',
'type' => 'select',
'choices' => array(
'value1' => 'Display(default)',
'value2' => 'Do not display',
),
));
// Minimum number of headings for displaying the table of contents Settings
$wp_customize->add_setting( 'fit_post_outline_number', array(
'default' => '1',
'type' => 'option',
'sanitize_callback' => 'fit_sanitize_number_range',
));
// Minimum number of headings for displaying the table of contents Control
$wp_customize->add_control( 'fit_post_outline_number', array(
'section' => 'fit_post_section',
'settings' => 'fit_post_outline_number',
'description' => 'Specify the minimum number of headings to display the table of contents.',
'type' => 'number',
'input_attrs' => array(
'step' => '1',
'min' => '1',
'max' => '50',
),
));
// Contents Panel default settings Settings
$wp_customize->add_setting('fit_post_outline_close', array(
'type' => 'option',
'sanitize_callback' => 'fit_sanitize_checkbox',
));
// Contents Panel default settings Controls
$wp_customize->add_control('fit_post_outline_close', array(
'section' => 'fit_post_section',
'settings' => 'fit_post_outline_close',
'label' => 'Keep the table of contents panel closed by default.',
'type' => 'checkbox',
));
}
add_action( 'customize_register', 'fit_post_cutomizer' );
//////////////////////////////////////////////////
//Show/hide table of contents, individual selection settings
//////////////////////////////////////////////////
if ( get_option('fit_post_outline') != 'value2') {
function add_outline_fields() {
//add_meta_box(ID of the HTML of the input box to be displayed, labels, function name to create the content to be displayed, post type, display method.)
add_meta_box( 'outline_setting', 'Individual hide settings for the table of contents.', 'insert_outline_fields', 'post', 'normal');
}
add_action('admin_menu', 'add_outline_fields');
// Input area for custom fields.
function insert_outline_fields() {
global $post;
if( get_post_meta($post->ID,'outline_none',true) == "1" ) {
$outline_none_check = "checked";
}else {
$outline_none_check = "";
}
echo '
<div style="margin:20px 0; overflow: hidden; line-height:2;">
<div style="float:left;width:120px;">Table of contents display settings.</div>
<div style="float:right;width:calc(100% - 140px);">
<input type="checkbox" name="outline_none" value="1" '.$outline_none_check.' >:Do you want to hide the table of contents in this post?
</div>
<div style="clear:both;"></div>
</div>
';
}
// Save custom field values.
function save_outline_fields( $post_id ) {
if(!empty($_POST['outline_none'])){
update_post_meta($post_id, 'outline_none', $_POST['outline_none'] );
}else{
delete_post_meta($post_id, 'outline_none');
}
}
add_action('save_post', 'save_outline_fields');
}
//////////////////////////////////////////////////
//Create original table of contents.
//////////////////////////////////////////////////
function get_outline_info($content) {
// Define a variable to contain the HTML of the table of contents.
$outline = '';
// h1?h6Define a variable to contain the number of tags.
$counter = 0;
// Search for h1?h6 tags in articles.(Improved to also include id and class attributes).
if (preg_match_all('/<h([1-4])[^>]*>(.*?)<\/h\1>/', $content, $matches, PREG_SET_ORDER)) {
// Get the smallest number in the h1?h6 tags used in the article, h1?h6.
// ※The word level in the source since then stands for h1?h6.
$min_level = min(array_map(function($m) { return $m[1]; }, $matches));
// Determines the starting level.
// ※Each time this level is increased, more <ul></li> tags are added.
$current_level = $min_level - 1;
// Define an array to store the number of occurrences of each level.
$sub_levels = array('1' => 0, '2' => 0, '3' => 0, '4' => 0);
// Loop over the number of h-tags, found in the article.
foreach ($matches as $m) {
$level = $m[1]; // Get the level of the h-tag found.
$text = $m[2]; // Get the content of the tag, of the h-tag found.
// This is the process of closing the li, ul tags, which may go inside after the second loop.
// For example, if the last time it was processed was for an h3 tag and the one that appeared this time was for an h2 tag,
// Close the ul for the h3 tag and prepare for the h2 tag.
while ($current_level > $level) {
$current_level--;
$outline .= '</li></ul>';
}
// For the same LEVEL, close the LI tag and open a new one.
if ($current_level == $level) {
$outline .= '</li><li class="outline__item">';
} else {
// If not on the same level, add ul and li tags.
// For example, if the last time it was processed was for an h2 tag and the one that appeared this time was for an h3 tag,
// Add ul for h3 tags.
while ($current_level < $level) {
$current_level++;
$outline .= sprintf('<ul class="outline__list outline__list-%s"><li class="outline__item">', $current_level);
}
// If the level of the heading changes, the number of occurrences below the current level is reset.
for ($idx = $current_level + 0; $idx < count($sub_levels); $idx++) {
$sub_levels[$idx] = 0;
}
}
// Update the array storing the number of occurrences at each level.
$sub_levels[$current_level]++;
// Defines an array containing the path of the h-tag currently being processed.
// For example, if you are proceeding with h2 -> h3 -> h3 tags,
// level_fullpath is like array(1, 2).
// ※The 1 in level_fullpath[0] indicates that it is directly under the first h2 tag.
// ※The 2 in level_fullpath[1] represents the second h3.
$level_fullpath = array();
for ($idx = $min_level; $idx <= $level; $idx++) {
$level_fullpath[] = $sub_levels[$idx];
}
$target_anchor = 'outline__' . implode('_', $level_fullpath);
// Add headings to the table of contents in the form of <a href="#outline_1_2">1.2 Headings</a>.
$outline .= sprintf('<a class="outline__link" href="#%s"><span class="outline__number" style="display:none;">%s.</span> %s</a>', $target_anchor, implode('.', $level_fullpath), strip_tags($text));
// Heading body in the text, <h3> heading</h3> to <h3id="outline_1_2">Headline</h3>
// Replace it with a form such as.
$hid = preg_replace('/<h([1-6])/', '<h\1 id="' .$target_anchor . '"', $m[0]);
$content = str_replace($m[0], $hid, $content);
}
// After the loop of the h tag ends, the unclosed ul tag is closed.
while ($current_level >= $min_level) {
$outline .= '</li></ul>';
$current_level--;
}
// Number of h1?h6 tags
$counter = count($matches);
}
return array('content' => $content, 'outline' => $outline, 'count' => $counter);
}
//Create a table of contents.
function add_outline($content) {
// Number of headings required to display the table of contents.
if(get_option('fit_post_outline_number')){
$number = get_option('fit_post_outline_number');
}else{
$number = 1;
}
// Retrieve information related to the table of contents.
$outline_info = get_outline_info($content);
$content = $outline_info['content'];
$outline = $outline_info['outline'];
$count = $outline_info['count'];
if (get_option('fit_post_outline_close') ) {
$close = "";
}else{
$close = "checked";
}
if ($outline != '' && $count >= $number) {
// Decorate the table of contents.
$decorated_outline = sprintf('
<div class="outline">
<span class="outline__title">目次</span>
<input class="outline__toggle" id="outline__toggle" type="checkbox" '.$close.'>
<label class="outline__switch" for="outline__toggle"></label>
%s
</div>', $outline);
// Add a table of contents when other than Hide table of contents is selected in the customiser & when the individual hide is other than 1.
if ( get_option('fit_post_outline') != 'value2' && get_post_meta(get_the_ID(), 'outline_none', true) != '1' && is_single() ) {
$shortcode_outline = '
';
if (strpos($content, $shortcode_outline) !== false) {
// If there is a shortcode in the article, the shortcode is replaced by a table of contents.
$content = str_replace($shortcode_outline, $decorated_outline, $content);
} else if (preg_match('/<h[1-6].*>/', $content, $matches, PREG_OFFSET_CAPTURE)) {
// Add a table of contents before the first h-tag.
$pos = $matches[0][1];
$content = substr($content, 0, $pos) . $decorated_outline . substr($content, $pos);
}
}
}
return $content;
}
add_filter('the_content', 'add_outline');
function override_mce_options( $init_array ) {
global $allowedposttags;
$init_array['valid_elements'] = '*[*]';
$init_array['extended_valid_elements'] = '*[*]';
$init_array['valid_children'] = '+a[' . implode( '|', array_keys( $allowedposttags ) ) . ']';
$init_array['indent'] = true;
$init_array['wpautop'] = false;
return $init_array;
}
add_filter( 'tiny_mce_before_init', 'override_mce_options' );
Editing CSS code.
CSS adjustments.
The CSS code is shown below.
Copy and paste the whole thing into any style sheet, such as style.css.
/*Table of Contents*/
.outline{
border:1px dotted #D8D8D8;
padding:20px;
margin-top:20px;
display:inline-block;
font-size:0.9em;
line-height:1.5em;
}
.outline__toggle{display: none;}
.outline__switch::before{
content:"Open";
cursor:pointer;
border: solid 1px #D8D8D8;
padding:5px;
font-size:0.8rem;
margin-left:5px;
border-radius: 5px;
}
.outline__toggle:checked + .outline__switch::before{content:"Close"}
.outline__switch + .outline__list{
overflow:hidden;
width:0;
height:0;
margin-top:0;
margin-left:-20px;
transition: 0.2s;
}
.outline__toggle:checked + .outline__switch + .outline__list {
width: auto;
height: auto;
margin-top: 20px;
transition: 0.2s;
border-top: dotted 1px #d2d2d2;
padding-top: 1em;
}
.outline__item:before {content: normal;}
.outline__link{
display:relative;
color:#191919 !important;
}
.outline__link:hover{border:none;}
.outline__number{
display: inline-block;
color:#7F7F7F;
background:#F2F2F2;
padding:3px 6px;
font-weight:400;
font-size:1.2rem;
margin-right: 5px;
}
label.outline__switch {
position: relative;
float: right;
}
li .outline__item{
list-style-type:none!important;
}
li .outline__item:before{
content:'- ';
}
ul .outline__item{
list-style-type:none!important;
}
ul{
-webkit-padding-start: 1.2em;
}
The design can be changed to any desired design by customising the CSS.
When you have finished editing the CSS, save it to the CSS used by your theme.
This completes the set-up.
Set display conditions on the Appearance → Customise screen.
Go to Appearance, Customise, Post Page Settings.
Select whether to display a table of contents on the post page.
The standard table of contents is displayed or not.
This item should basically be “Display”.
If you only need the table of contents occasionally, then “Hide” is fine.
Set the minimum number of headings to display the table of contents.
The table of contents is displayed if there are a number of headings.
A standard number is between 3 and 5.If you set it to 3, a table of contents will not be generated if there are only one or two headings.
This site is set at 2.
Keep the table of contents panel closed by default.
The table of contents field should be closed by default from the beginning.
This item should be left unchecked.
Adjustment of display and non-display within individual articles.
Basically, there is very little to manipulate, but there are times when you want to hide the table of contents due to the design and look and feel within a post, although the table of contents is displayed as standard with many headings.
In such cases, there is a check box in the individual article to check.
Conclusion.
In this article, we showed you how to implement a table of contents in WordPress without using a plugin.
The work itself does not take long and can be implemented quickly, so please refer to this if you like.
Thank you for watching until the end.
Arrival Shop
Accession in December 2024
More will appear in December! Pre-orders are also available.We hope you will order as soon as possible if you wish, as numbers are limited.
Continue readingAnimation
Post-airing popularity ranking of spring 2024 animations.
1. 【10th place】A salad bowl of eccentrics2. 【9th place】Jellyfish Can’t Swim in the Night3. 【8th place】The Fable4. 【7th place】Oblivion Battery5. 【6th place】Konosuba: God’s Blessing on This Wonderful World!36. 【5th place】Shuumatsu Train Doko He Iku?7. 【4th place】GIRLS BAND CRY8. 【3rd place】Mushoku...
Continue readingCode Web Wordpress
How to save rewriting links.WordPress
If you are building multiple WordPress sites, you face the problem of having to ‘rewrite URLs’ when duplicating them. The following code is recommended to solve this problem before it happens. Please describe it in the theme’s ‘functions.php’ file. /*...
Continue readingPlant
What is a cactus. Origin and characteristics of ‘Cactos’ [1].
The word ‘Cactus’ derives from the Greek word ‘Kàktos’. The term was used by Theophrastus in his book HistoriaPlantarum to describe ‘unknown thorny plants’. The term ‘Cactus’ was subsequently adopted by the renowned botanist Linneo to define the American thorny...
Continue readingPlant
Copiapoa cinerea var. cinerea
Copiapoa cinerea is known as the ‘white cactus’ and is arguably the most popular cactus in Japan. Individuals with particularly white skin and pitch-black spines fetch high prices. 1. Synonym2. Origin3. Habitat4. Description5. Farming6. Way of increasing Synonym Below are...
Continue readingCode Speed Web Without Plugin
Without Plugin!How to LazyLoad Google Adsense to speed up display speed.
Loading Google Adsense significantly reduces page display speed. The following methods will improve the expectation of problem resolution and should be tried. 1. Remove Script tag in Google Adsense code.2. Install code for LazyLoad. Remove Script tag in Google Adsense...
Continue readingSpeed Web
Image compression web tool to accelerate website display speed.
There are several ways to improve the display speed of a website, the first effective way is to optimise the size of images. In such cases, it is recommended to use the following image compression web tools. The advantage is...
Continue readingCode Security Web Wordpress
How to prohibit access to wp-config.php.WordPress
Prohibiting access to wp-config.php improves site security. You are encouraged to refer to this information to maintain your website. Put the following code in the “.htaccess” file. <files wp-config.php> order allow,deny deny from all </files>
Continue readingCode Web Without Plugin Youtube
How to make YouTube embedding responsive while maintaining proportions with CSS.
Learn how to make YouTube embeds responsive while maintaining the ratio. 1. 1:Add div tag.2. 2:Add css.3. Finalise. 1:Add div tag. Add a div tag to enclose the iframe tag. <div class="yt"><iframe width="560" height="315" src="https://www.youtube.com/embed/YUDbl9qBihk?si=RRyI62O5tVSEfHvo" title="YouTube video player" frameborder="0" allow="accelerometer;...
Continue readingPlant
Cool and easy to grow Gymnocalycium Origin, origin and how to grow.
Gymnocalycium is one of the most robust species to manage. It is a cool and varied species with a very good balance of both ornamental and collecting value. 1. Origin2. Habitat3. Features4. Type5. Farming Origin Derived from the Greek ‘gymnòs’...
Continue reading