Here's a complete HTML + CSS + JAVASCRIPT Convert JPG to PDF.

Convert Multiple JPG to A4 PDF

Preview File Name Size (KB)

HTML Sample Code


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="JPGtoPDF-Style.css">
<title>Multiple JPG To PDF</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
</head>
<div class="container">
       <h2>Convert Multiple JPG to A4 PDF</h2>
       <input
        type="file"
        id="files"
        multiple
        accept=".jpg,.jpeg,image/jpeg">

    <button id="btnGenerate">
        Generate PDF
    </button>

    <div id="summary"></div>

    <table id="fileTable">
        <thead>
            <tr>
                <th>Preview</th>
                <th>File Name</th>
                <th>Size (KB)</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</div>

<script src="app.js"></script>

<!-- Copy and Paste the Script here -->

</body>
</html>

CSS (JPGtoPDF-Style.css)



/* --- Reset and base styles --- */

body{
    font-family:Arial, sans-serif;
    background:#f4f6f9;
    padding:20px;
}

.container{
    max-width:900px;
    margin:auto;
    background:white;
    padding:20px;
    border-radius:8px;
    box-shadow:0 0 10px rgba(0,0,0,.1);
}

button{
    padding:10px 20px;
    cursor:pointer;
    margin-top:10px;
}

table{
    width:100%;
    border-collapse:collapse;
    margin-top:20px;
}

th,td{
    border:1px solid #ddd;
    padding:8px;
    text-align:left;
}

th{
    background:#f0f0f0;
}

img.preview{
    width:80px;
    height:100px;
    object-fit:cover;
}

#summary{
    margin-top:15px;
    font-weight:bold;
}

Script


<!-- Script -->
<script>
const fileInput =
document.getElementById("files");

const tbody =
document.querySelector("#fileTable tbody");

fileInput.addEventListener(
    "change",
    displayFiles
);

async function displayFiles(){

    tbody.innerHTML = "";

    const files = fileInput.files;

    let totalSize = 0;

    for(const file of files){

        totalSize += file.size;

        const row =
            document.createElement("tr");

        const imgURL =
            URL.createObjectURL(file);

        row.innerHTML = `
            <td>
                <img
                    class="preview"
                    src="${imgURL}">
            </td>
            <td>${file.name}</td>
            <td>
                ${(file.size/1024)
                .toFixed(2)}
            </td>
        `;

        tbody.appendChild(row);
    }

    document.getElementById("summary")
    .innerHTML =
        `
        Selected Files :
        ${files.length}
        <br>
        Total Size :
        ${(totalSize/1024/1024)
        .toFixed(2)} MB
        `;
}

document
.getElementById("btnGenerate")
.addEventListener(
    "click",
    generatePDF
);

async function generatePDF(){

    const files = fileInput.files;

    if(files.length === 0){

        alert(
            "Select JPG files first"
        );

        return;
    }

    const { jsPDF } =
        window.jspdf;

    const pdf =
        new jsPDF({
            orientation:"portrait",
            unit:"mm",
            format:"a4",
            compress:true
        });

    let originalSize = 0;

    for(let i=0;i<files.length;i++){

        const file = files[i];

        originalSize += file.size;

        const imageData =
            await fileToBase64(file);

        const compressed =
            await compressImage(
                imageData,
                1200,
                0.60
            );

        if(i > 0){

            pdf.addPage();
        }

        addImageToA4Page(
            pdf,
            compressed
        );
    }

    const pdfBlob =
        pdf.output("blob");

    const pdfSize =
        (pdfBlob.size
        /1024/1024)
        .toFixed(2);

    document.getElementById("summary")
    .innerHTML +=
        `
        <br>
        Generated PDF :
        ${pdfSize} MB
        `;

    savePDF(pdfBlob);
}

function fileToBase64(file){

    return new Promise(resolve=>{

        const reader =
            new FileReader();

        reader.onload =
            e => resolve(
                e.target.result
            );

        reader.readAsDataURL(file);
    });
}

function compressImage(
    src,
    maxWidth,
    quality
){

    return new Promise(resolve=>{

        const img =
            new Image();

        img.onload = ()=>{

            let width =
                img.width;

            let height =
                img.height;

            if(width > maxWidth){

                height =
                    height *
                    (maxWidth/width);

                width =
                    maxWidth;
            }

            const canvas =
                document.createElement(
                    "canvas"
                );

            canvas.width =
                width;

            canvas.height =
                height;

            const ctx =
                canvas.getContext(
                    "2d"
                );

            ctx.drawImage(
                img,
                0,
                0,
                width,
                height
            );

            resolve(
                canvas.toDataURL(
                    "image/jpeg",
                    quality
                )
            );
        };

        img.src = src;
    });
}

function addImageToA4Page(
    pdf,
    imageData
){

    const pageWidth = 210;
    const pageHeight = 297;

    const props =
        pdf.getImageProperties(
            imageData
        );

    const ratio =
        Math.min(
            pageWidth /
            props.width,

            pageHeight /
            props.height
        );

    const width =
        props.width *
        ratio;

    const height =
        props.height *
        ratio;

    const x =
        (pageWidth-width)/2;

    const y =
        (pageHeight-height)/2;

    pdf.addImage(
        imageData,
        "JPEG",
        x,
        y,
        width,
        height,
        "",
        "FAST"
    );
}

async function savePDF(pdfBlob){

    try{

        if(
            "showSaveFilePicker"
            in window
        ){

            const handle =
            await showSaveFilePicker({

                suggestedName:
                "Documents.pdf",

                types:[{
                    description:
                    "PDF File",

                    accept:{
                        "application/pdf":
                        [".pdf"]
                    }
                }]
            });

            const writable =
                await handle
                .createWritable();

            await writable.write(
                pdfBlob
            );

            await writable.close();

            alert(
                "PDF saved successfully"
            );
        }
        else{

            const url =
                URL.createObjectURL(
                    pdfBlob
                );

            const a =
                document.createElement(
                    "a"
                );

            a.href = url;

            a.download =
                "Documents.pdf";

            a.click();

            URL.revokeObjectURL(url);
        }

    }catch(error){

        console.log(error);

        alert(
            "Save cancelled"
        );
    }
}
</script>

All Rights Reserved, Copyright © PT. InetUtama Systemindo 2025