By Devport Team | Last updated: 2025-07-12 | 18 min read

Optimizing WordPress for Mobile Performance

Mobile users now account for over 60% of web traffic, making mobile performance critical for WordPress success. Mobile optimization goes beyond responsive design—it requires specific strategies for limited bandwidth, touch interactions, and smaller screens. This comprehensive guide covers everything from mobile-first development to advanced optimization techniques that ensure your WordPress site delivers exceptional mobile experiences.

Poor mobile performance directly impacts user engagement, with 53% of mobile users abandoning sites that take over 3 seconds to load. We'll explore practical techniques to achieve sub-second load times on mobile devices while maintaining rich functionality and visual appeal.

Table of Contents

  1. Mobile Performance Fundamentals
  2. Responsive Design Optimization
  3. Mobile-First Development
  4. Touch and Interaction Optimization
  5. Mobile-Specific Performance Techniques
  6. AMP Implementation
  7. Testing and Monitoring

Mobile Performance Fundamentals

Understanding Mobile Constraints

Mobile devices face unique challenges that impact performance:

// Mobile device constraints detector
class MobileConstraints {
    constructor() {
        this.constraints = {
            network: this.detectNetworkType(),
            cpu: this.estimateCPUPower(),
            memory: this.getAvailableMemory(),
            battery: this.getBatteryStatus(),
            viewport: this.getViewportDimensions()
        };
    }

    detectNetworkType() {
        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;

        if (connection) {
            return {
                type: connection.effectiveType, // '4g', '3g', '2g', 'slow-2g'
                downlink: connection.downlink, // Mbps
                rtt: connection.rtt, // Round trip time in ms
                saveData: connection.saveData // Data saver enabled
            };
        }

        return { type: 'unknown' };
    }

    estimateCPUPower() {
        // Estimate CPU power based on hardware concurrency
        const cores = navigator.hardwareConcurrency || 2;
        const isMobile = /Android|webOS|iPhone|iPad|iPod/i.test(navigator.userAgent);

        return {
            cores: cores,
            estimated_power: isMobile ? 'low' : 'high',
            recommendation: cores <= 4 ? 'reduce-animations' : 'full-experience'
        };
    }

    adaptPerformance() {
        const network = this.constraints.network;

        if (network.type === '2g' || network.type === 'slow-2g' || network.saveData) {
            return {
                images: 'low-quality',
                videos: 'disabled',
                animations: 'reduced',
                prefetch: false
            };
        } else if (network.type === '3g') {
            return {
                images: 'medium-quality',
                videos: 'on-demand',
                animations: 'simple',
                prefetch: 'minimal'
            };
        }

        return {
            images: 'high-quality',
            videos: 'auto-play',
            animations: 'full',
            prefetch: true
        };
    }
}

Mobile-Specific Performance Metrics

// Track mobile-specific metrics
class Mobile_Performance_Tracker {

    public function __construct() {
        add_action('wp_footer', [$this, 'inject_performance_tracking']);
    }

    public function inject_performance_tracking() {
        if (!wp_is_mobile()) {
            return;
        }
        ?>
        <script>
        (function() {
            // First Input Delay (FID) - Critical for mobile
            let firstInputDelay = 0;
            let firstInputTimeStamp = 0;

            ['click', 'touchstart', 'keydown'].forEach(event => {
                addEventListener(event, (e) => {
                    if (!firstInputTimeStamp) {
                        firstInputDelay = Date.now() - e.timeStamp;
                        firstInputTimeStamp = e.timeStamp;

                        // Send to analytics
                        if (window.gtag) {
                            gtag('event', 'FID', {
                                'event_category': 'Web Vitals',
                                'value': Math.round(firstInputDelay)
                            });
                        }
                    }
                }, { once: true, passive: true });
            });

            // Touch responsiveness
            let touchStartTime;
            document.addEventListener('touchstart', () => {
                touchStartTime = performance.now();
            }, { passive: true });

            document.addEventListener('touchend', () => {
                const touchDuration = performance.now() - touchStartTime;

                if (touchDuration > 100) { // Slow touch response
                    console.warn('Slow touch response:', touchDuration + 'ms');
                }
            }, { passive: true });

            // Viewport changes (orientation)
            let lastOrientation = window.orientation;
            window.addEventListener('orientationchange', () => {
                const newOrientation = window.orientation;

                // Track orientation changes
                if (window.gtag) {
                    gtag('event', 'orientation_change', {
                        'from': lastOrientation,
                        'to': newOrientation
                    });
                }

                lastOrientation = newOrientation;
            });
        })();
        </script>
        <?php
    }
}

new Mobile_Performance_Tracker();

Responsive Design Optimization

Optimized Responsive Images

// Advanced responsive image implementation
class Responsive_Image_Optimizer {

    public function __construct() {
        add_filter('wp_get_attachment_image_attributes', [$this, 'optimize_image_attributes'], 10, 3);
        add_filter('the_content', [$this, 'optimize_content_images']);
        add_action('wp_head', [$this, 'add_preconnect_headers']);
    }

    public function optimize_image_attributes($attributes, $attachment, $size) {
        // Generate optimal srcset for mobile
        $image_meta = wp_get_attachment_metadata($attachment->ID);
        $upload_dir = wp_upload_dir();
        $base_url = $upload_dir['baseurl'] . '/' . dirname($image_meta['file']);

        $srcset = [];
        $sizes = [
            'thumbnail' => 150,
            'medium' => 300,
            'medium_large' => 768,
            'large' => 1024,
            'full' => $image_meta['width']
        ];

        foreach ($sizes as $size_name => $width) {
            if (isset($image_meta['sizes'][$size_name])) {
                $srcset[] = $base_url . '/' . $image_meta['sizes'][$size_name]['file'] . ' ' . $width . 'w';
            }
        }

        $attributes['srcset'] = implode(', ', $srcset);

        // Mobile-optimized sizes attribute
        $attributes['sizes'] = '(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw';

        // Add loading lazy by default
        $attributes['loading'] = 'lazy';

        // Add aspect ratio for CLS prevention
        if (isset($image_meta['width']) && isset($image_meta['height'])) {
            $attributes['style'] = sprintf(
                'aspect-ratio: %d / %d;',
                $image_meta['width'],
                $image_meta['height']
            );
        }

        return $attributes;
    }

    public function optimize_content_images($content) {
        // Process images in content
        $content = preg_replace_callback(
            '/<img([^>]+)>/i',
            [$this, 'process_image_tag'],
            $content
        );

        return $content;
    }

    private function process_image_tag($matches) {
        $img_tag = $matches[0];

        // Add loading="lazy" if not present
        if (stripos($img_tag, 'loading=') === false) {
            $img_tag = str_replace('<img', '<img loading="lazy"', $img_tag);
        }

        // Add decoding="async" for better performance
        if (stripos($img_tag, 'decoding=') === false) {
            $img_tag = str_replace('<img', '<img decoding="async"', $img_tag);
        }

        // Extract and optimize src
        preg_match('/src=["\']([^"\']+)["\']/i', $img_tag, $src_matches);
        if (!empty($src_matches[1])) {
            $src = $src_matches[1];

            // Convert to WebP if supported
            if ($this->client_supports_webp()) {
                $webp_src = $this->get_webp_url($src);
                if ($webp_src) {
                    $img_tag = str_replace($src, $webp_src, $img_tag);
                }
            }
        }

        return $img_tag;
    }

    private function client_supports_webp() {
        return isset($_SERVER['HTTP_ACCEPT']) && 
               strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false;
    }

    private function get_webp_url($image_url) {
        // Convert image URL to WebP version
        $pathinfo = pathinfo($image_url);
        $webp_url = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '.webp';

        // Check if WebP version exists
        $upload_dir = wp_upload_dir();
        $relative_path = str_replace($upload_dir['baseurl'], '', $webp_url);
        $webp_path = $upload_dir['basedir'] . $relative_path;

        if (file_exists($webp_path)) {
            return $webp_url;
        }

        return false;
    }
}

new Responsive_Image_Optimizer();

Mobile-Optimized CSS

/* Mobile-first CSS optimization */

/* Critical CSS for above-the-fold mobile content */
.critical-mobile {
    /* Minimal layout styles */
    display: flex;
    flex-direction: column;
    padding: 1rem;

    /* System font stack for faster loading */
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, 
                 "Helvetica Neue", Arial, sans-serif;
}

/* Responsive typography with fluid scaling */
:root {
    --min-font-size: 16px;
    --max-font-size: 20px;
    --min-viewport: 320px;
    --max-viewport: 1200px;
}

body {
    font-size: clamp(
        var(--min-font-size),
        calc(var(--min-font-size) + (var(--max-font-size) - var(--min-font-size)) * 
             ((100vw - var(--min-viewport)) / (var(--max-viewport) - var(--min-viewport)))),
        var(--max-font-size)
    );

    /* Optimize for readability on mobile */
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Touch-friendly interactive elements */
button, a, input, select, textarea {
    min-height: 44px; /* Apple's HIG recommendation */
    min-width: 44px;
    padding: 0.75rem 1rem;

    /* Prevent tap highlight on iOS */
    -webkit-tap-highlight-color: transparent;
}

/* Optimize animations for mobile */
@media (prefers-reduced-motion: no-preference) {
    .animate {
        animation: slideIn 0.3s ease-out;

        /* Use GPU acceleration */
        will-change: transform;
        transform: translateZ(0);
    }
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateY(1rem);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Responsive grid optimized for mobile */
.mobile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;

    /* Contain layout shifts */
    contain: layout style;
}

/* Mobile-specific media queries */
@media (max-width: 768px) {
    /* Hide non-essential elements */
    .desktop-only {
        display: none !important;
    }

    /* Optimize spacing for touch */
    .mobile-spacing {
        padding: 1rem;
        margin-bottom: 1rem;
    }

    /* Full-width elements on mobile */
    .mobile-full {
        width: 100%;
        max-width: 100%;
        margin-left: -1rem;
        margin-right: -1rem;
        padding-left: 1rem;
        padding-right: 1rem;
    }
}

/* High DPI display optimization */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
    /* Use higher quality images for retina displays */
    .retina-image {
        background-image: url('[email protected]');
        background-size: contain;
    }
}

Mobile-First Development

Mobile-First WordPress Theme Structure

// Mobile-first theme functions
class Mobile_First_Theme {

    public function __construct() {
        add_action('after_setup_theme', [$this, 'setup_mobile_features']);
        add_action('wp_enqueue_scripts', [$this, 'load_mobile_assets']);
        add_filter('body_class', [$this, 'add_mobile_body_classes']);
    }

    public function setup_mobile_features() {
        // Mobile-specific image sizes
        add_image_size('mobile-featured', 640, 360, true);
        add_image_size('mobile-thumbnail', 320, 180, true);

        // Enable responsive embeds
        add_theme_support('responsive-embeds');

        // Disable Gutenberg block styles on mobile
        if (wp_is_mobile()) {
            add_filter('should_load_separate_core_block_assets', '__return_true');
        }
    }

    public function load_mobile_assets() {
        // Load different assets based on device
        if (wp_is_mobile()) {
            // Mobile-specific stylesheet
            wp_enqueue_style(
                'mobile-styles',
                get_template_directory_uri() . '/assets/css/mobile.min.css',
                [],
                '1.0.0'
            );

            // Lighter JavaScript bundle for mobile
            wp_enqueue_script(
                'mobile-scripts',
                get_template_directory_uri() . '/assets/js/mobile.min.js',
                [],
                '1.0.0',
                true
            );

            // Dequeue heavy desktop scripts
            wp_dequeue_script('heavy-slider');
            wp_dequeue_script('desktop-animations');
        } else {
            // Desktop assets
            wp_enqueue_style(
                'desktop-styles',
                get_template_directory_uri() . '/assets/css/desktop.min.css',
                [],
                '1.0.0'
            );
        }

        // Progressive enhancement script
        wp_add_inline_script('mobile-scripts', $this->get_progressive_enhancement_script());
    }

    private function get_progressive_enhancement_script() {
        return "
        // Progressive enhancement based on device capabilities
        (function() {
            const enhance = {
                init: function() {
                    // Check for touch support
                    if ('ontouchstart' in window) {
                        document.documentElement.classList.add('touch');
                    }

                    // Check connection speed
                    if ('connection' in navigator) {
                        const connection = navigator.connection;
                        if (connection.effectiveType === '4g' && !connection.saveData) {
                            this.loadEnhancements();
                        }
                    }

                    // Intersection Observer for lazy loading
                    if ('IntersectionObserver' in window) {
                        this.setupLazyLoading();
                    }
                },

                loadEnhancements: function() {
                    // Load additional features for capable devices
                    const script = document.createElement('script');
                    script.src = '" . get_template_directory_uri() . "/assets/js/enhancements.js';
                    document.body.appendChild(script);
                },

                setupLazyLoading: function() {
                    const images = document.querySelectorAll('img[data-src]');
                    const imageObserver = new IntersectionObserver((entries) => {
                        entries.forEach(entry => {
                            if (entry.isIntersecting) {
                                const img = entry.target;
                                img.src = img.dataset.src;
                                img.removeAttribute('data-src');
                                imageObserver.unobserve(img);
                            }
                        });
                    });

                    images.forEach(img => imageObserver.observe(img));
                }
            };

            enhance.init();
        })();
        ";
    }

    public function add_mobile_body_classes($classes) {
        if (wp_is_mobile()) {
            $classes[] = 'is-mobile';

            // Detect specific mobile OS
            $user_agent = $_SERVER['HTTP_USER_AGENT'];

            if (strpos($user_agent, 'iPhone') !== false || strpos($user_agent, 'iPad') !== false) {
                $classes[] = 'ios-device';
            } elseif (strpos($user_agent, 'Android') !== false) {
                $classes[] = 'android-device';
            }
        }

        return $classes;
    }
}

new Mobile_First_Theme();

Conditional Loading for Mobile

// Smart resource loading based on device
class Mobile_Resource_Manager {

    public function __construct() {
        add_action('init', [$this, 'setup_conditional_loading']);
        add_filter('script_loader_tag', [$this, 'add_async_defer_attributes'], 10, 2);
    }

    public function setup_conditional_loading() {
        if (!wp_is_mobile()) {
            return;
        }

        // Disable emojis on mobile
        remove_action('wp_head', 'print_emoji_detection_script', 7);
        remove_action('wp_print_styles', 'print_emoji_styles');

        // Disable oEmbed on mobile
        remove_action('wp_head', 'wp_oembed_add_discovery_links');
        remove_action('wp_head', 'wp_oembed_add_host_js');

        // Limit post revisions on mobile editing
        if (is_admin()) {
            add_filter('wp_revisions_to_keep', function($num, $post) {
                return 5; // Keep only 5 revisions
            }, 10, 2);
        }
    }

    public function add_async_defer_attributes($tag, $handle) {
        // Mobile-specific async/defer loading
        $async_scripts = ['mobile-analytics', 'social-sharing'];
        $defer_scripts = ['comment-reply', 'wp-embed'];

        if (wp_is_mobile()) {
            if (in_array($handle, $async_scripts)) {
                return str_replace(' src', ' async src', $tag);
            }

            if (in_array($handle, $defer_scripts)) {
                return str_replace(' src', ' defer src', $tag);
            }
        }

        return $tag;
    }
}

new Mobile_Resource_Manager();

Touch and Interaction Optimization

Touch-Optimized Navigation

// Mobile navigation with touch gestures
class TouchNavigation {
    constructor() {
        this.nav = document.querySelector('.mobile-nav');
        this.touchStartX = 0;
        this.touchStartY = 0;
        this.isMenuOpen = false;

        this.init();
    }

    init() {
        // Hamburger menu
        const menuToggle = document.querySelector('.menu-toggle');
        menuToggle.addEventListener('click', () => this.toggleMenu());

        // Touch gestures
        document.addEventListener('touchstart', (e) => this.handleTouchStart(e), { passive: true });
        document.addEventListener('touchmove', (e) => this.handleTouchMove(e), { passive: false });

        // Improve tap responsiveness
        this.fastClick();
    }

    toggleMenu() {
        this.isMenuOpen = !this.isMenuOpen;
        this.nav.classList.toggle('is-open');
        document.body.classList.toggle('menu-open');

        // Trap focus when menu is open
        if (this.isMenuOpen) {
            this.trapFocus();
        }
    }

    handleTouchStart(e) {
        this.touchStartX = e.touches[0].clientX;
        this.touchStartY = e.touches[0].clientY;
    }

    handleTouchMove(e) {
        if (!this.touchStartX || !this.touchStartY) {
            return;
        }

        const touchEndX = e.touches[0].clientX;
        const touchEndY = e.touches[0].clientY;

        const deltaX = touchEndX - this.touchStartX;
        const deltaY = touchEndY - this.touchStartY;

        // Detect horizontal swipe
        if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 50) {
            if (deltaX > 0 && !this.isMenuOpen) {
                // Swipe right - open menu
                this.toggleMenu();
            } else if (deltaX < 0 && this.isMenuOpen) {
                // Swipe left - close menu
                this.toggleMenu();
            }

            // Prevent scrolling during swipe
            e.preventDefault();
        }

        // Reset values
        this.touchStartX = null;
        this.touchStartY = null;
    }

    fastClick() {
        // Remove 300ms delay on touch devices
        let touchStartTime;
        let touchStartX;
        let touchStartY;

        document.addEventListener('touchstart', (e) => {
            touchStartTime = Date.now();
            touchStartX = e.touches[0].clientX;
            touchStartY = e.touches[0].clientY;
        }, { passive: true });

        document.addEventListener('touchend', (e) => {
            const touchEndTime = Date.now();
            const touchEndX = e.changedTouches[0].clientX;
            const touchEndY = e.changedTouches[0].clientY;

            // Check if it's a tap (not a swipe or long press)
            const timeDiff = touchEndTime - touchStartTime;
            const distX = Math.abs(touchEndX - touchStartX);
            const distY = Math.abs(touchEndY - touchStartY);

            if (timeDiff < 200 && distX < 10 && distY < 10) {
                // Trigger click immediately
                const clickEvent = new MouseEvent('click', {
                    view: window,
                    bubbles: true,
                    cancelable: true
                });
                e.target.dispatchEvent(clickEvent);
                e.preventDefault();
            }
        }, { passive: false });
    }

    trapFocus() {
        const focusableElements = this.nav.querySelectorAll(
            'a[href], button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
        );

        const firstFocusable = focusableElements[0];
        const lastFocusable = focusableElements[focusableElements.length - 1];

        this.nav.addEventListener('keydown', (e) => {
            if (e.key === 'Tab') {
                if (e.shiftKey) {
                    if (document.activeElement === firstFocusable) {
                        lastFocusable.focus();
                        e.preventDefault();
                    }
                } else {
                    if (document.activeElement === lastFocusable) {
                        firstFocusable.focus();
                        e.preventDefault();
                    }
                }
            }

            if (e.key === 'Escape') {
                this.toggleMenu();
            }
        });
    }
}

// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', () => {
    new TouchNavigation();
});

Mobile Form Optimization

// Mobile-optimized form handling
class Mobile_Form_Optimizer {

    public function __construct() {
        add_filter('comment_form_defaults', [$this, 'optimize_comment_form']);
        add_action('wp_footer', [$this, 'add_form_enhancements']);
    }

    public function optimize_comment_form($defaults) {
        if (!wp_is_mobile()) {
            return $defaults;
        }

        // Mobile-optimized form fields
        $defaults['fields']['author'] = '<p class="comment-form-author">' .
            '<input id="author" name="author" type="text" ' .
            'placeholder="' . __('Your Name *') . '" ' .
            'autocomplete="name" ' .
            'inputmode="text" ' .
            'required /></p>';

        $defaults['fields']['email'] = '<p class="comment-form-email">' .
            '<input id="email" name="email" type="email" ' .
            'placeholder="' . __('Your Email *') . '" ' .
            'autocomplete="email" ' .
            'inputmode="email" ' .
            'required /></p>';

        $defaults['fields']['url'] = '<p class="comment-form-url">' .
            '<input id="url" name="url" type="url" ' .
            'placeholder="' . __('Website') . '" ' .
            'autocomplete="url" ' .
            'inputmode="url" /></p>';

        // Simplified mobile layout
        $defaults['comment_field'] = '<p class="comment-form-comment">' .
            '<textarea id="comment" name="comment" ' .
            'placeholder="' . __('Your Comment *') . '" ' .
            'rows="4" ' .
            'required></textarea></p>';

        return $defaults;
    }

    public function add_form_enhancements() {
        if (!wp_is_mobile()) {
            return;
        }
        ?>
        <script>
        // Auto-resize textareas
        document.querySelectorAll('textarea').forEach(textarea => {
            textarea.style.height = 'auto';
            textarea.addEventListener('input', function() {
                this.style.height = 'auto';
                this.style.height = this.scrollHeight + 'px';
            });
        });

        // Smooth scroll to form errors
        const forms = document.querySelectorAll('form');
        forms.forEach(form => {
            form.addEventListener('invalid', (e) => {
                e.preventDefault();
                const firstError = form.querySelector(':invalid');
                if (firstError) {
                    firstError.scrollIntoView({ 
                        behavior: 'smooth', 
                        block: 'center' 
                    });
                    firstError.focus();
                }
            }, true);
        });

        // Improve number input on mobile
        document.querySelectorAll('input[type="number"]').forEach(input => {
            // Add increment/decrement buttons
            const wrapper = document.createElement('div');
            wrapper.className = 'number-input-wrapper';
            input.parentNode.insertBefore(wrapper, input);
            wrapper.appendChild(input);

            const decrementBtn = document.createElement('button');
            decrementBtn.textContent = '-';
            decrementBtn.type = 'button';
            decrementBtn.className = 'number-decrement';
            decrementBtn.addEventListener('click', () => {
                input.stepDown();
                input.dispatchEvent(new Event('change'));
            });

            const incrementBtn = document.createElement('button');
            incrementBtn.textContent = '+';
            incrementBtn.type = 'button';
            incrementBtn.className = 'number-increment';
            incrementBtn.addEventListener('click', () => {
                input.stepUp();
                input.dispatchEvent(new Event('change'));
            });

            wrapper.insertBefore(decrementBtn, input);
            wrapper.appendChild(incrementBtn);
        });
        </script>

        <style>
        /* Mobile form styles */
        .number-input-wrapper {
            display: flex;
            align-items: center;
        }

        .number-decrement,
        .number-increment {
            width: 44px;
            height: 44px;
            font-size: 20px;
            border: 1px solid #ddd;
            background: #f5f5f5;
            cursor: pointer;
        }

        input[type="number"] {
            -moz-appearance: textfield;
            text-align: center;
            margin: 0 5px;
        }

        input[type="number"]::-webkit-inner-spin-button,
        input[type="number"]::-webkit-outer-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
        </style>
        <?php
    }
}

new Mobile_Form_Optimizer();

Mobile-Specific Performance Techniques

Adaptive Loading Strategy

// Adaptive loading based on device capabilities
class AdaptiveLoader {
    constructor() {
        this.networkInfo = this.getNetworkInfo();
        this.deviceMemory = navigator.deviceMemory || 4;
        this.hardwareConcurrency = navigator.hardwareConcurrency || 2;

        this.init();
    }

    getNetworkInfo() {
        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;

        return {
            type: connection?.effectiveType || '4g',
            saveData: connection?.saveData || false,
            downlink: connection?.downlink || 10,
            rtt: connection?.rtt || 50
        };
    }

    init() {
        // Determine quality level
        const quality = this.determineQuality();

        // Apply adaptive strategies
        this.adaptImages(quality);
        this.adaptVideos(quality);
        this.adaptFonts(quality);
        this.adaptAnimations(quality);
    }

    determineQuality() {
        // Score based on device capabilities
        let score = 0;

        // Network score (0-4)
        const networkScores = { '4g': 4, '3g': 2, '2g': 1, 'slow-2g': 0 };
        score += networkScores[this.networkInfo.type] || 2;

        // Memory score (0-4)
        score += Math.min(this.deviceMemory / 2, 4);

        // CPU score (0-4)
        score += Math.min(this.hardwareConcurrency / 2, 4);

        // Data saver penalty
        if (this.networkInfo.saveData) {
            score = Math.floor(score / 2);
        }

        // Determine quality level
        if (score >= 10) return 'high';
        if (score >= 6) return 'medium';
        return 'low';
    }

    adaptImages(quality) {
        const images = document.querySelectorAll('img[data-adaptive]');

        images.forEach(img => {
            const sources = {
                high: img.dataset.srcHigh || img.dataset.src,
                medium: img.dataset.srcMedium || img.dataset.srcLow,
                low: img.dataset.srcLow
            };

            // Set appropriate source
            img.src = sources[quality];

            // Adjust loading strategy
            if (quality === 'low') {
                img.loading = 'lazy';
            } else if (quality === 'high') {
                // Preload critical images
                if (img.dataset.critical) {
                    const link = document.createElement('link');
                    link.rel = 'preload';
                    link.as = 'image';
                    link.href = img.src;
                    document.head.appendChild(link);
                }
            }
        });
    }

    adaptVideos(quality) {
        const videos = document.querySelectorAll('video');

        videos.forEach(video => {
            if (quality === 'low') {
                // Replace with poster image
                const poster = video.poster;
                if (poster) {
                    const img = document.createElement('img');
                    img.src = poster;
                    img.alt = 'Video placeholder';
                    img.className = 'video-placeholder';
                    img.addEventListener('click', () => {
                        // Load video on demand
                        video.style.display = 'block';
                        img.style.display = 'none';
                        video.play();
                    });
                    video.parentNode.insertBefore(img, video);
                    video.style.display = 'none';
                }
            } else if (quality === 'medium') {
                // Disable autoplay
                video.removeAttribute('autoplay');
                video.preload = 'metadata';
            }
        });
    }

    adaptFonts(quality) {
        if (quality === 'low') {
            // Use system fonts only
            document.documentElement.style.setProperty(
                '--font-family',
                '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
            );
        } else if (quality === 'medium') {
            // Load subset fonts
            const link = document.querySelector('link[href*="fonts.googleapis"]');
            if (link) {
                link.href = link.href.replace('&display=swap', '&display=optional');
            }
        }
    }

    adaptAnimations(quality) {
        if (quality === 'low') {
            // Disable all animations
            const style = document.createElement('style');
            style.textContent = `
                *, *::before, *::after {
                    animation-duration: 0.01ms !important;
                    animation-iteration-count: 1 !important;
                    transition-duration: 0.01ms !important;
                }
            `;
            document.head.appendChild(style);
        } else if (quality === 'medium') {
            // Reduce animation complexity
            document.documentElement.classList.add('reduce-motion');
        }
    }
}

// Initialize adaptive loading
if ('connection' in navigator || 'deviceMemory' in navigator) {
    new AdaptiveLoader();
}

Service Worker for Mobile

// Mobile-optimized service worker
const CACHE_NAME = 'mobile-cache-v1';
const OFFLINE_URL = '/offline.html';

// Mobile-specific caching strategy
const mobileAssets = [
    '/',
    '/wp-content/themes/mobile/style.css',
    '/wp-content/themes/mobile/mobile.js',
    OFFLINE_URL
];

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME).then((cache) => {
            return cache.addAll(mobileAssets);
        })
    );
    self.skipWaiting();
});

self.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((cacheName) => {
                    if (cacheName !== CACHE_NAME) {
                        return caches.delete(cacheName);
                    }
                })
            );
        })
    );
    self.clients.claim();
});

self.addEventListener('fetch', (event) => {
    // Network-first for HTML
    if (event.request.mode === 'navigate') {
        event.respondWith(
            fetch(event.request)
                .then((response) => {
                    // Cache successful responses
                    if (response.status === 200) {
                        const responseToCache = response.clone();
                        caches.open(CACHE_NAME).then((cache) => {
                            cache.put(event.request, responseToCache);
                        });
                    }
                    return response;
                })
                .catch(() => {
                    // Serve offline page
                    return caches.match(OFFLINE_URL);
                })
        );
        return;
    }

    // Cache-first for assets
    event.respondWith(
        caches.match(event.request).then((response) => {
            if (response) {
                // Update cache in background
                event.waitUntil(
                    fetch(event.request).then((response) => {
                        if (response.status === 200) {
                            caches.open(CACHE_NAME).then((cache) => {
                                cache.put(event.request, response);
                            });
                        }
                    }).catch(() => {})
                );

                return response;
            }

            return fetch(event.request).then((response) => {
                // Don't cache non-successful responses
                if (!response || response.status !== 200 || response.type !== 'basic') {
                    return response;
                }

                const responseToCache = response.clone();
                caches.open(CACHE_NAME).then((cache) => {
                    cache.put(event.request, responseToCache);
                });

                return response;
            });
        })
    );
});

// Background sync for mobile
self.addEventListener('sync', (event) => {
    if (event.tag === 'sync-comments') {
        event.waitUntil(syncComments());
    }
});

async function syncComments() {
    const db = await openDB();
    const tx = db.transaction('pending-comments', 'readonly');
    const comments = await tx.objectStore('pending-comments').getAll();

    for (const comment of comments) {
        try {
            await fetch('/wp-comments-post.php', {
                method: 'POST',
                body: new URLSearchParams(comment)
            });

            // Remove from pending
            const deleteTx = db.transaction('pending-comments', 'readwrite');
            await deleteTx.objectStore('pending-comments').delete(comment.id);
        } catch (error) {
            console.error('Failed to sync comment:', error);
        }
    }
}

AMP Implementation

WordPress AMP Setup

// AMP implementation for WordPress
class WordPress_AMP_Handler {

    public function __construct() {
        add_action('init', [$this, 'setup_amp_support']);
        add_filter('amp_post_template_data', [$this, 'customize_amp_template']);
        add_action('amp_post_template_css', [$this, 'amp_custom_styles']);
    }

    public function setup_amp_support() {
        // Add AMP support for post types
        add_post_type_support('post', 'amp');
        add_post_type_support('page', 'amp');

        // Custom AMP endpoints
        add_rewrite_endpoint('amp', EP_PERMALINK);
    }

    public function customize_amp_template($data) {
        // Add custom data to AMP template
        $data['site_icon_url'] = get_site_icon_url();
        $data['nav_menu'] = $this->get_amp_menu();

        return $data;
    }

    public function amp_custom_styles() {
        ?>
        /* AMP Custom Styles */
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            line-height: 1.6;
            padding: 1rem;
        }

        .amp-wp-header {
            background-color: #0073aa;
            color: white;
            padding: 1rem;
            text-align: center;
        }

        .amp-wp-article-content img {
            max-width: 100%;
            height: auto;
        }

        /* Mobile-optimized typography */
        .amp-wp-article-content {
            font-size: 18px;
            line-height: 1.8;
        }

        /* Touch-friendly links */
        a {
            color: #0073aa;
            text-decoration: none;
            padding: 0.25rem;
            margin: -0.25rem;
        }

        /* Optimized lists */
        ul, ol {
            padding-left: 1.5rem;
        }

        /* Code blocks */
        pre {
            overflow-x: auto;
            background: #f5f5f5;
            padding: 1rem;
            border-radius: 4px;
        }
        <?php
    }

    private function get_amp_menu() {
        // Generate AMP-compatible menu
        $menu_items = wp_get_nav_menu_items('primary');
        $amp_menu = '<nav class="amp-nav"><ul>';

        foreach ($menu_items as $item) {
            $amp_menu .= sprintf(
                '<li><a href="%s">%s</a></li>',
                esc_url($item->url),
                esc_html($item->title)
            );
        }

        $amp_menu .= '</ul></nav>';

        return $amp_menu;
    }
}

// AMP content filter
add_filter('the_content', function($content) {
    if (!function_exists('is_amp_endpoint') || !is_amp_endpoint()) {
        return $content;
    }

    // Convert images to amp-img
    $content = preg_replace_callback(
        '/<img([^>]+)>/i',
        function($matches) {
            preg_match('/src=["\']([^"\']+)["\']/i', $matches[1], $src);
            preg_match('/width=["\'](\d+)["\']/i', $matches[1], $width);
            preg_match('/height=["\'](\d+)["\']/i', $matches[1], $height);
            preg_match('/alt=["\']([^"\']+)["\']/i', $matches[1], $alt);

            $amp_img = sprintf(
                '<amp-img src="%s" width="%s" height="%s" alt="%s" layout="responsive"></amp-img>',
                esc_url($src[1] ?? ''),
                esc_attr($width[1] ?? '800'),
                esc_attr($height[1] ?? '600'),
                esc_attr($alt[1] ?? '')
            );

            return $amp_img;
        },
        $content
    );

    // Convert iframes to amp-iframe
    $content = preg_replace_callback(
        '/<iframe([^>]+)>/i',
        function($matches) {
            preg_match('/src=["\']([^"\']+)["\']/i', $matches[1], $src);
            preg_match('/width=["\'](\d+)["\']/i', $matches[1], $width);
            preg_match('/height=["\'](\d+)["\']/i', $matches[1], $height);

            // YouTube embeds
            if (strpos($src[1], 'youtube.com') !== false) {
                preg_match('/embed\/([a-zA-Z0-9_-]+)/', $src[1], $video_id);

                return sprintf(
                    '<amp-youtube data-videoid="%s" width="%s" height="%s" layout="responsive"></amp-youtube>',
                    esc_attr($video_id[1] ?? ''),
                    esc_attr($width[1] ?? '800'),
                    esc_attr($height[1] ?? '450')
                );
            }

            // Generic iframe
            return sprintf(
                '<amp-iframe src="%s" width="%s" height="%s" layout="responsive" sandbox="allow-scripts allow-same-origin"></amp-iframe>',
                esc_url($src[1] ?? ''),
                esc_attr($width[1] ?? '800'),
                esc_attr($height[1] ?? '600')
            );
        },
        $content
    );

    return $content;
});

new WordPress_AMP_Handler();

Testing and Monitoring

Mobile Performance Testing

// Mobile performance testing framework
class Mobile_Performance_Tester {

    private $test_results = [];

    public function run_tests() {
        $this->test_results = [
            'page_speed' => $this->test_page_speed(),
            'mobile_usability' => $this->test_mobile_usability(),
            'core_web_vitals' => $this->test_core_web_vitals(),
            'touch_targets' => $this->test_touch_targets(),
            'viewport_config' => $this->test_viewport_configuration()
        ];

        return $this->generate_report();
    }

    private function test_page_speed() {
        // Simulate mobile network conditions
        $start_time = microtime(true);

        // Test critical resources
        $critical_resources = [
            home_url() => 'Homepage',
            get_permalink(get_option('page_for_posts')) => 'Blog page',
            get_permalink(wc_get_page_id('shop')) => 'Shop page'
        ];

        $results = [];

        foreach ($critical_resources as $url => $name) {
            $response = wp_remote_get($url, [
                'timeout' => 10,
                'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15'
            ]);

            if (!is_wp_error($response)) {
                $body = wp_remote_retrieve_body($response);
                $size = strlen($body) / 1024; // KB

                $results[$name] = [
                    'size' => round($size, 2) . ' KB',
                    'load_time' => round(microtime(true) - $start_time, 2) . 's',
                    'status' => $size < 100 ? 'good' : ($size < 300 ? 'needs-improvement' : 'poor')
                ];
            }
        }

        return $results;
    }

    private function test_mobile_usability() {
        $issues = [];

        // Check viewport meta tag
        $viewport = get_option('viewport_meta_tag');
        if (!$viewport || strpos($viewport, 'width=device-width') === false) {
            $issues[] = 'Missing or incorrect viewport meta tag';
        }

        // Check font sizes
        $theme_styles = file_get_contents(get_stylesheet_directory() . '/style.css');
        if (preg_match_all('/font-size:\s*(\d+)px/i', $theme_styles, $matches)) {
            foreach ($matches[1] as $size) {
                if (intval($size) < 16) {
                    $issues[] = "Font size {$size}px is too small for mobile";
                    break;
                }
            }
        }

        // Check tap target sizes
        if (preg_match_all('/(button|a)\s*\{[^}]*height:\s*(\d+)px/i', $theme_styles, $matches)) {
            foreach ($matches[2] as $height) {
                if (intval($height) < 44) {
                    $issues[] = "Tap target height {$height}px is too small";
                    break;
                }
            }
        }

        return empty($issues) ? ['status' => 'good'] : ['status' => 'issues', 'issues' => $issues];
    }

    private function test_core_web_vitals() {
        // Simulate Core Web Vitals measurement
        return [
            'lcp' => [
                'value' => 2.3,
                'status' => 'good',
                'recommendation' => 'Optimize largest image loading'
            ],
            'fid' => [
                'value' => 85,
                'status' => 'good',
                'recommendation' => 'Continue monitoring JavaScript execution'
            ],
            'cls' => [
                'value' => 0.08,
                'status' => 'good',
                'recommendation' => 'Add size attributes to all images'
            ]
        ];
    }

    private function generate_report() {
        $overall_score = $this->calculate_overall_score();

        return [
            'score' => $overall_score,
            'grade' => $this->get_grade($overall_score),
            'test_results' => $this->test_results,
            'recommendations' => $this->generate_recommendations(),
            'timestamp' => current_time('mysql')
        ];
    }

    private function calculate_overall_score() {
        $scores = [
            'page_speed' => 30,
            'mobile_usability' => 25,
            'core_web_vitals' => 25,
            'touch_targets' => 10,
            'viewport_config' => 10
        ];

        $total = 0;

        foreach ($scores as $test => $weight) {
            if (isset($this->test_results[$test]['status'])) {
                $status = $this->test_results[$test]['status'];
                $score = $status === 'good' ? 1 : ($status === 'needs-improvement' ? 0.5 : 0);
                $total += $score * $weight;
            }
        }

        return round($total);
    }

    private function get_grade($score) {
        if ($score >= 90) return 'A';
        if ($score >= 80) return 'B';
        if ($score >= 70) return 'C';
        if ($score >= 60) return 'D';
        return 'F';
    }

    private function generate_recommendations() {
        $recommendations = [];

        foreach ($this->test_results as $test => $result) {
            if (isset($result['status']) && $result['status'] !== 'good') {
                switch ($test) {
                    case 'page_speed':
                        $recommendations[] = 'Implement lazy loading for images and videos';
                        $recommendations[] = 'Minify CSS and JavaScript files';
                        break;
                    case 'mobile_usability':
                        if (isset($result['issues'])) {
                            $recommendations = array_merge($recommendations, $result['issues']);
                        }
                        break;
                    case 'core_web_vitals':
                        foreach ($result as $metric => $data) {
                            if (isset($data['recommendation'])) {
                                $recommendations[] = $data['recommendation'];
                            }
                        }
                        break;
                }
            }
        }

        return array_unique($recommendations);
    }
}

// Run mobile performance test
$tester = new Mobile_Performance_Tester();
$report = $tester->run_tests();

Next Steps

After implementing mobile optimization strategies:

  1. Monitor Real User Metrics: Use tools like Google Analytics and Search Console to track mobile performance
  2. Test on Real Devices: Don't rely solely on emulators—test on actual mobile devices
  3. Implement Progressive Web App Features: Consider adding PWA capabilities for app-like experiences
  4. Optimize for Core Web Vitals: Focus on mobile-specific CWV improvements

For more performance optimization strategies, explore our complete WordPress Performance Optimization guide.


Last updated: July 12, 2025