Theming
The calendar reads its colors, sizes and fonts from --vfc-* custom properties. Set one on the calendar, on any ancestor, or on :root. Pick a theme below and watch the tokens change.
<div class="my-calendar">
<FunctionalCalendar v-model="value" is-date-range can-clear-range />
</div>
<style>
.my-calendar {
--vfc-primary: #e11d48;
--vfc-on-primary: #ffffff;
}
</style>
Where to set tokens
:root {
--vfc-radius: 4px;
}
.booking-form {
--vfc-primary: #0d9488;
--vfc-on-primary: #ffffff;
}
You can also set them on one calendar with a style or class attribute. Both land on the root element of the component.
<FunctionalCalendar style="--vfc-primary: #0d9488; --vfc-on-primary: #fff" is-date-picker />
A token on :root applies in light and dark. To change a value in dark mode only, scope it to .vfc-dark:
.vfc-dark {
--vfc-primary: #2dd4bf;
--vfc-on-primary: #042f2e;
}
Dark mode
isDark adds the vfc-dark class to the calendar and its input. The dark block changes colors and shadows only. Radius, spacing, fonts, --vfc-day-size, --vfc-header-height and --vfc-transition keep their values. --vfc-today and --vfc-focus default to --vfc-primary, so they follow the dark primary.
To follow your site theme, bind isDark:
<FunctionalCalendar :is-dark="colorMode.value === 'dark'" is-date-picker />
isDark is watched, so the calendar follows the theme without a re-key.
Color tokens
| Token | Light | Dark | Used for |
|---|---|---|---|
--vfc-primary | hsl(228 70% 50%) | hsl(228 88% 68%) | Selected days, active controls |
--vfc-on-primary | hsl(0 0% 100%) | hsl(228 40% 8%) | Text on the primary color |
--vfc-bg | hsl(0 0% 100%) | hsl(228 24% 9%) | Calendar background |
--vfc-bg-raised | --vfc-bg | #1c1f27 | Pickers and presets |
--vfc-text | hsl(228 32% 12%) | hsl(228 20% 96%) | Main text |
--vfc-text-muted | #60636d | #abacb1 | Day names, neighbor month days |
--vfc-text-disabled | #b4b5ba | #595c62 | Disabled days |
--vfc-border | #e3e3e5 | #2c2f36 | Dividers and outlines |
--vfc-border-strong | #7e8189 | #82848a | Input and button borders |
--vfc-hover | #f1f1f2 | #23262e | Hover background |
--vfc-primary-hover | #2443c0 | #7a92f5 | Hover on primary parts |
--vfc-range-mix | 12% | 26% | Share of primary in the range colors |
--vfc-range | #e5e9fa | #273154 | Range fill |
--vfc-range-strong | #dbe1f9 | #303c6b | Range ends and hover |
--vfc-today | --vfc-primary | --vfc-primary | Today marker |
--vfc-focus | --vfc-primary | --vfc-primary | Focus ring |
--vfc-danger | hsl(0 70% 42%) | hsl(0 84% 68%) | Remove badge on a range |
--vfc-on-danger | hsl(0 0% 100%) | hsl(228 40% 8%) | Text on the danger color |
Shadow tokens
| Token | Light | Dark |
|---|---|---|
--vfc-shadow-sm | 0 1px 2px hsl(228 40% 10% / 0.08) | 0 1px 2px hsl(228 50% 2% / 0.4) |
--vfc-shadow-md | 0 4px 12px hsl(228 40% 10% / 0.1), 0 1px 3px hsl(228 40% 10% / 0.08) | 0 4px 12px hsl(228 50% 2% / 0.5), 0 1px 3px hsl(228 50% 2% / 0.4) |
--vfc-shadow-lg | 0 16px 32px hsl(228 40% 10% / 0.12), 0 4px 8px hsl(228 40% 10% / 0.08) | 0 16px 32px hsl(228 50% 2% / 0.6), 0 4px 8px hsl(228 50% 2% / 0.5) |
Shape, spacing and type tokens
These are the same in light and dark.
| Token | Default |
|---|---|
--vfc-radius-sm, --vfc-radius, --vfc-radius-lg | 6px, 8px, 12px |
--vfc-space-1 to --vfc-space-5 | 4px, 8px, 12px, 16px, 24px |
--vfc-font | ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif |
--vfc-font-size-xs, -sm, -md | 12px, 14px, 16px |
--vfc-font-weight, -medium, -strong | 400, 500, 600 |
--vfc-day-size | 36px |
--vfc-header-height | 40px |
--vfc-transition | 150ms ease |
Derived colors
Where the browser supports color-mix(), eight tokens derive from three base colors, so changing --vfc-primary, --vfc-bg or --vfc-text recolors the whole calendar.
| Token | Derived as |
|---|---|
--vfc-text-muted | --vfc-text 68% over --vfc-bg |
--vfc-text-disabled | --vfc-text 32% over --vfc-bg |
--vfc-border | --vfc-text 12% over --vfc-bg |
--vfc-border-strong | --vfc-text 55% over --vfc-bg |
--vfc-hover | --vfc-text 7% over --vfc-bg |
--vfc-primary-hover | --vfc-primary 86% over --vfc-text |
--vfc-range | --vfc-primary at --vfc-range-mix over --vfc-bg |
--vfc-range-strong | --vfc-primary at 1.4 times --vfc-range-mix over --vfc-bg |
In dark mode, --vfc-bg-raised also derives, as --vfc-text 5% over --vfc-bg.
Browsers without color-mix
Safari below 16.2 and other browsers without color-mix() use the fixed values from the tables above. They match the default colors only. If you change --vfc-primary, --vfc-bg or --vfc-text, override the derived tokens together:
.my-calendar {
--vfc-primary: #0d9488;
--vfc-primary-hover: #0f766e;
--vfc-range: #ccfbf1;
--vfc-range-strong: #99f6e4;
--vfc-text-muted: #5b6770;
--vfc-text-disabled: #b3bcc2;
--vfc-border: #e2e8ec;
--vfc-border-strong: #7b8a94;
--vfc-hover: #f0f4f6;
}
Add --vfc-bg-raised under .vfc-dark as well. --vfc-range-mix has no effect in these browsers.
Class overrides
The vfc-* class names are the same as in 2.x, so CSS overrides written for 2.x keep working. Tokens and class rules mix freely.