Skip to content

Mobile performance issues with Splide showcase #102

Description

@nikki5149

Environment

  • Fictioneer theme (parent) + child theme
  • WordPress (Query Monitor confirms standard wp_enqueue_scripts pipeline)
  • Cloudflare Free plan in front of the site
  • Issue reproduces specifically on mobile (not desktop)
  • Site: mizushinovels.com (homepage, uses [fictioneer_showcase] shortcode with Splide carousel)

Issue 1: application-properties-splide.css is render-blocking and delays LCP

Observed in Lighthouse (mobile):

  • application-properties-splide.css — 43.7 KiB, ~2,100–2,300ms duration, consistently the single largest render-blocking request on every audit run.
  • File is enqueued in <head> as a standard blocking stylesheet with handle fictioneer-application (confirmed via rendered <link id='fictioneer-application-css' ...>).
  • The Splide carousel ([fictioneer_showcase]) is above the fold on mobile and renders the page's LCP image, so this CSS genuinely is critical-path — it's not a case of "just defer it," since doing so would delay LCP further.

What I tried:

  1. Preloading the CSS via wp_head at priority 1:

    add_action( 'wp_head', function() {
        if ( is_front_page() ) {
            global $wp_styles;
            $handle = 'fictioneer-application';
            $src = $wp_styles->registered[ $handle ]->src ?? null;
            $ver = $wp_styles->registered[ $handle ]->ver ?? null;
            if ( $src ) {
                $url = add_query_arg( 'ver', $ver, $src );
                echo '<link rel="preload" as="style" href="' . esc_url( $url ) . '">';
            }
        }
    }, 1 );

    Result: preload tag renders correctly (confirmed the handle via Query Monitor, but Lighthouse's render-blocking duration for the file barely changed. Preload doesn't help much here because the file is still render-blocking in addition to being preloaded — the browser still can't paint until it's parsed either way.

  2. Deferring splide.min.js (handle fictioneer-splide) via script_loader_tag:

    add_filter( 'script_loader_tag', function( $tag, $handle ) {
        $defer_handles = array( 'fictioneer-splide', 'fictioneer-stimulus' );
        if ( in_array( $handle, $defer_handles, true ) ) {
            return str_replace( ' src', ' defer src', $tag );
        }
        return $tag;
    }, 10, 2 );

    This reduces JS blocking but doesn't touch the 43.7 KiB CSS file, which remains the dominant blocking resource.

Question for maintainers: Is application-properties-splide.css intentionally a single monolithic file combining Splide's own library CSS with Fictioneer's custom showcase/carousel styling? A ~44 KiB file for what's visually a single above-the-fold carousel component seems large — is there a supported way to:

  • Split "critical" showcase-specific rules (needed for correct above-the-fold layout) from non-critical carousel-interaction styles (arrows, pagination dots, hover states) so only the critical subset needs to block render?
  • Or is there a filter/hook to opt out of loading the full file when only a subset of Splide features are used (e.g., this showcase uses autoplay, loop, pagination, no arrows)?

Issue 2 (related, lower priority): Multiple LCP-candidate images all receiving fetchpriority="high"

Not a theme bug per se, but flagging in case it's relevant to how the showcase shortcode template outputs the_post_thumbnail() — the showcase loop renders every slide's <img> at full priority by default (no differentiation for the first/likely-LCP slide vs. later off-screen slides in the Splide track). We worked around this site-side via a wp_get_attachment_image_attributes filter limiting fetchpriority="high" to only the first image encountered per page load, but it might be worth the showcase template itself only prioritizing the first slide (or first perPage count of slides) by default, since Splide loop mode duplicates/preloads slides for infinite scroll and all of them currently compete for "high" priority simultaneously.


Summary of what's been tried without full resolution

  • Preloading Splide CSS — renders correctly, minimal measured improvement to render-blocking time.
  • Deferring Splide/Stimulus JS — works for JS, doesn't address CSS blocking time.
  • Regenerating thumbnails / adjusting add_image_size('cover', ...) — resolved a separate oversized-image issue, unrelated to the above two but mentioned for context since all three were found during the same performance audit.

Happy to provide a full Lighthouse trace, Query Monitor output, or reproduce on a staging URL if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions