> ## Documentation Index
> Fetch the complete documentation index at: https://viewerdocs.planpoint.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom CSS

> Learn how to upload custom CSS to match your floor plan viewer to your brand's look and feel.

## Before You Begin

### Requirements

* Custom CSS must be enabled in your project settings (see "Enabling Custom CSS" below)
* The custom CSS file must use the correct selectors to work properly (more on this below)

### Important Note

Even after enabling Custom CSS in your settings, **you must add `?customCss=true` to your embed URLs** for the custom styles to load. Without this parameter, the viewer will use the default theme.

**Example:**

```text theme={null}
https://viewer.planpoint.io/embed/your-project?customCss=true
```

***

## Video Guide for Visual Learners

<iframe className="w-full aspect-video rounded-xl" src="https://streamable.com/o/5kgjr6" title="Planpoint KB - Forms" allowFullScreen />

***

## How to Set Up Custom CSS

### Step 1: Enable Custom CSS

1. Go to **Style & Embed**
2. Navigate to **Style** → **Custom CSS**
3. Toggle the Custom CSS feature to **Enabled**

### Step 2: Download the Default Template

Before creating your custom CSS, download our default theme template as your starting point:

1. In the **Custom CSS** settings section, click **Download Default Template**
2. Save the `planpoint-theme.css` file to your computer

**Why start with the template?** Our template includes all the correct selectors that work with Planpoint's system. Modifying it ensures your custom CSS will work properly.

### Step 3: Customize Your CSS

Open the downloaded CSS file in any text editor and make your changes. Here's what you can customize:

**Brand Colors**

* Primary and accent colors
* Status indicators (Available, Sold, Reserved)
* Background and text colors

**Typography**

* Font families
* Font sizes for different elements
* Font weights and styles

**Layout & Spacing**

* Padding and margins
* Border radius values
* Grid gaps and alignment

**Visual Effects**

* Box shadows
* Hover effects
* Transitions and animations

### Step 4: Upload Your Custom CSS

1. Return to **Style & Embed** → **Style** → **Custom CSS**
2. Click **Upload Custom CSS File**
3. Select your modified CSS file
4. Click **Save**

### Step 5: Add the URL Parameter

Update your embed code to include the `customCss=true` parameter:

**Before:**

```html theme={null}
<iframe src="https://viewer.planpoint.io/embed/your-project"></iframe>
```

**After:**

```html theme={null}
<iframe src="https://viewer.planpoint.io/embed/your-project?customCss=true"></iframe>
```

***

## Understanding CSS Selectors

### Use the Right Selectors

Our system uses CSS Modules, which means you need to target elements using specific attribute selectors and class wildcards. The default template already includes these, but here's what to know if you're adding new styles:

**✅ Correct selectors that work:**

```css theme={null}
/* Data attribute selectors for main containers */
[data-pp-embed]              /* Main embed wrapper */
[data-pp-container]          /* Inner container */
[data-pp-layout]             /* Layout container */
[data-pp-header]             /* Portal header bar */
[data-pp-cta-desktop]        /* Header CTA button (desktop) */
[data-pp-cta-mobile]         /* Header CTA button (mobile) */
[data-pp-filters]            /* Filters container */
[data-pp-filters-wrapper]    /* Filters wrapper with background */
[data-pp-glass-filters]      /* Glass-style filter variant */
[data-pp-unit-grid]          /* Unit grid */
[data-pp-unit-list]          /* Unit list table */
[data-pp-unit-view]          /* Unit view container */
[data-pp-amenity-view]       /* Amenity view container */
[data-pp-commerce-view]      /* Commerce view container */
[data-pp-canvas]             /* Canvas/floor plan area */
[data-pp-modal]              /* Modal containers */

/* Scope-specific selectors */
[data-pp-scope="project"]    /* Project view */
[data-pp-scope="floor"]      /* Floor view */
[data-pp-scope="unit"]       /* Unit detail view */

/* Class wildcard selectors for nested elements */
[data-pp-embed] [class*="unitTile"]           /* Unit cards */
[data-pp-embed] [class*="unitTileBody"]       /* Card body */
[data-pp-embed] [class*="unitTilePrice"]      /* Price display */
[data-pp-embed] [class*="unitTileAttrs"]      /* Attributes container */
[data-pp-embed] [class*="badge"]              /* Status badges */
[data-pp-embed] [class*="dropdownToggle"]     /* Filter dropdowns */
[data-pp-embed] [class*="dropdownMenu"]       /* Dropdown menus */
[data-pp-embed] [class*="unitCardAction"]     /* Action buttons */
[data-pp-embed] [class*="shortlistAction"]    /* Favorite button */

/* Scope-specific selectors */
[data-pp-scope="project"] [data-pp-layout]    /* Project view layout */
[data-pp-scope="floor"] [data-pp-layout]      /* Floor view layout */
[data-pp-scope="unit"] [class*="unitCard"]    /* Unit detail card */
```

**❌ Incorrect selectors that won't work:**

```css theme={null}
/* These data attribute selectors are NOT implemented */
[data-pp-button]         /* Use [class*="button"] or [class*="unitCardAction"] */
[data-pp-unit-tile]      /* Use [class*="unitTile"] instead */
[data-pp-badge]          /* Use [class*="badge"] instead */
[data-pp-dropdown]       /* Use [class*="dropdown"] instead */
[data-pp-list]           /* Use [data-pp-unit-list] or [data-pp-unit-grid] */
[data-pp-floor]          /* Use [data-pp-scope="floor"] instead */

/* Plain class names won't work due to CSS Modules */
.header
.unitTile
.badge

/* This attribute doesn't exist */
[data-theme="showcase"]
```

### Common Elements You Can Style

Here are some frequently customized elements:

| Element              | Selector                     | What it controls                      |
| -------------------- | ---------------------------- | ------------------------------------- |
| Main container       | `[data-pp-embed]`            | Overall viewer wrapper, CSS variables |
| Inner container      | `[data-pp-container]`        | Inner container element               |
| Layout               | `[data-pp-layout]`           | Grid layout container                 |
| Portal header        | `[data-pp-header]`           | Header bar with logo and CTAs         |
| Header CTA (desktop) | `[data-pp-cta-desktop]`      | Desktop call-to-action button         |
| Header CTA (mobile)  | `[data-pp-cta-mobile]`       | Mobile call-to-action button          |
| Filters wrapper      | `[data-pp-filters-wrapper]`  | Filter bar background/styling         |
| Filters              | `[data-pp-filters]`          | Filter controls section               |
| Glass filters        | `[data-pp-glass-filters]`    | Glass-style filter variant            |
| Unit grid            | `[data-pp-unit-grid]`        | Grid of unit cards                    |
| Unit list            | `[data-pp-unit-list]`        | Table view of units                   |
| Unit cards           | `[class*="unitTile"]`        | Individual unit listings              |
| Card body            | `[class*="unitTileBody"]`    | Card content area                     |
| Card price           | `[class*="unitTilePrice"]`   | Price display                         |
| Status badges        | `[class*="badge"]`           | Available/Sold/Reserved labels        |
| Dropdowns            | `[class*="dropdownToggle"]`  | Filter dropdown buttons               |
| Dropdown menus       | `[class*="dropdownMenu"]`    | Filter dropdown options               |
| Action buttons       | `[class*="unitCardAction"]`  | CTA buttons                           |
| Modals               | `[data-pp-modal]`            | Popup windows                         |
| Canvas area          | `[data-pp-canvas]`           | Floor plan display area               |
| Unit view            | `[data-pp-unit-view]`        | Unit view container                   |
| Amenity view         | `[data-pp-amenity-view]`     | Amenity view container                |
| Commerce view        | `[data-pp-commerce-view]`    | Commerce view container               |
| Gallery              | `[class*="embla"]`           | Image carousel                        |
| Shortlist button     | `[class*="shortlistAction"]` | Favorite/save button                  |

***

## CSS Custom Properties (Variables)

The template uses CSS custom properties for easy theme-wide changes. Modify these at the top of your CSS file for consistent styling:

```css theme={null}
[data-pp-embed] {
  /* Brand Colors */
  --pp-brand-primary: #5b4cdb;
  --pp-brand-secondary: #7c3aed;
  --pp-brand-accent: #8b5cf6;
  --pp-brand-light: #ede9fe;

  /* Status Colors */
  --pp-success: #059669;
  --pp-success-bg: #d1fae5;
  --pp-danger: #dc2626;
  --pp-danger-bg: #fee2e2;
  --pp-warning: #d97706;
  --pp-warning-bg: #fef3c7;

  /* Neutral Palette */
  --pp-white: #ffffff;
  --pp-gray-50: #f9fafb;
  --pp-gray-100: #f3f4f6;
  --pp-gray-200: #e5e7eb;
  --pp-gray-500: #6b7280;
  --pp-gray-700: #374151;
  --pp-gray-900: #111827;

  /* Shadows */
  --pp-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
  --pp-shadow-md: 0 4px 8px -2px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.04);
  --pp-shadow-lg: 0 12px 24px -4px rgba(0, 0, 0, 0.1), 0 4px 8px -2px rgba(0, 0, 0, 0.05);

  /* Border Radius */
  --pp-radius-sm: 8px;
  --pp-radius-md: 12px;
  --pp-radius-lg: 16px;
  --pp-radius-xl: 20px;
  --pp-radius-full: 9999px;
}
```

Changing these values will update styling throughout your viewer automatically.

***

## Example: Styling Status Badges

Here's an example of how to style the availability badges:

```css theme={null}
/* Available badge - green gradient */
[data-pp-embed] [class*="badge"][data-style="available"] {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  padding: 6px 14px !important;
  border-radius: 9999px !important;
}

/* Sold badge - red gradient */
[data-pp-embed] [class*="badge"][data-style="sold"] {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%) !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  padding: 6px 14px !important;
  border-radius: 9999px !important;
}

/* Reserved/On Hold badge - gray gradient */
[data-pp-embed] [class*="badge"][data-style="reserved"],
[data-pp-embed] [class*="badge"][data-style="onhold"] {
  background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%) !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  padding: 6px 14px !important;
  border-radius: 9999px !important;
}
```

***

## Troubleshooting

### My custom CSS isn't showing up

**Check these common issues:**

1. **Missing URL parameter:** Ensure `?customCss=true` is in your embed URL
2. **Custom CSS not enabled:** Verify it's toggled on in Project Settings → Style
3. **Wrong selectors:** Make sure you're using `[class*="className"]` pattern for nested elements, not plain class names or non-existent data attributes
4. **Missing `!important`:** Many styles require `!important` to override defaults
5. **Cache issues:** Try clearing your browser cache or testing in an incognito window
6. **File upload failed:** Re-upload your CSS file and confirm the save was successful

### Some elements aren't styling correctly

This usually means you're using selectors that don't match our system:

* ❌ Don't use: `[data-pp-button]`, `[data-pp-unit-tile]`, `.unitTile`
* ✅ Do use: `[class*="button"]`, `[class*="unitTile"]`

Download a fresh copy of the default template and compare your selectors to the working examples included.

### Styles work in dev tools but not in my CSS file

Make sure you're adding `!important` to your declarations. CSS Modules generate high-specificity selectors, so you need `!important` to override them.

### How do I reset to the default theme?

In **Style & Embed** → **Style** → **Custom CSS**, click **Remove Custom CSS** or simply remove the `?customCss=true` parameter from your embed URL.
