Skip to main content

Custom CSS Injection in SmartUI


Custom CSS injection is a specialized feature in SmartUI that allows you to apply test-only styles during snapshot capture without modifying your application code. This feature enables you to stabilize visual tests by normalizing dynamic content, enforcing consistent styling across environments, and masking sensitive information—all while keeping your visual testing logic centralized and maintainable.

Why Custom CSS Matters

  1. Stabilize Visual Diffs: Hide or normalize volatile UI elements (ads, rotating banners, dynamic counters, time-based content) to reduce false positives in your visual regression tests.

  2. Environment Parity: Enforce consistent fonts, themes, and spacing across different operating systems, browsers, and devices for predictable rendering and accurate comparisons.

  3. Non-Intrusive Testing: Avoid modifying application code or injecting styles directly in test scripts. Keep all visual adjustments in a centralized configuration, making it easier to maintain and review.

  4. Enhanced Test Reliability: Reduce test flakiness by masking dynamic elements that change between test runs, ensuring your visual tests focus on meaningful UI changes rather than transient content.

Prerequisites

Before using the Custom CSS feature, ensure you meet the following requirements:

  • Node.js v20.3+ (recommended)
  • SmartUI CLI v4.1.40+ (supports both exec and capture commands)
  • Valid PROJECT_TOKEN configured in your environment

Custom CSS Configuration in SmartUI

SmartUI supports two methods for providing custom CSS: file path (recommended for maintainability) and embedded string (quick and portable). Choose the method that best fits your workflow.

The file path method is recommended for larger stylesheets and team collaboration. Create a separate CSS file in your project and reference it in your SmartUI configuration.

Steps:

  1. Create a CSS file (e.g., visual-test-styles.css or code.css) in your project directory.

  2. Add your CSS rules to the file:

/* General samples: pick what suits your use case */

/* 1) Normalize fonts for consistent rendering */
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }

/* 2) Hide flaky, time-based banners or rotating promos */
.promo-banner, [data-testid="rotating-banner"] { display: none !important; }

/* 3) Freeze dynamic badges/counters that change every run */
[data-badge], .cart-count { visibility: hidden; }
  1. Reference the file path in your SmartUI configuration:
{
"web": {
"browsers": ["chrome"],
"viewports": [[1440, 900]]
},
"enableJavaScript": true,
"customCSS": "./visual-test-styles.css"
}

Method 2: Embedded String

The embedded string method is useful for quick edits and single-use CSS rules. Provide the CSS directly as a JSON string value.

Important Notes:

  • Keep CSS single-line to avoid JSON parsing issues
  • Escape quotes properly (' or \")
  • Use \n for newlines if needed (though single-line is preferred)
{
"web": {
"browsers": ["chrome"],
"viewports": [[1440, 900]]
},
"enableJavaScript": true,
"customCSS": "body{font-family:'Inter',sans-serif!important;} .banner,.ad{display:none!important;}"
}

Configuration Guidelines

  • Placement: The customCSS property must be placed at the top level of your configuration file (not inside the web object). Placing it inside web will result in a "must NOT have additional properties" error.

  • Path Resolution: File paths are relative to your project root directory. Ensure the CSS file exists at the specified path. Files outside the project directory may not be accessible.

  • CSS Specificity: Your custom CSS will be injected at snapshot time. Use !important declarations if you need to override existing styles. If CSS is overridden by inline styles, increase selector specificity (e.g., .target-class#specific-id .target-class).

  • Multi-line CSS: For multi-line CSS, prefer the file path method to avoid JSON escaping complexity. If using embedded strings, keep rules compact and single-line.

  • Method Selection: Choose the file path method for larger stylesheets and team collaboration. Use embedded strings only for quick, single-use CSS rules.

  • CSS Organization: Keep your CSS snapshot-specific—target only elements that need stabilization or normalization. Avoid broad selectors that might affect unintended elements.

  • JSON Escaping: When using embedded strings, escape quotes properly:

    • Use single quotes within CSS strings: "body{font-family:'Inter',sans-serif;}"
    • Or escape double quotes: "body{font-family:\"Inter\",sans-serif;}"
  • Selector Verification: If the CSS Injection Report shows "no elements found" or "invalid selector" errors:

    • Verify the element exists at snapshot time (use browser dev tools)
    • Check selector specificity—it may need to be more specific or less specific
    • Consider timing issues—ensure the element is rendered before snapshot capture
    • Check the CSS Injection Report in logs for detailed feedback
  • CLI Version: Ensure SmartUI CLI v4.1.40+ is installed. You can verify this by running npx smartui --version. Older versions may not support the customCSS feature.

  • Waiting for UI Readiness: If you need to wait for UI elements to be ready before snapshots, add these options to your configuration:

    {
    "waitForTimeout": 2000,
    "waitForPageRender": 5000,
    "customCSS": "./visual-test-styles.css"
    }

Known Limitations

The Custom CSS feature has the following limitations:

  • Specificity Constraints: Custom CSS can be overridden by higher-specificity inline styles. Increase your selector specificity or use !important declarations if needed.

  • Snapshot-Only Application: CSS is only injected during snapshot capture and does not affect your application's runtime behavior.

  • File Path Resolution: Ensure CSS file paths are correctly specified relative to your project root. Files outside the project directory may not be accessible.


Use Cases for Custom CSS

The custom CSS feature is particularly valuable in the following scenarios:

/* Hide elements that change between runs */
.ad, .banner, #cookie-consent { display: none !important; }

/* Replace volatile text with a constant */
[data-testid="rotating-copy"] { font-size: 0 !important; }
[data-testid="rotating-copy"]::after { content: "Stable text for snapshots"; }

Minimal Configuration Templates

File Path Template

{
"web": {
"browsers": ["chrome"],
"viewports": [[1440, 900]]
},
"customCSS": "./path/to/visual-test-styles.css"
}

Embedded String Template

{
"web": {
"browsers": ["chrome"],
"viewports": [[1440, 900]]
},
"customCSS": "body{font-family:'Inter',sans-serif!important;} .ad,.banner{display:none!important;}"
}

Additional Resources


Test across 3000+ combinations of browsers, real devices & OS.

Book Demo

Help and Support

Related Articles