Files
roi-theme/Assets/css/critical-bootstrap.css
FrankZamora d5a2fd2702 perf: defer Bootstrap CSS with critical subset inline
- Created Assets/css/critical-bootstrap.css (~10KB subset)
  Contains only Bootstrap classes used in above-the-fold components:
  container, navbar, flexbox, dropdown, spacing utilities

- Created CriticalBootstrapService (singleton)
  Injects minified critical Bootstrap in <head> at priority 0
  Output: <style id="roi-critical-bootstrap">...</style>

- Modified enqueue-scripts.php
  Bootstrap now loads with media="print" + onload="this.media='all'"
  Full 31KB Bootstrap loads async, doesn't block rendering

- Updated CriticalCSSHooksRegistrar
  Now registers both CriticalBootstrapService (priority 0)
  and CriticalCSSService (priority 1)

Flow:
1. wp_head (priority 0) → Critical Bootstrap (~10KB inline)
2. wp_head (priority 1) → Critical Component CSS (~4KB inline)
3. Bootstrap full (31KB) loads deferred, non-blocking

Expected PageSpeed improvement: ~400-600ms LCP reduction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 10:26:24 -06:00

471 lines
15 KiB
CSS

/**
* Critical Bootstrap CSS Subset
*
* Contiene SOLO las clases Bootstrap usadas en componentes above-the-fold:
* - TopNotificationBar
* - Navbar
* - Hero
*
* Esto permite diferir la carga del Bootstrap completo (31KB)
* mientras se renderiza el contenido crítico inmediatamente.
*
* @version 5.3.2-subset
* @see Inc/enqueue-scripts.php - Bootstrap diferido
* @see Shared/Infrastructure/Services/CriticalBootstrapService.php
*/
/* ==========================================================================
BOX SIZING & RESETS (Bootstrap Reboot crítico)
========================================================================== */
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: var(--bs-body-font-family, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif);
font-size: var(--bs-body-font-size, 1rem);
font-weight: var(--bs-body-font-weight, 400);
line-height: var(--bs-body-line-height, 1.5);
color: var(--bs-body-color, #212529);
background-color: var(--bs-body-bg, #fff);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
}
a {
color: var(--bs-link-color, #0d6efd);
text-decoration: underline;
}
a:hover {
color: var(--bs-link-hover-color, #0a58ca);
}
img, svg {
vertical-align: middle;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
/* ==========================================================================
CONTAINER (Layout crítico)
========================================================================== */
.container,
.container-fluid {
--bs-gutter-x: 1.5rem;
--bs-gutter-y: 0;
width: 100%;
padding-right: calc(var(--bs-gutter-x) * 0.5);
padding-left: calc(var(--bs-gutter-x) * 0.5);
margin-right: auto;
margin-left: auto;
}
@media (min-width: 576px) {
.container { max-width: 540px; }
}
@media (min-width: 768px) {
.container { max-width: 720px; }
}
@media (min-width: 992px) {
.container { max-width: 960px; }
}
@media (min-width: 1200px) {
.container { max-width: 1140px; }
}
@media (min-width: 1400px) {
.container { max-width: 1320px; }
}
/* ==========================================================================
FLEXBOX UTILITIES (Layout crítico)
========================================================================== */
.d-flex {
display: flex !important;
}
.d-none {
display: none !important;
}
.d-block {
display: block !important;
}
.flex-wrap {
flex-wrap: wrap !important;
}
.justify-content-center {
justify-content: center !important;
}
.justify-content-between {
justify-content: space-between !important;
}
.align-items-center {
align-items: center !important;
}
.gap-2 {
gap: 0.5rem !important;
}
/* ==========================================================================
SPACING UTILITIES (Margin/Padding críticos)
========================================================================== */
.mb-0 { margin-bottom: 0 !important; }
.mb-2 { margin-bottom: 0.5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.me-1 { margin-right: 0.25rem !important; }
.me-2 { margin-right: 0.5rem !important; }
.ms-2 { margin-left: 0.5rem !important; }
.ms-3 { margin-left: 1rem !important; }
.py-3 {
padding-top: 1rem !important;
padding-bottom: 1rem !important;
}
/* ==========================================================================
NAVBAR COMPONENT (Crítico - Above the fold)
========================================================================== */
.navbar {
--bs-navbar-padding-x: 0;
--bs-navbar-padding-y: 0.5rem;
--bs-navbar-color: rgba(255, 255, 255, 0.55);
--bs-navbar-hover-color: rgba(255, 255, 255, 0.75);
--bs-navbar-disabled-color: rgba(255, 255, 255, 0.25);
--bs-navbar-active-color: #fff;
--bs-navbar-brand-padding-y: 0.3125rem;
--bs-navbar-brand-margin-end: 1rem;
--bs-navbar-brand-font-size: 1.25rem;
--bs-navbar-brand-color: #fff;
--bs-navbar-brand-hover-color: #fff;
--bs-navbar-nav-link-padding-x: 0.5rem;
--bs-navbar-toggler-padding-y: 0.25rem;
--bs-navbar-toggler-padding-x: 0.75rem;
--bs-navbar-toggler-font-size: 1.25rem;
--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
--bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1);
--bs-navbar-toggler-border-radius: var(--bs-border-radius, 0.375rem);
--bs-navbar-toggler-focus-width: 0.25rem;
--bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out;
position: relative;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x);
}
.navbar > .container,
.navbar > .container-fluid {
display: flex;
flex-wrap: inherit;
align-items: center;
justify-content: space-between;
}
.navbar-brand {
padding-top: var(--bs-navbar-brand-padding-y);
padding-bottom: var(--bs-navbar-brand-padding-y);
margin-right: var(--bs-navbar-brand-margin-end);
font-size: var(--bs-navbar-brand-font-size);
color: var(--bs-navbar-brand-color);
text-decoration: none;
white-space: nowrap;
}
.navbar-brand:hover,
.navbar-brand:focus {
color: var(--bs-navbar-brand-hover-color);
}
.navbar-nav {
--bs-nav-link-padding-x: 0;
--bs-nav-link-padding-y: 0.5rem;
--bs-nav-link-color: var(--bs-navbar-color);
--bs-nav-link-hover-color: var(--bs-navbar-hover-color);
--bs-nav-link-disabled-color: var(--bs-navbar-disabled-color);
display: flex;
flex-direction: column;
padding-left: 0;
margin-bottom: 0;
list-style: none;
}
.navbar-nav .nav-link {
padding-right: 0;
padding-left: 0;
color: var(--bs-nav-link-color);
}
.navbar-nav .nav-link:hover,
.navbar-nav .nav-link:focus {
color: var(--bs-nav-link-hover-color);
}
.navbar-nav .nav-link.active {
color: var(--bs-navbar-active-color);
}
.nav-link {
display: block;
padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);
font-size: var(--bs-nav-link-font-size);
font-weight: var(--bs-nav-link-font-weight);
color: var(--bs-nav-link-color);
text-decoration: none;
background: 0 0;
border: 0;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
}
.nav-item {
margin-bottom: 0;
}
.navbar-toggler {
padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);
font-size: var(--bs-navbar-toggler-font-size);
line-height: 1;
color: var(--bs-navbar-color);
background-color: transparent;
border: var(--bs-border-width, 1px) solid var(--bs-navbar-toggler-border-color);
border-radius: var(--bs-navbar-toggler-border-radius);
transition: var(--bs-navbar-toggler-transition);
}
.navbar-toggler:hover {
text-decoration: none;
}
.navbar-toggler:focus {
text-decoration: none;
outline: 0;
box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width);
}
.navbar-toggler-icon {
display: inline-block;
width: 1.5em;
height: 1.5em;
vertical-align: middle;
background-image: var(--bs-navbar-toggler-icon-bg);
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
}
.navbar-dark,
.navbar[data-bs-theme="dark"] {
--bs-navbar-color: rgba(255, 255, 255, 0.55);
--bs-navbar-hover-color: rgba(255, 255, 255, 0.75);
--bs-navbar-disabled-color: rgba(255, 255, 255, 0.25);
--bs-navbar-active-color: #fff;
--bs-navbar-brand-color: #fff;
--bs-navbar-brand-hover-color: #fff;
--bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1);
--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
/* ==========================================================================
COLLAPSE COMPONENT (Navbar mobile)
========================================================================== */
.collapse:not(.show) {
display: none;
}
.navbar-collapse {
flex-basis: 100%;
flex-grow: 1;
align-items: center;
}
/* ==========================================================================
DROPDOWN COMPONENT (Navbar submenus)
========================================================================== */
.dropdown {
position: relative;
}
.dropdown-toggle {
white-space: nowrap;
}
.dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
}
.dropdown-menu {
--bs-dropdown-zindex: 1000;
--bs-dropdown-min-width: 10rem;
--bs-dropdown-padding-x: 0;
--bs-dropdown-padding-y: 0.5rem;
--bs-dropdown-spacer: 0.125rem;
--bs-dropdown-font-size: 1rem;
--bs-dropdown-color: var(--bs-body-color, #212529);
--bs-dropdown-bg: var(--bs-body-bg, #fff);
--bs-dropdown-border-color: var(--bs-border-color-translucent, rgba(0,0,0,.175));
--bs-dropdown-border-radius: var(--bs-border-radius, 0.375rem);
--bs-dropdown-border-width: var(--bs-border-width, 1px);
--bs-dropdown-inner-border-radius: calc(var(--bs-border-radius, 0.375rem) - var(--bs-border-width, 1px));
--bs-dropdown-divider-bg: var(--bs-border-color-translucent, rgba(0,0,0,.175));
--bs-dropdown-divider-margin-y: 0.5rem;
--bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-dropdown-link-color: var(--bs-body-color, #212529);
--bs-dropdown-link-hover-color: var(--bs-body-color, #212529);
--bs-dropdown-link-hover-bg: var(--bs-tertiary-bg, #f8f9fa);
--bs-dropdown-link-active-color: #fff;
--bs-dropdown-link-active-bg: #0d6efd;
--bs-dropdown-link-disabled-color: var(--bs-tertiary-color, #adb5bd);
--bs-dropdown-item-padding-x: 1rem;
--bs-dropdown-item-padding-y: 0.25rem;
--bs-dropdown-header-color: #6c757d;
--bs-dropdown-header-padding-x: 1rem;
--bs-dropdown-header-padding-y: 0.5rem;
position: absolute;
z-index: var(--bs-dropdown-zindex);
display: none;
min-width: var(--bs-dropdown-min-width);
padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);
margin: 0;
font-size: var(--bs-dropdown-font-size);
color: var(--bs-dropdown-color);
text-align: left;
list-style: none;
background-color: var(--bs-dropdown-bg);
background-clip: padding-box;
border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);
border-radius: var(--bs-dropdown-border-radius);
}
.dropdown-menu.show {
display: block;
}
.dropdown-item {
display: block;
width: 100%;
padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);
clear: both;
font-weight: 400;
color: var(--bs-dropdown-link-color);
text-align: inherit;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border: 0;
}
.dropdown-item:hover,
.dropdown-item:focus {
color: var(--bs-dropdown-link-hover-color);
background-color: var(--bs-dropdown-link-hover-bg);
}
.dropdown-item.active,
.dropdown-item:active {
color: var(--bs-dropdown-link-active-color);
text-decoration: none;
background-color: var(--bs-dropdown-link-active-bg);
}
/* ==========================================================================
TEXT UTILITIES
========================================================================== */
.text-decoration-underline {
text-decoration: underline !important;
}
/* ==========================================================================
BUTTON CLOSE (Dismiss notification)
========================================================================== */
.btn-close {
--bs-btn-close-color: #000;
--bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e");
--bs-btn-close-opacity: 0.5;
--bs-btn-close-hover-opacity: 0.75;
--bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
--bs-btn-close-focus-opacity: 1;
--bs-btn-close-disabled-opacity: 0.25;
--bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%);
box-sizing: content-box;
width: 1em;
height: 1em;
padding: 0.25em 0.25em;
color: var(--bs-btn-close-color);
background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat;
border: 0;
border-radius: 0.375rem;
opacity: var(--bs-btn-close-opacity);
}
.btn-close:hover {
color: var(--bs-btn-close-color);
text-decoration: none;
opacity: var(--bs-btn-close-hover-opacity);
}
.btn-close:focus {
outline: 0;
box-shadow: var(--bs-btn-close-focus-shadow);
opacity: var(--bs-btn-close-focus-opacity);
}
.btn-close-white {
filter: var(--bs-btn-close-white-filter);
}
/* ==========================================================================
RESPONSIVE BREAKPOINTS (navbar-expand-lg)
========================================================================== */
@media (min-width: 992px) {
.navbar-expand-lg {
flex-wrap: nowrap;
justify-content: flex-start;
}
.navbar-expand-lg .navbar-nav {
flex-direction: row;
}
.navbar-expand-lg .navbar-nav .dropdown-menu {
position: absolute;
}
.navbar-expand-lg .navbar-nav .nav-link {
padding-right: var(--bs-navbar-nav-link-padding-x);
padding-left: var(--bs-navbar-nav-link-padding-x);
}
.navbar-expand-lg .navbar-collapse {
display: flex !important;
flex-basis: auto;
}
.navbar-expand-lg .navbar-toggler {
display: none;
}
.d-lg-block { display: block !important; }
.d-lg-none { display: none !important; }
.mb-lg-0 { margin-bottom: 0 !important; }
}
@media (max-width: 991.98px) {
.navbar-expand-lg > .container,
.navbar-expand-lg > .container-fluid {
padding-right: 0;
padding-left: 0;
}
}
/* ==========================================================================
RESPONSIVE DISPLAY UTILITIES (md breakpoint)
========================================================================== */
@media (min-width: 768px) {
.d-md-block { display: block !important; }
.d-md-none { display: none !important; }
}