Skip to main content
Cal.com embeds are highly customizable, allowing you to match your brand’s look and feel. This guide covers all available customization options.

Theme Configuration

Basic Theme Selection

Choose between light, dark, or auto themes:
Cal("ui", {
  theme: "dark"  // "light" | "dark" | "auto"
});
The auto theme automatically adapts to the user’s system preferences.

Layout Options

Select the calendar layout that best fits your use case:
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    layout: "month_view"  // "month_view" | "week_view" | "column_view"
  }
});
  • month_view: Traditional monthly calendar view (default)
  • week_view: Week-based calendar view
  • column_view: Column-based layout

Brand Colors

Primary Brand Color

Set your brand color to customize the main accent color:
Cal("ui", {
  styles: {
    branding: {
      brandColor: "#FF6B6B"
    }
  }
});

Custom CSS Variables

Per-Theme CSS Variables

Customize specific CSS variables for light and dark themes:
Cal("ui", {
  cssVarsPerTheme: {
    light: {
      "cal-border-booker": "#e5e7eb",
      "cal-border-booker-width": "1px",
      "cal-text-emphasis": "#111827",
      "cal-bg-emphasis": "#f9fafb",
      "cal-bg": "#ffffff"
    },
    dark: {
      "cal-border-booker": "#374151",
      "cal-border-booker-width": "1px",
      "cal-text-emphasis": "#f9fafb",
      "cal-bg-emphasis": "#1f2937",
      "cal-bg": "#111827"
    }
  }
});

Available CSS Variables

Key CSS variables you can customize:
/* Colors */
--cal-text-emphasis
--cal-text-default
--cal-text-muted
--cal-bg
--cal-bg-emphasis
--cal-bg-subtle
--cal-border
--cal-border-emphasis

/* Booker-specific */
--cal-border-booker
--cal-border-booker-width
--cal-bg-booker

/* Interactive elements */
--cal-brand
--cal-brand-emphasis
--cal-brand-text

Component Styles

Custom Component Styling

Style specific components within the embed:
Cal("ui", {
  styles: {
    body: {
      background: "#f9fafb"
    },
    eventTypeListItem: {
      backgroundColor: "#ffffff",
      color: "#111827"
    },
    enabledDateButton: {
      backgroundColor: "#3b82f6",
      color: "#ffffff"
    },
    disabledDateButton: {
      backgroundColor: "#e5e7eb",
      color: "#9ca3af"
    },
    availabilityDatePicker: {
      backgroundColor: "#ffffff",
      color: "#111827"
    }
  }
});

Supported Style Properties

interface EmbedStyles {
  body?: {
    background?: string;
  };
  eventTypeListItem?: {
    background?: string;
    color?: string;
    backgroundColor?: string;
  };
  enabledDateButton?: {
    background?: string;
    color?: string;
    backgroundColor?: string;
  };
  disabledDateButton?: {
    background?: string;
    color?: string;
    backgroundColor?: string;
  };
  availabilityDatePicker?: {
    background?: string;
    color?: string;
    backgroundColor?: string;
  };
}

UI Configuration Options

Hide Event Type Details

Hide event type details in the booking interface:
Cal("ui", {
  hideEventTypeDetails: true
});

Disable Auto-Scroll

Prevent automatic scrolling when the booking form changes:
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    "ui.autoscroll": "false"
  }
});

Color Scheme

Force a specific color scheme:
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    "ui.color-scheme": "dark"
  }
});

Mobile Slot View

Enable slots view on small screens for better mobile experience:
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    useSlotsViewOnSmallScreen: "true"
  }
});

Prefilling Information

Contact Information

Prefill attendee details:
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    name: "John Doe",
    email: "[email protected]",
    notes: "Looking forward to our meeting",
    guests: ["[email protected]", "[email protected]"],
    smsReminderNumber: "+1234567890"
  }
});

Dynamic Prefilling

Prefill based on user data from your application:
const userData = getCurrentUser();

Cal("modal", {
  calLink: "organization/event-type",
  config: {
    name: userData.fullName,
    email: userData.email,
    notes: `User ID: ${userData.id}`
  }
});

Iframe Customization

Iframe Attributes

Add custom attributes to the embed iframe:
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    iframeAttrs: {
      id: "booking-iframe",
      title: "Cal.com Booking Interface",
      class: "custom-iframe-class"
    }
  }
});

Complete Customization Example

Here’s a comprehensive example combining multiple customization options:
Cal("init");

// Set up UI customization
Cal("ui", {
  theme: "dark",
  hideEventTypeDetails: false,
  styles: {
    branding: {
      brandColor: "#FF6B6B"
    },
    body: {
      background: "#1a1a1a"
    },
    eventTypeListItem: {
      backgroundColor: "#2a2a2a",
      color: "#ffffff"
    },
    enabledDateButton: {
      backgroundColor: "#FF6B6B",
      color: "#ffffff"
    }
  },
  cssVarsPerTheme: {
    dark: {
      "cal-border-booker": "#FF6B6B",
      "cal-border-booker-width": "2px",
      "cal-text-emphasis": "#ffffff",
      "cal-bg": "#1a1a1a"
    }
  }
});

// Create inline embed with configuration
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    layout: "month_view",
    name: "John Doe",
    email: "[email protected]",
    useSlotsViewOnSmallScreen: "true",
    iframeAttrs: {
      id: "booking-iframe",
      title: "Book Your Appointment"
    }
  }
});

Responsive Design

Container Styling

Ensure your embed container is responsive:
#my-cal-inline {
  width: 100%;
  height: 100vh;
  min-height: 600px;
  overflow: auto;
}

@media (max-width: 768px) {
  #my-cal-inline {
    min-height: 500px;
  }
}

Mobile Optimizations

Use slots view on small screens:
const isMobile = window.innerWidth < 768;

Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type",
  config: {
    layout: isMobile ? "column_view" : "month_view",
    useSlotsViewOnSmallScreen: "true"
  }
});

Advanced Customization

Dynamic Theme Switching

Allow users to toggle between themes:
let currentTheme = "light";

const toggleTheme = () => {
  currentTheme = currentTheme === "light" ? "dark" : "light";
  Cal("ui", {
    theme: currentTheme
  });
};

document.querySelector("#theme-toggle").addEventListener("click", toggleTheme);

Match Parent Page Theme

Automatically match your page’s theme:
const pageTheme = document.documentElement.classList.contains("dark") ? "dark" : "light";

Cal("ui", {
  theme: pageTheme
});

// Update when page theme changes
const observer = new MutationObserver(() => {
  const newTheme = document.documentElement.classList.contains("dark") ? "dark" : "light";
  Cal("ui", { theme: newTheme });
});

observer.observe(document.documentElement, {
  attributes: true,
  attributeFilter: ["class"]
});

Custom Loading State

Show a custom loader while the embed initializes:
<div id="my-cal" style="position: relative; min-height: 600px;">
  <div id="loader" style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;">
    <div class="spinner">Loading...</div>
  </div>
</div>

<script>
  Cal("init");
  
  Cal("on", {
    action: "bookerReady",
    callback: () => {
      document.querySelector("#loader").style.display = "none";
    }
  });
  
  Cal("inline", {
    elementOrSelector: "#my-cal",
    calLink: "organization/event-type"
  });
</script>

Configuration Reference

Complete Config Interface

interface PrefillAndIframeAttrsConfig {
  // Prefill fields
  name?: string;
  email?: string;
  notes?: string;
  guests?: string[];
  smsReminderNumber?: string;
  
  // UI configuration
  theme?: "light" | "dark" | "auto";
  layout?: "month_view" | "week_view" | "column_view";
  "ui.color-scheme"?: string;
  "ui.autoscroll"?: "true" | "false";
  useSlotsViewOnSmallScreen?: "true" | "false";
  
  // Feature flags
  "flag.coep"?: "true" | "false";
  
  // Iframe attributes
  iframeAttrs?: {
    id?: string;
    title?: string;
    [key: string]: string | undefined;
  };
  
  // Custom fields
  [key: string]: string | string[] | Record<string, string> | undefined;
}

interface UiConfig {
  theme?: "light" | "dark" | "auto" | null;
  hideEventTypeDetails?: boolean;
  styles?: EmbedStyles;
  cssVarsPerTheme?: {
    light?: Record<string, string>;
    dark?: Record<string, string>;
  };
  layout?: "month_view" | "week_view" | "column_view";
  colorScheme?: string | null;
  disableAutoScroll?: boolean;
  useSlotsViewOnSmallScreen?: boolean;
}

Best Practices

Define CSS variables for colors and spacing to maintain consistency across light and dark themes.
Always test your embed on mobile devices. Enable useSlotsViewOnSmallScreen for better mobile UX.
Ensure your brand color has sufficient contrast against both light and dark backgrounds for accessibility.
Only prefill data that’s already available in your application. Never expose sensitive information.

Next Steps

JavaScript Snippet

Learn about the vanilla JS implementation

React Component

Explore the React component API

Build docs developers (and LLMs) love