diff --git a/Inc/critical-css.php b/Inc/critical-css.php deleted file mode 100644 index 7fe93ec5..00000000 --- a/Inc/critical-css.php +++ /dev/null @@ -1,426 +0,0 @@ - - * 2. Main stylesheet is loaded asynchronously after page load - * 3. Improves Core Web Vitals by reducing render-blocking CSS - * - * @package ROI_Theme - * @since 1.0.0 - */ - -// Exit if accessed directly. -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - -/** - * Check if Critical CSS is enabled - * - * @since 1.0.0 - * @return bool - */ -function roi_is_critical_css_enabled() { - return get_theme_mod( 'roi_enable_critical_css', false ); -} - -/** - * Get Critical CSS Content - * - * Returns the critical CSS for the current page type. - * You can customize this based on page types (home, single, archive, etc.) - * - * @since 1.0.0 - * @return string Critical CSS content - */ -function roi_get_critical_css() { - // Define critical CSS based on page type - $critical_css = ''; - - // Get transient to cache critical CSS - $transient_key = 'roi_critical_css_' . roi_get_page_type(); - $cached_css = get_transient( $transient_key ); - - if ( false !== $cached_css ) { - return $cached_css; - } - - // Generate critical CSS based on page type - if ( is_front_page() || is_home() ) { - $critical_css = roi_get_home_critical_css(); - } elseif ( is_single() ) { - $critical_css = roi_get_single_critical_css(); - } elseif ( is_archive() || is_category() || is_tag() ) { - $critical_css = roi_get_archive_critical_css(); - } else { - $critical_css = roi_get_default_critical_css(); - } - - // Cache for 24 hours - set_transient( $transient_key, $critical_css, DAY_IN_SECONDS ); - - return $critical_css; -} - -/** - * Get current page type for caching - * - * @since 1.0.0 - * @return string Page type identifier - */ -function roi_get_page_type() { - if ( is_front_page() ) { - return 'home'; - } elseif ( is_single() ) { - return 'single'; - } elseif ( is_archive() ) { - return 'archive'; - } elseif ( is_search() ) { - return 'search'; - } elseif ( is_404() ) { - return '404'; - } else { - return 'page'; - } -} - -/** - * Critical CSS for Homepage - * - * @since 1.0.0 - * @return string - */ -function roi_get_home_critical_css() { - return ' - /* Reset and Base */ - *,*::before,*::after{box-sizing:border-box} - body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.6;color:#333;background:#fff} - img{max-width:100%;height:auto;display:block} - a{color:#0066cc;text-decoration:none} - - /* Header */ - .site-header{background:#fff;border-bottom:1px solid #e5e5e5;position:sticky;top:0;z-index:1000} - .site-header .container{max-width:1200px;margin:0 auto;padding:1rem} - .site-branding{display:flex;align-items:center} - .site-title{margin:0;font-size:1.5rem;font-weight:700} - - /* Hero Section */ - .hero-section{padding:3rem 1rem;text-align:center;background:#f8f9fa} - .hero-title{font-size:2.5rem;margin:0 0 1rem;font-weight:700;line-height:1.2} - .hero-description{font-size:1.125rem;color:#666;max-width:600px;margin:0 auto} - - /* Container */ - .container{max-width:1200px;margin:0 auto;padding:0 1rem} - - /* Featured Posts Grid */ - .featured-posts{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:2rem;margin:2rem 0} - .post-card{background:#fff;border:1px solid #e5e5e5;border-radius:8px;overflow:hidden;transition:transform .2s} - .post-card:hover{transform:translateY(-4px)} - - /* Skip to content */ - .skip-link{position:absolute;left:-999px;top:0;background:#0066cc;color:#fff;padding:.5rem 1rem;text-decoration:none} - .skip-link:focus{left:0} - '; -} - -/** - * Critical CSS for Single Post/Page - * - * @since 1.0.0 - * @return string - */ -function roi_get_single_critical_css() { - return ' - /* Reset and Base */ - *,*::before,*::after{box-sizing:border-box} - body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.6;color:#333;background:#fff} - img{max-width:100%;height:auto;display:block} - a{color:#0066cc;text-decoration:none} - h1,h2,h3,h4,h5,h6{margin:1.5rem 0 1rem;font-weight:700;line-height:1.3} - h1{font-size:2.5rem} - h2{font-size:2rem} - h3{font-size:1.5rem} - p{margin:0 0 1.5rem} - - /* Header */ - .site-header{background:#fff;border-bottom:1px solid #e5e5e5;position:sticky;top:0;z-index:1000} - .site-header .container{max-width:1200px;margin:0 auto;padding:1rem} - - /* Article */ - .entry-header{margin:2rem 0} - .entry-title{font-size:2.5rem;margin:0 0 1rem;line-height:1.2} - .entry-meta{color:#666;font-size:.875rem} - .entry-content{max-width:800px;margin:0 auto;font-size:1.125rem;line-height:1.8} - .featured-image{margin:2rem 0} - - /* Container */ - .container{max-width:1200px;margin:0 auto;padding:0 1rem} - - /* Skip to content */ - .skip-link{position:absolute;left:-999px;top:0;background:#0066cc;color:#fff;padding:.5rem 1rem;text-decoration:none} - .skip-link:focus{left:0} - '; -} - -/** - * Critical CSS for Archive Pages - * - * @since 1.0.0 - * @return string - */ -function roi_get_archive_critical_css() { - return ' - /* Reset and Base */ - *,*::before,*::after{box-sizing:border-box} - body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.6;color:#333;background:#fff} - img{max-width:100%;height:auto;display:block} - a{color:#0066cc;text-decoration:none} - - /* Header */ - .site-header{background:#fff;border-bottom:1px solid #e5e5e5;position:sticky;top:0;z-index:1000} - .site-header .container{max-width:1200px;margin:0 auto;padding:1rem} - - /* Archive Header */ - .archive-header{padding:2rem 1rem;background:#f8f9fa;border-bottom:1px solid #e5e5e5} - .archive-title{margin:0;font-size:2rem;font-weight:700} - .archive-description{margin:1rem 0 0;color:#666;font-size:1.125rem} - - /* Posts Grid */ - .posts-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:2rem;margin:2rem 0} - .post-card{background:#fff;border:1px solid #e5e5e5;border-radius:8px;overflow:hidden} - - /* Container */ - .container{max-width:1200px;margin:0 auto;padding:0 1rem} - - /* Skip to content */ - .skip-link{position:absolute;left:-999px;top:0;background:#0066cc;color:#fff;padding:.5rem 1rem;text-decoration:none} - .skip-link:focus{left:0} - '; -} - -/** - * Critical CSS for Default Pages - * - * @since 1.0.0 - * @return string - */ -function roi_get_default_critical_css() { - return ' - /* Reset and Base */ - *,*::before,*::after{box-sizing:border-box} - body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.6;color:#333;background:#fff} - img{max-width:100%;height:auto;display:block} - a{color:#0066cc;text-decoration:none} - - /* Header */ - .site-header{background:#fff;border-bottom:1px solid #e5e5e5;position:sticky;top:0;z-index:1000} - .site-header .container{max-width:1200px;margin:0 auto;padding:1rem} - - /* Container */ - .container{max-width:1200px;margin:0 auto;padding:0 1rem} - - /* Content */ - .site-content{min-height:50vh;padding:2rem 0} - - /* Skip to content */ - .skip-link{position:absolute;left:-999px;top:0;background:#0066cc;color:#fff;padding:.5rem 1rem;text-decoration:none} - .skip-link:focus{left:0} - '; -} - -/** - * Output Critical CSS inline in head - * - * @since 1.0.0 - */ -function roi_output_critical_css() { - if ( ! roi_is_critical_css_enabled() ) { - return; - } - - $critical_css = roi_get_critical_css(); - - if ( empty( $critical_css ) ) { - return; - } - - // Minify CSS (remove extra whitespace and newlines) - $critical_css = preg_replace( '/\s+/', ' ', $critical_css ); - $critical_css = trim( $critical_css ); - - // Output inline critical CSS - echo '' . "\n"; -} -add_action( 'wp_head', 'roi_output_critical_css', 1 ); - -/** - * Load main stylesheet asynchronously when critical CSS is enabled - * - * @since 1.0.0 - */ -function roi_async_main_stylesheet() { - if ( ! roi_is_critical_css_enabled() ) { - return; - } - - // Dequeue main stylesheet to prevent render-blocking - wp_dequeue_style( 'roi-theme-style' ); - - // Enqueue with media="print" and onload to load asynchronously - wp_enqueue_style( - 'roi-theme-style-async', - get_stylesheet_uri(), - array(), - ROI_VERSION, - 'print' - ); - - // Add onload attribute to switch media to "all" - add_filter( 'style_loader_tag', 'roi_add_async_attribute', 10, 2 ); -} -add_action( 'wp_enqueue_scripts', 'roi_async_main_stylesheet', 999 ); - -/** - * Add async loading attributes to stylesheet - * - * @since 1.0.0 - * @param string $html The link tag for the enqueued style. - * @param string $handle The style's registered handle. - * @return string Modified link tag - */ -function roi_add_async_attribute( $html, $handle ) { - if ( 'roi-theme-style-async' !== $handle ) { - return $html; - } - - // Add onload attribute to switch media to "all" - $html = str_replace( - "media='print'", - "media='print' onload=\"this.media='all'\"", - $html - ); - - // Add noscript fallback - $html .= ''; - - return $html; -} - -/** - * Add Customizer setting for Critical CSS - * - * @since 1.0.0 - * @param WP_Customize_Manager $wp_customize Theme Customizer object. - */ -function roi_critical_css_customizer( $wp_customize ) { - // Add Performance section - $wp_customize->add_section( - 'roi_performance', - array( - 'title' => __( 'Performance Optimization', 'roi-theme' ), - 'priority' => 130, - ) - ); - - // Critical CSS Enable/Disable - $wp_customize->add_setting( - 'roi_enable_critical_css', - array( - 'default' => false, - 'sanitize_callback' => 'roi_sanitize_checkbox', - 'transport' => 'refresh', - ) - ); - - $wp_customize->add_control( - 'roi_enable_critical_css', - array( - 'label' => __( 'Enable Critical CSS', 'roi-theme' ), - 'description' => __( 'Inline critical CSS and load main stylesheet asynchronously. This can improve Core Web Vitals but may cause a flash of unstyled content (FOUC). Test thoroughly before enabling in production.', 'roi-theme' ), - 'section' => 'roi_performance', - 'type' => 'checkbox', - ) - ); -} -add_action( 'customize_register', 'roi_critical_css_customizer' ); - -/** - * Clear critical CSS cache when theme is updated - * - * @since 1.0.0 - */ -function roi_clear_critical_css_cache() { - $page_types = array( 'home', 'single', 'archive', 'search', '404', 'page' ); - - foreach ( $page_types as $type ) { - delete_transient( 'roi_critical_css_' . $type ); - } -} -add_action( 'after_switch_theme', 'roi_clear_critical_css_cache' ); -add_action( 'customize_save_after', 'roi_clear_critical_css_cache' ); - -/** - * Output Hero Section Critical CSS - * - * This CSS is ALWAYS injected in the to prevent CLS (Cumulative Layout Shift) - * by reserving space for the hero section BEFORE it renders. - * - * The min-height values match the actual rendered height (~260px on desktop) - * to prevent any layout shift when the dynamic CSS loads. - * - * @since 1.0.21 - * @see Public/Hero/Infrastructure/Ui/HeroRenderer.php - */ -function roi_output_hero_critical_css() { - // Only output on single posts where hero is displayed - if ( ! is_single() ) { - return; - } - - // Check if hero is enabled (read from database) - $is_enabled = roi_get_component_setting( 'hero', 'visibility', 'is_enabled', true ); - if ( ! $is_enabled ) { - return; - } - - $critical_css = ' - /* Hero Critical CSS - Prevent CLS */ - .hero-section { - min-height: 260px; - background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%); - padding: 3rem 0; - margin-bottom: 1.5rem; - box-sizing: border-box; - } - .hero-section__title { - min-height: 3.5rem; - margin-bottom: 0; - } - .hero-section__badge { - min-height: 32px; - display: inline-block; - } - @media (max-width: 767.98px) { - .hero-section { - min-height: 200px; - } - .hero-section__title { - min-height: 2.5rem; - } - } - '; - - // Minify CSS - $critical_css = preg_replace( '/\s+/', ' ', $critical_css ); - $critical_css = trim( $critical_css ); - - echo '' . "\n"; -} -add_action( 'wp_head', 'roi_output_hero_critical_css', 2 ); diff --git a/functions.php b/functions.php index 550a7f6f..09ab3db2 100644 --- a/functions.php +++ b/functions.php @@ -42,7 +42,7 @@ require_once get_template_directory() . '/Inc/enqueue-scripts.php'; // ELIMINADO: Inc/customizer-fonts.php (FASE 6 - Clean Architecture) require_once get_template_directory() . '/Inc/seo.php'; require_once get_template_directory() . '/Inc/performance.php'; -require_once get_template_directory() . '/Inc/critical-css.php'; +// ELIMINADO: Inc/critical-css.php (CSS crítico ahora viene de CriticalCSSService.php) require_once get_template_directory() . '/Inc/image-optimization.php'; require_once get_template_directory() . '/Inc/template-functions.php'; require_once get_template_directory() . '/Inc/template-tags.php';