---
title: Apply a Theme to a PDF Form
product: PDF Generator
description: Learn how to apply predefined SurveyJS themes to both a web form and its generated PDF version. Switch themes at runtime and see the selected theme applied immediately to the web form and automatically reused in the generated PDF.
framework: Vue 3
source: https://surveyjs.io/pdf-generator/examples/apply-surveyjs-theme-to-pdf-form/vue3js
index: https://surveyjs.io/pdf-generator/examples/overview.md
---

# Apply a Theme to a PDF Form (Vue 3)

This demo shows how predefined SurveyJS themes can be applied to both a web form and its PDF version to maintain a consistent appearance. SurveyJS themes are based on CSS variables and can be shared across all SurveyJS components. By default, the demo uses the Monochrome Light theme, which is optimized for printing. To try other themes or color palettes, open the **Settings** panel using the button in the bottom-right corner.

## Predefined Themes

SurveyJS includes the following [predefined themes](/documentation/themes-and-custom-styles):

- Default
- Contrast
- Borderless
- Flat
- Plain
- 3D
- Soft
- Monochrome

Each theme is available in Light and Dark variations, providing a total of 16 predefined theme options that can be applied to PDF forms.

> SurveyJS themes also include "panelless" variations that remove question containers. These variations are not supported by PDF Generator.

In this and other PDF Generator demos, you can switch themes at runtime using the **Themes** panel. Theme changes are applied to the current web form immediately and used for the generated PDF when you click **Download PDF** or **Preview PDF**. If the **Themes** panel is not visible, open it using the button in the bottom-right corner of the Demo tab.

> In PDF Generator, themes control colors and shadows only. Other visual properties, such as spacing, sizing, typography, and border radius, are defined by [layouts](/pdf-generator/examples/compact-vs-spacious-pdf-layout/).

## Apply a Theme

A SurveyJS theme is a JSON object that defines a form's visual appearance. To apply a theme to a PDF form, import the theme object and pass it to the [`applyTheme`](/pdf-generator/documentation/api-reference/surveypdf#applyTheme) method. The following code applies the Monochrome Light theme:

```js
// Modular applications
import { MonochromeLight } from "survey-core/themes";
import { SurveyPDF } from "survey-pdf";

const surveyJson = { /* Survey JSON schema */ };
const surveyPDF = new SurveyPDF(surveyJson);

surveyPDF.applyTheme(MonochromeLight);

surveyPDF.save("my-pdf-form.pdf");
```

```html
<!-- Classic script applications -->
<head>
  <!-- ... -->
  <script src="https://unpkg.com/survey-core/themes/monochrome-light.min.js"></script>
  <!-- ... -->
</head>
<body>
  <script>
    const surveyPdf = new SurveyPDF.SurveyPDF({ /* ... */});

    surveyPdf.applyLayout(SurveyTheme.MonochromeLight);

    surveyPdf.save("my-monochrome-form.pdf");
  </script>
</body>
```

## Synchronize Themes Between Web and PDF Forms

If users can change themes at runtime, apply the survey's current theme to the PDF form before generating it:

```js
function createSurveyPdfModel(surveyModel) {
  const surveyPDF = new SurveyPDF(surveyJson, pdfOptions);

  if (surveyModel) {
    surveyPDF.data = surveyModel.data;
    surveyPDF.locale = surveyModel.locale;
    
    if (surveyModel.theme) {
      surveyPDF.applyTheme(surveyModel.theme);
    }
  }

  return surveyPDF;
}
```

For more information about themes and other appearance customization options, refer to the following help topic:

[PDF Appearance Customization](/pdf-generator/documentation/pdf-appearance-customization (linkStyle))

## Files

### `public/index.html`

```html
<div style="display: flex;">
    <div id="app" style="flex: 1 1 0%; height: 100%; min-width: 0;"></div>
    <div id="pdf-preview" style="flex: 0.7 0.7 0%; display: none">
        <embed id="pdf-preview-frame" type="application/pdf" style="width:100%; height:100%;" />
    </div>
</div>
```

### `src/App.vue`

```html
<template>
    <SurveyComponent :model="survey" />
</template>
<script setup lang="ts">
    import { Model } from "survey-core";
    import { SurveyComponent } from "survey-vue3-ui";
    import "survey-core/survey-core.min.css";
    import { SurveyPDF } from "survey-pdf";
    import SurveyTheme from "survey-core/themes";
    import "./index.css";
    import { json } from "./json";

    function createSurveyPdfModel (surveyModel) {
        const surveyPDF = new SurveyPDF(json);
        if (surveyModel) {
            surveyPDF.data = surveyModel.data;
            surveyPDF.locale = surveyModel.locale;
            surveyPDF.applyTheme(SurveyTheme.MonochromeLight);
            
        }
        surveyPDF.onGetQuestionStyle.add((_, options) => {  
            if (options.question.getType() === "matrix") {
                options.style.columnMinWidth = 20;
            }
        });
        return surveyPDF;
    }
    function saveSurveyToPdf (filename, surveyModel) {
        const pdfDoc = createSurveyPdfModel(surveyModel);
        if (!pdfDoc) return;
    
        pdfDoc.save(filename);
    }
    
    const previewDiv = document.getElementById("pdf-preview");
    const previewEmbed = document.getElementById("pdf-preview-frame");
    let pdfBlobUrl;
    
    function showPdfPreview(surveyModel) {
        if (!previewDiv || !previewEmbed) return;
    
        const pdfDoc = createSurveyPdfModel(surveyModel);
        if (!pdfDoc) return;
    
        pdfDoc.raw("blob").then((blob) => {
            if (pdfBlobUrl) {
                URL.revokeObjectURL(pdfBlobUrl);
            }
            pdfBlobUrl = URL.createObjectURL(blob);
            previewEmbed.setAttribute("src", pdfBlobUrl);
            previewDiv.style.display = "block";
        });
    }
    
    function previewPdf(surveyModel) {
        if (!previewDiv) return;
    
        if (previewDiv.style.display !== "none") {
            previewDiv.style.display = "none";
            return;
        }
    
        showPdfPreview(surveyModel);
    }
    
    const survey = new Model(json);
    survey.showCompleteButton = false;
    survey.navigationButtonsLocation = "topBottom";
    survey.addNavigationItem({
        id: "survey_save_as_file",
        title: "Download PDF",
        action: () => {
            saveSurveyToPdf("surveyResult.pdf", survey);
        }
    });
    survey.addNavigationItem({
        id: "survey_pdf_preview",
        title: "Preview PDF",
        visible: window.navigator.pdfViewerEnabled,
        action: () => {
            previewPdf(survey);
        }
    });
    survey.applyTheme(SurveyTheme.MonochromeLight);
</script>
```

### `src/index.css`

```css
/* You can add your custom CSS here. */
```

### `src/json.ts`

```ts
export const json = {
  "title": "Product Feedback",
  "description": "Share your experience with our platform. Required fields are marked with *.",
  "pages": [
    {
      "name": "feedback",
      "elements": [
        {
          "type": "panel",
          "name": "profile",
          "title": "Your profile",
          "elements": [
            {
              "type": "text",
              "name": "full-name",
              "title": "Full name",
              "isRequired": true
            },
            {
              "type": "text",
              "name": "email",
              "startWithNewLine": false,
              "title": "Work email",
              "isRequired": true,
              "inputType": "email",
              "validators": [{ "type": "email" }]
            },
            {
              "type": "dropdown",
              "name": "role",
              "title": "Your role",
              "choices": [
                "Developer",
                "Product manager",
                "Designer",
                "QA engineer",
                "Other"
              ]
            }
          ]
        },
        {
          "type": "matrix",
          "name": "feature-ratings",
          "title": "How would you rate the following?",
          "description": "Rate each area from 1 (poor) to 5 (excellent).",
          "rowTitleWidth": "140px",
          "columns": [1, 2, 3, 4, 5],
          "rows": [
            { "value": "ui", "text": "User interface" },
            { "value": "performance", "text": "Performance" },
            { "value": "docs", "text": "Documentation" },
            { "value": "api", "text": "API & integrations" },
            { "value": "support", "text": "Support quality" }
          ],
          "eachRowRequired": true
        },
        {
          "type": "rating",
          "name": "overall",
          "title": "Overall satisfaction",
          "rateCount": 5,
          "rateMin": 1,
          "rateMax": 5,
          "minRateDescription": "Very dissatisfied",
          "maxRateDescription": "Very satisfied"
        },
        {
          "type": "checkbox",
          "name": "used-features",
          "title": "Which features do you use regularly?",
          "choices": [
            "Form builder",
            "PDF export",
            "Analytics dashboard",
            "Custom themes",
            "Team collaboration"
          ],
          "colCount": 2,
          "showOtherItem": true,
          "otherText": "Other"
        },
        {
          "type": "comment",
          "name": "improvements",
          "title": "What should we improve next?",
          "maxLength": 500
        },
        {
          "type": "boolean",
          "name": "recommend",
          "title": "Would you recommend us to a colleague?",
          "valueTrue": "yes",
          "valueFalse": "no"
        }
      ]
    }
  ],
  "showQuestionNumbers": false,
  "headerView": "advanced"
}
;
```

### `src/main.ts`

```ts
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.mount("#app");
```

### `src/shims-vue.d.ts`

```ts
/* eslint-disable */
declare module "*.vue" {
    import type { DefineComponent } from "vue"
    const component: DefineComponent<{}, {}, any>
    export default component
}
```

### `src/theme.ts`

```ts
export const themeJson = {};
```

### `.eslintrc.js`

```js
module.exports = {
    root: true,
    env: {
        node: true
    },
    extends: [
        "plugin:vue/vue3-essential",
        "eslint:recommended",
        "@vue/typescript/recommended",
        "@vue/prettier",
        "@vue/prettier/@typescript-eslint"
    ],
    parserOptions: {
        ecmaVersion: 2020
    },
    rules: {
        "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
        "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
    },
    overrides: [
        {
            files: [
                "**/__tests__/*.{j,t}s?(x)",
                "**/tests/unit/**/*.spec.{j,t}s?(x)"
            ],
            env: {
                jest: true
            }
        }
    ]
};
```

### `babel.config.js`

```js
module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"]
};
```

### `package.json`

```json
{
  "name": "surveyjs-library-vue3",
  "version": "0.1.0",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "tslib": "2.6.1",
    "vue": "^3.4.1",
    "survey-core": "latest",
    "survey-pdf": "latest",
    "survey-vue3-ui": "latest",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-pwa": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "@vue/test-utils": "^2.0.0-0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-0",
    "node-sass": "^4.12.0",
    "prettier": "^1.19.1",
    "sass-loader": "^8.0.2",
    "typescript": "~3.9.3"
  }
}
```

### `tsconfig.json`

```json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env",
      "jest"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/pdf-generator/examples/apply-surveyjs-theme-to-pdf-form/angular.md)
- [React](https://surveyjs.io/pdf-generator/examples/apply-surveyjs-theme-to-pdf-form/reactjs.md)
- [jQuery](https://surveyjs.io/pdf-generator/examples/apply-surveyjs-theme-to-pdf-form/jquery.md)
- [Vanilla JS](https://surveyjs.io/pdf-generator/examples/apply-surveyjs-theme-to-pdf-form/vanillajs.md)
