Customization

Widget Styling

Customize the look and feel of the SearchX widget to match your brand identity.


Overview

SearchX provides a comprehensive theming system based on CSS custom properties (variables). You can create a custom theme file that overrides the default styles, giving you full control over colors, typography, border radius, shadows, and individual component appearance.


Loading a Custom Theme

Create a CSS file and pass its URL to the SDK via the customCSSUrl option:

SearchXSDK.init({
  // ... other config
  customCSSUrl: '/path/to/your/client-theme.css',
});

The custom CSS file is loaded after the default styles, so your overrides take effect without needing !important in most cases.


Theme Structure

A SearchX theme is organized into sections. You only need to override the properties you want to change — everything else falls back to the defaults.

1. Color Tokens

These are the foundational colors used across the entire widget. Each color has a full scale from 50 (lightest) to 950 (darkest).

:root {
  /* Neutral */
  --searchx-white: #ffffff;
  --searchx-black: #111111;

  /* Primary scale — your brand color */
  --searchx-primary-50: #fff5f5;
  --searchx-primary-100: #ffeaea;
  --searchx-primary-200: #ffd6d6;
  --searchx-primary-300: #ffb4b4;
  --searchx-primary-400: #f28c8c;
  --searchx-primary-500: #cc5b5b;
  --searchx-primary-600: #a20808; /* Base accent — used for buttons, active states */
  --searchx-primary-700: #7f0606;
  --searchx-primary-800: #5f0404;
  --searchx-primary-900: #3e0202;
  --searchx-primary-950: #240101;

  /* Gray scale */
  --searchx-gray-50: #fafafa;
  --searchx-gray-100: #f5f5f5;
  --searchx-gray-200: #e5e5e5;
  --searchx-gray-300: #d4d4d4;
  --searchx-gray-400: #a3a3a3;
  --searchx-gray-500: #737373;
  --searchx-gray-600: #525252;
  --searchx-gray-700: #404040;
  --searchx-gray-800: #262626;
  --searchx-gray-900: #171717;
  --searchx-gray-950: #0a0a0a;

  /* Status */
  --searchx-danger-color: #dc2626;
}

2. Non-Color Tokens

Control typography, border radius, shadows, and transitions globally.

:root {
  /* Typography */
  --sx-font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;
  --sx-font-size-base: 16px;

  /* Border radius */
  --sx-radius-sm: 6px;
  --sx-radius-md: 12px;
  --sx-radius-pill: 999px;

  /* Borders */
  --sx-border-width: 1px;
  --sx-border-color: var(--searchx-gray-300);

  /* Shadows */
  --sx-shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.06);
  --sx-shadow-md: 0 8px 24px rgba(0, 0, 0, 0.1);

  /* Transitions */
  --sx-transition: 200ms ease;
}

Component CSS Classes

All SearchX components use BEM-style class names scoped under .searchx__container.searchx__theme (search bar / popup) or .searchx__page.searchx__theme (results page).

SelectorDescription
.searchx__formSearch bar wrapper (border, background, shadow)
.searchx__inputText input container
.searchx__input inputThe actual input element
.searchx__input input::placeholderPlaceholder text
.searchx__mobile-triggerMobile search toggle button
.sx-settings__triggerSettings gear icon
.searchx__form-close-iconClear/close button

Autocomplete Popup

SelectorDescription
.searchx__popupDropdown container
.searchx__popup-results-counterResults count badge
.searchx__popup-itemIndividual suggestion row
.searchx__popup-item-imageProduct thumbnail in popup
.searchx__popup-item-titleProduct name in popup
.searchx__popup-item-pricePrice in popup
.searchx__popup-no-results-iconEmpty state icon
.searchx__popup-no-results-titleEmpty state message
.searchx__showcaseSuggested products grid

Results Page

SelectorDescription
.searchx__page-heading-titleSearch query heading
.searchx__page-heading-subtitleResults count subtitle
.searchx__page-sortingSort dropdown button
.searchx__page-resultsProduct grid container
.searchx__page-itemsAlternative product grid container

Product Cards

SelectorDescription
.searchx__page-itemCard wrapper
.searchx__page-item-image-wrapperImage area container
.searchx__page-item-image-containerImage container (for aspect ratio)
.searchx__page-item-imageProduct image
.searchx__page-item-image--hoverSecond image (hover reveal)
.searchx__page-item-detailsLink wrapper for image + info
.searchx__page-item-infoText info area below image
.searchx__page-item-brandBrand name
.searchx__page-item-titleProduct title
.searchx__page-item-priceCurrent price
.searchx__page-item-price-originalOriginal price (strikethrough)
.searchx__page-item-sizesAvailable sizes
.searchx__page-item-badgeDiscount/sale badge
.searchx__page-item-buttonAdd-to-cart button
.searchx__page-item-button.wishlistWishlist heart button
.searchx__page-item-actionsButton actions container

Facets / Filters

SelectorDescription
.searchx__facet-blockFilter group container
.searchx__facet-titleFilter group heading
.searchx__facet-itemIndividual filter option
.searchx__facet-item--activeActive/selected filter
.searchx__facet-search-inputSearch within filter
.multi-range-slider__rangePrice range slider track
.multi-range-slider__thumbPrice range slider handle

Pagination

SelectorDescription
.sx-paginationPagination container
.sx-page-arrowPrevious/Next arrows
.sx-page-pillPage number button
.sx-page-pill.is-activeCurrent page
.sx-page-ellipsisEllipsis between pages

Mobile Filters

SelectorDescription
.facet-toggle-button"Filters" toggle button
.facet-sheet__controlsFilter sheet header
.facet-sheet__labelFilter labels in sheet
.facet-sheet__selectDropdown selects in sheet
.facet-sheet__apply"Apply" button in filter sheet

Example: Minimal Monochrome Theme

A flat, square-corner aesthetic with no shadows — ideal for fashion or luxury brands.

:root {
  --searchx-primary-600: #222222;
  --searchx-primary-700: #111111;
  --searchx-primary-800: #0a0a0a;

  --sx-font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --sx-font-size-base: 14px;

  --sx-radius-sm: 0px;
  --sx-radius-md: 0px;
  --sx-radius-pill: 0px;

  --sx-shadow-sm: none;
  --sx-shadow-md: none;
}

/* Square search bar with black border */
.searchx__container.searchx__theme .searchx__form {
  border: 1px solid #000;
  border-radius: 0;
  box-shadow: none;
}

/* Uppercase placeholder */
.searchx__container.searchx__theme .searchx__input input::placeholder {
  text-transform: uppercase;
  font-size: 12px;
  letter-spacing: 0.08em;
}

/* Flat product cards with no border or shadow */
.searchx__page.searchx__theme .searchx__page-item {
  border: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}

.searchx__page.searchx__theme .searchx__page-item:hover {
  transform: none !important;
}

/* Image zoom on hover */
.searchx__page.searchx__theme .searchx__page-item-image {
  clip-path: inset(0);
  transition: transform 500ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.searchx__page.searchx__theme .searchx__page-item:hover .searchx__page-item-image {
  transform: scale(1.05);
}

/* Uppercase facet titles */
.searchx__page.searchx__theme .searchx__facet-title {
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.1em;
}

Example: Ocean Teal Theme

Override only the primary scale to switch the entire accent color:

:root {
  --searchx-primary-50: #f0fdfa;
  --searchx-primary-100: #ccfbf1;
  --searchx-primary-200: #99f6e4;
  --searchx-primary-300: #5eead4;
  --searchx-primary-400: #2dd4bf;
  --searchx-primary-500: #14b8a6;
  --searchx-primary-600: #0d9488;
  --searchx-primary-700: #0f766e;
  --searchx-primary-800: #115e59;
  --searchx-primary-900: #134e4a;
  --searchx-primary-950: #042f2e;
}

Since all components reference --searchx-primary-* tokens, a single color scale change updates buttons, active filters, hover states, pagination, and sort controls.


Controlling the Product Grid

Override the grid layout with CSS grid:

/* 4 columns on desktop, 3 on tablet, 2 on mobile */
.searchx__page.searchx__theme .searchx__page-results,
.searchx__page.searchx__theme .searchx__page-items {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px 16px;
}

@media (max-width: 1024px) {
  .searchx__page.searchx__theme .searchx__page-results,
  .searchx__page.searchx__theme .searchx__page-items {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 768px) {
  .searchx__page.searchx__theme .searchx__page-results,
  .searchx__page.searchx__theme .searchx__page-items {
    grid-template-columns: repeat(2, 1fr);
  }
}

Hover Image Swap

Show a second product image on hover using CSS:

/* Hide second image by default */
.searchx__page.searchx__theme .searchx__page-item-image--hover {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 320ms ease;
  z-index: 2;
}

/* Reveal on hover */
.searchx__page.searchx__theme .searchx__page-item:hover .searchx__page-item-image--hover {
  opacity: 1;
}

Hiding Elements

You can hide any component with CSS:

/* Hide the add-to-cart button */
.searchx__page.searchx__theme .searchx__page-item-button:not(.wishlist) {
  display: none !important;
}

/* Hide the wishlist button */
.searchx__page.searchx__theme .searchx__page-item-button.wishlist {
  display: none !important;
}

/* Hide the powered-by badge */
.searchx__powered-by {
  display: none !important;
}

Tip

When hiding elements, use !important to ensure the override applies regardless of the default theme's specificity.


Best Practices

  1. Start with tokens — Override --searchx-primary-* and --sx-* variables first. This handles 80% of theming with minimal CSS.
  2. Use the default theme as a template — Copy the default theme file and modify it rather than starting from scratch.
  3. Scope your selectors — Always prefix with .searchx__container.searchx__theme or .searchx__page.searchx__theme to avoid affecting the rest of your page.
  4. Test on mobile — The mobile filter sheet (.facet-sheet__*) and compact pagination (.sx-page-pill) have their own selectors.
  5. Respect specificity — Custom CSS loads after defaults, so equal-specificity rules win. Use !important sparingly.

Previous
Product Showcase