---
title: Add Header and Footer to a PDF Document
product: PDF Generator
description: Boost your brand awareness with custom headers and footers in your PDF forms. This free demo for JavaScript will show you how to add your brand logo, slogan, or annotations to give your PDF forms a professional and personalized look.
framework: Vue 3
source: https://surveyjs.io/pdf-generator/examples/customize-header-and-footer-of-pdf-form/vue3js
index: https://surveyjs.io/pdf-generator/examples/overview.md
---

# Add Header and Footer to a PDF Document (Vue 3)

You can improve the appeal of your PDF forms or simply make their contents more clear to respondents by customizing their header and footer with annotations, page numbers, a brand logo, titles, and more. This example shows how you can add a brand logo or fully custom header and footer to a PDF form.

## Add a Brand Logo to Your PDF Form

SurveyJS Form Library allows you to add a logo to your survey on a web page. This logo can be exported to PDF without additional configuration.

To add a logo, assign a Base64 or URL string value to the [`logo`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#logo) property in the survey JSON schema. You can also specify other logo parameters:

- [`logoHeight`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#logoHeight) and [`logoWidth`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#logoWidth)          
Set the height and width of a logo in CSS-accepted values.

- [`logoFit`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#logoFit): `"contain"` (default) | `"cover"` | `"fill"` | `"none"`          
Specifies how a logo should be resized to fit its container.

- [`logoPosition`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#logoPosition): `"left"` (default) | `"right"` | `"none"`           
Specifies the position of a logo relative to the survey title.

This example demonstrates how to embed a Base64 logo in a survey JSON schema and display the logo in the survey header. Click "Save as PDF" to export a PDF form with the logo.

## Customize Header and Footer in a PDF Form

With SurveyJS PDF Generator, you can create a fully custom header and footer for your PDF form. To do this, implement the [`onRenderHeader`](https://surveyjs.io/pdf-generator/documentation/api-reference/surveypdf#onRenderHeader) and [`onRenderFooter`](https://surveyjs.io/pdf-generator/documentation/api-reference/surveypdf#onRenderFooter) event handlers. They accept a [`DrawCanvas`](https://surveyjs.io/pdf-generator/documentation/api-reference/drawcanvas) object as the second parameter. Use this object to draw images or text within a PDF page header or footer.

In this demo, a `DrawCanvas` method, [`drawImage`()](https://surveyjs.io/pdf-generator/documentation/api-reference/drawcanvas#drawImage), renders a SurveyJS logo in the PDF page header. Another `DrawCanvas` method, [`drawText()`](https://surveyjs.io/pdf-generator/documentation/api-reference/drawcanvas#drawText), renders page numbers and additional information in the footer.

## 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 "./index.css";
    import { json } from "./json";

    function createSurveyPdfModel (surveyModel) {
        const surveyPDF = new SurveyPDF(json);
        if (surveyModel) {
            surveyPDF.data = surveyModel.data;
            surveyPDF.locale = surveyModel.locale;
            
            
        }
        // Adds the Generated on date note aligned right
        surveyPDF.onRenderHeader.add((_, canvas) => {
            canvas.drawText({
                text: "Generated on: " + new Date().toLocaleDateString(),
                fontSize: 9,
                horizontalAlign: "right",
                verticalAlign: "top",
                margins: { top: 12, right: 12 }
            });
        });
    
        // Adds custom text and page information to the footer area
        surveyPDF.onRenderFooter.add((_, canvas) => {
            canvas.drawText({
                text: "Created by SurveyJS PDF Generator",
                fontSize: 10
            });
            canvas.drawText({
                text: "Page " + canvas.pageNumber + " of " + canvas.pageCount,
                fontSize: 10,
                horizontalAlign: "right",   
                margins: { right: 12 }      
            });
        });
        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.data = {
        "nps-score": 9
    };
</script>
```

### `src/index.css`

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

### `src/json.ts`

```ts
export const json = {
  "title": "NPS Survey Question",
  "description": "NPS (net promoter score) is a metric used to evaluate customer loyalty and business growth opportunities. To measure NPS, respondents should rate on a scale of 0 to 10 how likely they would recommend your product or service to a friend or colleague.",
  "logo": "https://api.surveyjs.io/private/Surveys/files?name=52f2ca1e-9604-4d41-a887-0ee358b37625",
  "logoHeight": "80px",
  "logoFit": "cover",
  "pages": [
    {
      "name": "page1",
      "elements": [
        {
          "type": "panel",
          "name": "panel1",
          "elements": [
            {
              "type": "rating",
              "name": "nps-score",
              "title": "On a scale from 0 to 10, how likely are you to recommend us to a friend or colleague?",
              "defaultValue": 9,
              "rateCount": 11,
              "rateMin": 0,
              "rateMax": 10
            },
            {
              "type": "comment",
              "name": "improvements-required",
              "title": "What can we do to make your experience more satisfying?",
              "maxLength": 300
            },
            {
              "type": "checkbox",
              "name": "promoter-features",
              "title": "Which of the following features do you value the most?",
              "description": "Please select no more than three features.",
              "isRequired": true,
              "choices": [
                {
                  "value": "performance",
                  "text": "Performance"
                },
                {
                  "value": "stability",
                  "text": "Stability"
                },
                {
                  "value": "ui",
                  "text": "User interface"
                },
                {
                  "value": "complete-functionality",
                  "text": "Complete functionality"
                },
                {
                  "value": "learning-materials",
                  "text": "Learning materials (documentation, demos, code examples)"
                },
                {
                  "value": "support",
                  "text": "Quality support"
                }
              ],
              "showOtherItem": true,
              "otherPlaceholder": "Please specify...",
              "otherText": "Other features",
              "colCount": 2,
              "maxSelectedChoices": 3
            }
          ]
        }
      ]
    },
    {
      "name": "page2",
      "elements": [
        {
          "type": "boolean",
          "name": "rebuy",
          "title": "Would you buy our product again?"
        }
      ]
    },
    {
      "name": "page3",
      "elements": [
        {
          "type": "radiogroup",
          "name": "testimonial",
          "title": "Would you mind providing us a brief testimonial for the website?",
          "choices": [
            {
              "value": "yes",
              "text": "Sure!"
            },
            {
              "value": "no",
              "text": "No"
            }
          ]
        },
        {
          "type": "text",
          "name": "email",
          "title": "What is your email address?",
          "validators": [
            {
              "type": "email"
            }
          ],
          "placeholder": "Enter your email here"
        }
      ]
    }
  ],
  "showPrevButton": false,
  "questionsOnPageMode": "singlePage",  
  "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/customize-header-and-footer-of-pdf-form/angular.md)
- [React](https://surveyjs.io/pdf-generator/examples/customize-header-and-footer-of-pdf-form/reactjs.md)
- [jQuery](https://surveyjs.io/pdf-generator/examples/customize-header-and-footer-of-pdf-form/jquery.md)
- [Vanilla JS](https://surveyjs.io/pdf-generator/examples/customize-header-and-footer-of-pdf-form/vanillajs.md)
