Electronic Signature on Website: Drawing, Text, Image Upload

Electronic Signature Implementation (Drawing/Input) on a Website

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • B2B ADVANCE company website development
    B2B ADVANCE company website development
    1467
  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1320
  • Website development for BELFINGROUP
    Website development for BELFINGROUP
    1015
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1276
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1019
  • Website development for FIXPER company
    Website development for FIXPER company
    1019

Electronic Signature Implementation (Drawing/Input) on a Website

Developers face a typical problem: a user on a mobile device tries to draw a signature with a finger, but the canvas does not handle touches correctly. Or on Retina displays the signature comes out blurry, and on old Android tablets—with a delay of up to 300 ms. We solved this problem in several projects—from data processing consents to acceptance certificates for 5+ clients. We'll tell you how to implement three signature input methods: drawing, printed text, and image upload.

Do not confuse with a qualified electronic signature (QES): here we are talking about a visual signature without cryptography, used in contracts, consents, acts. For legal force, additional infrastructure is required—we also implement that turnkey. Get a consultation to evaluate your project.

Why canvas is the best choice for drawing signatures?

Canvas provides low latency (up to 16 ms at 60 FPS), Retina adaptation, and correct stylus handling. Unlike SVG, canvas does not create DOM nodes with each stroke, which is critical for long sessions—canvas performance is 3 times higher on 1000+ strokes. The alternative—jSignature—does not support Retina and is heavier to customize.

Three signature input options

Drawing — the user draws a signature with a mouse or stylus on canvas. The most familiar format for most users. Printed text — enter a name, displayed in a chosen "handwritten" font (Caveat, Dancing Script, Pacifico). Image upload — upload a photo/scan of your own signature.

Let's compare the methods:

Method Mobile Convenience Image Quality Compatibility
Drawing (canvas) Excellent (with touch-none) High (Retina adaptation) All browsers
Printed text Excellent (keyboard) Medium (depends on font) All browsers
Image upload Good (gallery) Depends on source All browsers

Now let's compare libraries for canvas signature:

Library Size (min) Touch Support Retina Adaptation
signature_pad 8 KB Yes Yes
jSignature 12 KB Yes No
Fabric.js 300+ KB Yes Partial

Implementation via signature_pad

The signature_pad library is the standard for canvas signatures:

import SignaturePad from 'signature_pad'; import { useRef, useEffect, useState } from 'react'; function SignatureCanvas({ onSave, onClear }) { const canvasRef = useRef<HTMLCanvasElement>(null); const padRef = useRef<SignaturePad | null>(null); useEffect(() => { const canvas = canvasRef.current!; padRef.current = new SignaturePad(canvas, { backgroundColor: 'rgb(255, 255, 255)', penColor: 'rgb(0, 0, 0)', minWidth: 0.5, maxWidth: 2.5, throttle: 16, // ~60fps }); // Scale for Retina displays function resizeCanvas() { const ratio = Math.max(window.devicePixelRatio || 1, 1); canvas.width = canvas.offsetWidth * ratio; canvas.height = canvas.offsetHeight * ratio; const ctx = canvas.getContext('2d')!; ctx.scale(ratio, ratio); padRef.current!.clear(); } resizeCanvas(); window.addEventListener('resize', resizeCanvas); return () => window.removeEventListener('resize', resizeCanvas); }, []); const handleSave = () => { if (padRef.current!.isEmpty()) return; const dataUrl = padRef.current!.toDataURL('image/png'); onSave(dataUrl); }; return ( <div className="border-2 border-dashed border-gray-300 rounded-lg"> <canvas ref={canvasRef} className="w-full h-40 touch-none" // touch-none is important for mobile /> <div className="flex gap-2 p-2"> <button onClick={() => { padRef.current!.clear(); onClear(); }}>Clear</button> <button onClick={handleSave} className="btn-primary">Sign</button> </div> </div> ); } 

Text signature input

const SIGNATURE_FONTS = [ { name: 'Caveat', label: 'Handwritten 1' }, { name: 'Dancing Script', label: 'Handwritten 2' }, { name: 'Pacifico', label: 'Calligraphy' }, ]; function TextSignature({ name, onSave }) { const [selectedFont, setSelectedFont] = useState(SIGNATURE_FONTS[0]); const canvasRef = useRef<HTMLCanvasElement>(null); const renderToCanvas = (font: string, text: string) => { const canvas = canvasRef.current!; const ctx = canvas.getContext('2d')!; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.font = `48px "${font}"`; ctx.fillStyle = '#1a1a1a'; ctx.fillText(text, 20, 70); return canvas.toDataURL('image/png'); }; return ( <div> <div className="flex gap-2 mb-3"> {SIGNATURE_FONTS.map(font => ( <button key={font.name} style={{ fontFamily: font.name }} onClick={() => setSelectedFont(font)} className={selectedFont.name === font.name ? 'border-blue-500 border-2' : ''} > {name} </button> ))} </div> <canvas ref={canvasRef} width={400} height={100} className="border rounded" /> <button onClick={() => onSave(renderToCanvas(selectedFont.name, name))}> Apply signature </button> </div> ); } 

How to embed the signature into PDF and other documents?

After receiving the signature as a base64 PNG, we embed it into the document. For PDF—via PDF-lib:

import { PDFDocument } from 'pdf-lib'; async function embedSignatureInPdf(pdfBytes, signatureDataUrl, position) { const pdfDoc = await PDFDocument.load(pdfBytes); const pages = pdfDoc.getPages(); const targetPage = pages[position.page]; const signatureBytes = Buffer.from(signatureDataUrl.split(',')[1], 'base64'); const signatureImage = await pdfDoc.embedPng(signatureBytes); targetPage.drawImage(signatureImage, { x: position.x, y: position.y, width: position.width, height: position.height, }); return await pdfDoc.save(); } 

Storage and audit

The signature as an image is stored in S3. The database records: user_id, timestamp, IP address, user-agent, document_id, document hash. This provides a basic audit trail. Additionally, you can add an invisible watermark with metadata—it does not degrade readability but allows restoring the owner when editing the file.

Why touch-none is critical for mobile devices?

Without touch-none, the browser interprets the touch as a page scroll, not drawing on the canvas. This leads to delays and false triggers. We set the CSS property touch-action: none on the canvas, giving priority to drawing. On mobile devices, the latency drops from 300 ms to 16 ms—a noticeable difference for the user.

How to ensure legal significance of the signature?

A visual signature has no legal force without additional measures. We record the time, IP, user-agent, and document hash at the moment of signing. If full legal validity is required, we add integration with QES (qualified electronic signature)—this increases the timeline to 5 days but ensures compliance with 63-FZ (Russian Federal Law).

Work process

  1. Analytics—determine signature requirements (legal force, number of signatories).
  2. Design—select input methods, widget design.
  3. Implementation—write components in React/TypeScript using signature_pad and pdf-lib.
  4. Testing—verify on iOS, Android, desktop, with various resolutions.
  5. Deploy—configure S3 storage, add audit logs.

Indicative timeline

A component with three signature methods (drawing, text, upload) and PDF embedding—from 2 to 5 days depending on integration complexity. Cost is calculated individually.

What is included in the work

  • Ready React signature component with three input methods.
  • Integration with PDF-lib for embedding signatures into documents.
  • Signature storage in S3 with audit log.
  • API and setup documentation.
  • Team training (1 hour online).

Typical implementation mistakes

  • Forgetting touch-none on canvas—signature won't work on mobile.
  • Not scaling for Retina—blurry signature.
  • Using SVG instead of canvas—performance drop on long sessions.

We have implemented electronic signatures for 5+ projects, including an online housing rental service and a contract platform. We guarantee post-implementation support. Order electronic signature implementation on your website—from simple consent to full document workflow. Get a consultation, and we will prepare a commercial offer within 24 hours.