Skip to content

Adding a Page Watermark



If you are looking to add watermark to your PDF pages, Vue PDF Viewer provides the pageOverlay slot to achieve this objective. This tutorial will guide you on how to add custom watermarks that scale properly with the PDF zoom level.

INFO

The pageOverlay slot is only available for Organization license users.

Here is a technical summary of what the example will consist of:

  1. VPdfViewer: Display the PDF document
  2. pageOverlay Slot: Render custom watermark overlay on each page
  3. Scale-Responsive Styling: Ensure watermarks scale proportionally with PDF zoom

Breakdown step by step

1. Setting Up the PDF Viewer

The VPdfViewer component is responsible for rendering the PDF file inside your Vue application. To initialize and load the viewer, you need to provide a valid PDF file source through the src prop.

Here is how to create a VPdfViewer component with the pageOverlay slot:

vue
<VPdfViewer :src="pdfFileSource">
  <template #pageOverlay="{ pageIndex, scale }">
    <!-- Watermark content will go here -->
  </template>
</VPdfViewer>

2. Creating the Watermark Component

The watermark can be a simple text overlay or a more complex design. The key is to position it absolutely within the page overlay and make it responsive to the scale.

Here is how to create a basic text watermark:

vue
<script setup>
const getWatermarkStyle = (scale) => {
  return {}
} 
</script>
<template #pageOverlay="{ scale }">
  <div class="watermark" :style="getWatermarkStyle(scale)">
    CONFIDENTIAL
  </div>
</template>
<style scoped>
.watermark{
  position: absolute;
  color: red;
  opacity: 0.25;
}
</style>

Adding page watermark - Basic text watermark

3. Implementing Scale-Responsive Styling

To ensure the watermark scales properly when users zoom in or out, we need to multiply our base style values by the scale prop. This ensures the watermark maintains its relative size and position.

Here is how to create a helper function for scale-responsive styling:

vue
<script setup>
const getWatermarkStyle = (scale: number) => {
  return {
    fontSize: `${48 * scale}px`,
  };
};
</script>
css
<style scoped>
.watermark {
  position: absolute;
  color: red;
  opacity: 0.25;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-45deg);
}
</style>

This approach ensures the watermark maintains consistent size relative to the PDF page regardless of zoom level.

4. Adding Conditional Watermarks

You can also add watermarks to specific pages only by using the pageIndex prop:

vue
<template #pageOverlay="{ pageIndex, scale }">
  <!-- Only show watermark on first page (index 0) -->
  <div
    v-if="pageIndex === 0"
    class="watermark"
    :style="getWatermarkStyle(scale)"
  >
    DRAFT - Page {{ pageIndex + 1 }}
  </div>
</template>

Adding page watermark - Conditional watermark

Complete Example

How Each Part Works Together

  1. VPdfViewer Component: This component displays the PDF file in the application.
  2. pageOverlay Slot: Provides access to pageIndex and scale props for each page.
  3. Watermark Style Function: Calculates responsive styles based on the current scale to ensure proper sizing.
  4. CSS Styling: Positions the watermark and applies visual effects like rotation and opacity.

Here is a complete example of how you can add a watermark to PDF pages:

vue
<script setup lang="ts">
import { VPdfViewer } from "@vue-pdf-viewer/viewer";

const pdfFileSource =
  "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf";

// Helper function to calculate responsive watermark styles
const getWatermarkStyle = (scale: number) => {
  return {
    fontSize: `${48 * scale}px`
  };
};
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer :src="pdfFileSource">
      <template #pageOverlay="{ scale }">
        <div class="watermark" :style="getWatermarkStyle(scale)">
          CONFIDENTIAL
        </div>
      </template>
    </VPdfViewer>
  </div>
</template>

<style scoped>
.watermark {
  position: absolute;
  color: red;
  top: 50%;
	left: 50%;
  transform: translate(-50%, -50%) rotate(-45deg);
  opacity: 0.25;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}
</style>
vue
<script setup>
import { VPdfViewer } from "@vue-pdf-viewer/viewer";

const pdfFileSource =
  "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf";

// Helper function to calculate responsive watermark styles
const getWatermarkStyle = (scale) => {
  return {
    fontSize: `${48 * scale}px`
  };
};
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer :src="pdfFileSource">
      <template #pageOverlay="{ scale }">
        <div class="watermark" :style="getWatermarkStyle(scale)">
          CONFIDENTIAL
        </div>
      </template>
    </VPdfViewer>
  </div>
</template>

<style scoped>
.watermark {
  position: absolute;
  color: red;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-45deg);
  opacity: 0.25;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}
</style>
vue
<script lang="ts">
import { defineComponent } from "vue";
import { VPdfViewer } from "@vue-pdf-viewer/viewer";

export default defineComponent({
  components: { VPdfViewer },
  data() {
    return {
      pdfFileSource:
        "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf",
    };
  },
  methods: {
    // Helper method to calculate responsive watermark styles
    getWatermarkStyle(scale: number) {
      return {
        fontSize: `${48 * scale}px`,
        top: "50%",
        left: "50%",
      };
    },
  },
});
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer :src="pdfFileSource">
      <template #pageOverlay="{ scale }">
        <div class="watermark" :style="getWatermarkStyle(scale)">
          CONFIDENTIAL
        </div>
      </template>
    </VPdfViewer>
  </div>
</template>

<style scoped>
.watermark {
  position: absolute;
  color: red;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-45deg);
  opacity: 0.25;
  pointer-events: none;
  user-select: none;
}
</style>
vue
<script>
import { VPdfViewer } from "@vue-pdf-viewer/viewer";

export default {
  components: { VPdfViewer },
  data() {
    return {
      pdfFileSource:
        "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf",
    };
  },
  methods: {
    // Helper method to calculate responsive watermark styles
    getWatermarkStyle(scale) {
      return {
        fontSize: `${48 * scale}px`
      };
    },
  },
};
</script>

<template>
  <div :style="{ width: '1028px', height: '700px' }">
    <VPdfViewer :src="pdfFileSource">
      <template #pageOverlay="{ scale }">
        <div class="watermark" :style="getWatermarkStyle(scale)">
          CONFIDENTIAL
        </div>
      </template>
    </VPdfViewer>
  </div>
</template>

<style scoped>
.watermark {
  position: absolute;
  color: red;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-45deg);
  opacity: 0.25;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}
</style>

Advanced: Image-Based Watermarks

You can also use images as watermarks instead of text. Here's how to add a logo watermark:

vue
<template #pageOverlay="{ scale }">
  <img
    src="/your-logo.png"
    class="watermark-image"
    :style="getImageWatermarkStyle(scale)"
    alt="Watermark"
  />
</template>
js
const getImageWatermarkStyle = (scale: number) => {
  return {
    width: `${300 * scale}px`,
    height: `${300 * scale}px`,
  };
};
css
.watermark-image {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.1;
  pointer-events: none;
  user-select: none;
}

Tips and Best Practices

Watermark Visibility

  • Use low opacity (0.1 - 0.2) to ensure the watermark doesn't interfere with document readability
  • Choose contrasting colors that work well on both light and dark content
  • Consider using mix-blend-mode CSS property for better integration

Performance Considerations

  • Keep watermark DOM structure simple to avoid performance issues with large documents
  • Use CSS transforms instead of absolute positioning when possible
  • Avoid complex animations or transitions in the watermark

Accessibility

  • Add pointer-events: none to prevent watermarks from blocking user interaction
  • Include user-select: none to prevent accidental text selection
  • Ensure watermarks don't obscure critical information in the PDF