Search code examples
javascriptphpwordpressaccessibility

Stop WordPress PHP/JavaScript function adding skip-link code


In wp-includes/block-template.php, the_block_template_skip_link() adds a script and style that creates a skip-link on every page. I want to stop this addition.

I understand why the skip-link is important. I’m not removing it; I’m replacing it because I need to wrap it in a div and change the link text to title case:

add_action( 'wp_body_open', 'custom_skip_link' );

function custom_skip_link() {
    echo '
    <div class="skip-link-container">
        <a class="skip-link screen-reader-text" href="#content">Skip to Content</a>
    </div>
  ';
}

the_block_template_skip_link()

function the_block_template_skip_link() {
    global $_wp_current_template_content;
 
    // Early exit if not a block theme.
    if ( ! current_theme_supports( 'block-templates' ) ) {
        return;
    }
 
    // Early exit if not a block template.
    if ( ! $_wp_current_template_content ) {
        return;
    }
    ?>
 
    <?php
    /**
     * Print the skip-link styles.
     */
    ?>
    <style id="skip-link-styles">
        .skip-link.screen-reader-text {
            border: 0;
            clip: rect(1px,1px,1px,1px);
            clip-path: inset(50%);
            height: 1px;
            margin: -1px;
            overflow: hidden;
            padding: 0;
            position: absolute !important;
            width: 1px;
            word-wrap: normal !important;
        }
 
        .skip-link.screen-reader-text:focus {
            background-color: #eee;
            clip: auto !important;
            clip-path: none;
            color: #444;
            display: block;
            font-size: 1em;
            height: auto;
            left: 5px;
            line-height: normal;
            padding: 15px 23px 14px;
            text-decoration: none;
            top: 5px;
            width: auto;
            z-index: 100000;
        }
    </style>
    <?php
    /**
     * Print the skip-link script.
     */
    ?>
    <script>
    ( function() {
        var skipLinkTarget = document.querySelector( 'main' ),
            sibling,
            skipLinkTargetID,
            skipLink;
 
        // Early exit if a skip-link target can't be located.
        if ( ! skipLinkTarget ) {
            return;
        }
 
        // Get the site wrapper.
        // The skip-link will be injected in the beginning of it.
        sibling = document.querySelector( '.wp-site-blocks' );
 
        // Early exit if the root element was not found.
        if ( ! sibling ) {
            return;
        }
 
        // Get the skip-link target's ID, and generate one if it doesn't exist.
        skipLinkTargetID = skipLinkTarget.id;
        if ( ! skipLinkTargetID ) {
            skipLinkTargetID = 'wp--skip-link--target';
            skipLinkTarget.id = skipLinkTargetID;
        }
 
        // Create the skip link.
        skipLink = document.createElement( 'a' );
        skipLink.classList.add( 'skip-link', 'screen-reader-text' );
        skipLink.href = '#' + skipLinkTargetID;
        skipLink.innerHTML = '<?php esc_html_e( 'Skip to content' ); ?>';
 
        // Inject the skip link.
        sibling.parentElement.insertBefore( skipLink, sibling );
    }() );
    </script>
    <?php
}

What I've Tried

In functions.php, I’ve tried the following to no avail:

// Attempt 1
remove_action( 'wp_body_open', 'gutenberg_the_skip_link' );

//Attempt 2
remove_action( 'init', 'gutenberg_the_skip_link' );

// Attempt 3
remove_action( 'wp_body_open', 'the_block_template_skip_link' );

// Attempt 4
remove_action( 'init', 'the_block_template_skip_link' );

I understand I can remove the skip-link using jQuery but I’d prefer to stop it being added in the first place using PHP.

(function($) {
    $(document).ready(function() {
        $("a.skip-link, style#skip-link-styles").remove();
    })
})(jQuery);

Solution

  • This works:

    // Attempt 5
    remove_action( 'wp_footer', 'the_block_template_skip_link' );
    

    I didn't consider removing the action from wp_footer(). I incorrectly assumed the_block_template_skip_link() was being applied to wp_body_open() because of the skip-link's position in the page.

    I can see now that the skip-link's position is determined in relation to the site wrapper using JavaScript:

    // Get the site wrapper.
    // The skip-link will be injected in the beginning of it.
    sibling = document.querySelector( '.wp-site-blocks' );
    
    [...]
    
    // Inject the skip link.
    sibling.parentElement.insertBefore( skipLink, sibling );