How to make a Image To Pdf Convertor online for free

Features Implemented:

Responsive 4-Column Layout:

  • Uses CSS Grid for desktop view (4 columns)
  • Switches to 2 columns on medium screens (tablets)
  • Stacks to 1 column on mobile devices

Profile Column:

  • Circular profile image with border
  • Centered with caption
  • Soft shadow and hover effect

Basic Details Column:

  • Student name as heading
  • Field of study as subheading
  • Short bio paragraph

Portfolio Column:

  • List of 5 projects with clickable links
  • Hover effects for better interactivity

Contact Column:

  • Contact form with name, email, and message fields
  • JavaScript alert on form submission
  • Download CV button with distinct styling

Design Elements:

  • Clean, minimal aesthetic
  • Soft shadows and rounded corners
  • Hover animations for interactivity
  • Professional color scheme
  • Legible typography

Technical Implementation:

  • Pure HTML, CSS, and JavaScript (no external libraries)
  • CSS Grid for layout
  • Media queries for responsiveness
  • Simple form validation and feedback

The placeholder image can be replaced with an actual student photo by changing the src attribute in the profile image tag. Similarly, the download CV link can be updated to point to an actual PDF file.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Image to PDF Converter</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script> </head> <body> <div class="container"> <h1>Image to PDF Converter</h1> <div class="toolbar"> <button id="uploadBtn" class="btn">Browse Images</button> <input type="file" id="fileInput" class="file-input" accept="image/*" multiple> <div class="settings"> <select id="orientation"> <option value="portrait">Portrait</option> <option value="landscape">Landscape</option> </select> <input type="text" id="filename" class="filename-input" placeholder="Filename" value="images-to-pdf"> <button id="convertBtn" class="btn" disabled>Convert to PDF</button> <button class="theme-toggle" id="themeToggle">🌓</button> </div> </div> <div id="dropArea" class="drop-area"> <p>Drag & drop images here</p> </div> <div class="preview-container" id="previewContainer" style="display: none;"> <div class="preview-title"> <h2>Selected Images</h2> <span id="imageCount">0 images</span> </div> <div id="previewGrid" class="preview-grid"></div> </div> <div id="loading" class="loading"> <div class="loading-spinner"></div> <p>Generating PDF...</p> </div> </div> </body> </html>
CSS provides style to an HTML page. To make the page attractive create a CSS file with the name style.css and remember that you have to make a file with a .css extension.


    :root {
            --primary-color: #4a6fa5;
            --secondary-color: #166088;
            --background-color: #f8f9fa;
            --text-color: #333;
            --border-color: #ddd;
            --hover-color: #e9ecef;
            --dark-bg: #2d3748;
            --dark-text: #f7fafc;
            --dark-border: #4a5568;
        }

        [data-theme="dark"] {
            --primary-color: #63b3ed;
            --secondary-color: #4299e1;
            --background-color: #2d3748;
            --text-color: #f7fafc;
            --border-color: #4a5568;
            --hover-color: #4a5568;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            background-color: var(--background-color);
            color: var(--text-color);
            padding: 20px;
            transition: background-color 0.3s, color 0.3s;
        }

        .container {
            max-width: 1000px;
            margin: 0 auto;
            padding: 20px;
        }

        h1 {
            text-align: center;
            margin-bottom: 30px;
            color: var(--primary-color);
        }

        .toolbar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            flex-wrap: wrap;
            gap: 10px;
        }

        .settings {
            display: flex;
            gap: 15px;
            align-items: center;
            flex-wrap: wrap;
        }

        .drop-area {
            border: 2px dashed var(--border-color);
            border-radius: 8px;
            padding: 40px 20px;
            text-align: center;
            cursor: pointer;
            margin-bottom: 20px;
            transition: all 0.3s;
            background-color: rgba(255, 255, 255, 0.05);
        }

        .drop-area:hover {
            border-color: var(--primary-color);
            background-color: var(--hover-color);
        }

        .drop-area.highlight {
            border-color: var(--primary-color);
            background-color: rgba(74, 111, 165, 0.1);
        }

        .drop-area p {
            margin-bottom: 15px;
            font-size: 18px;
        }

        .btn {
            background-color: var(--primary-color);
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
        }

        .btn:hover {
            background-color: var(--secondary-color);
        }

        .btn:disabled {
            background-color: #cccccc;
            cursor: not-allowed;
        }

        .file-input {
            display: none;
        }

        .preview-container {
            margin-top: 30px;
        }

        .preview-title {
            margin-bottom: 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .preview-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: 15px;
            margin-bottom: 20px;
        }

        .preview-item {
            position: relative;
            border: 1px solid var(--border-color);
            border-radius: 5px;
            overflow: hidden;
            transition: transform 0.2s;
        }

        .preview-item:hover {
            transform: scale(1.02);
        }

        .preview-item img {
            width: 100%;
            height: 150px;
            object-fit: cover;
            display: block;
        }

        .preview-item .remove-btn {
            position: absolute;
            top: 5px;
            right: 5px;
            background-color: rgba(255, 0, 0, 0.7);
            color: white;
            border: none;
            width: 25px;
            height: 25px;
            border-radius: 50%;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
        }

        .preview-item .remove-btn:hover {
            background-color: rgba(255, 0, 0, 0.9);
        }

        .loading {
            display: none;
            text-align: center;
            margin: 20px 0;
        }

        .loading-spinner {
            border: 4px solid rgba(0, 0, 0, 0.1);
            border-radius: 50%;
            border-top: 4px solid var(--primary-color);
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto 10px;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .theme-toggle {
            background: none;
            border: none;
            color: var(--text-color);
            cursor: pointer;
            font-size: 24px;
            padding: 5px;
        }

        select {
            padding: 8px 12px;
            border-radius: 5px;
            border: 1px solid var(--border-color);
            background-color: var(--background-color);
            color: var(--text-color);
        }

        .filename-input {
            padding: 8px 12px;
            border-radius: 5px;
            border: 1px solid var(--border-color);
            background-color: var(--background-color);
            color: var(--text-color);
            min-width: 200px;
        }

        @media (max-width: 768px) {
            .toolbar {
                flex-direction: column;
                align-items: flex-start;
            }
            
            .settings {
                width: 100%;
                margin-top: 10px;
            }
            
            .preview-grid {
                grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
            }
        }
JavaScript makes the page work functionally. At last, create a JavaScript file with the name of script.js, and remember that you've got to make a file with a .js extension.


 // Initialize jsPDF
        const { jsPDF } = window.jspdf;
        
        // DOM elements
        const dropArea = document.getElementById('dropArea');
        const fileInput = document.getElementById('fileInput');
        const uploadBtn = document.getElementById('uploadBtn');
        const convertBtn = document.getElementById('convertBtn');
        const previewContainer = document.getElementById('previewContainer');
        const previewGrid = document.getElementById('previewGrid');
        const imageCount = document.getElementById('imageCount');
        const loading = document.getElementById('loading');
        const orientationSelect = document.getElementById('orientation');
        const filenameInput = document.getElementById('filename');
        const themeToggle = document.getElementById('themeToggle');
        
        // Store uploaded files
        let files = [];
        
        // Theme toggle
        themeToggle.addEventListener('click', () => {
            document.body.dataset.theme = document.body.dataset.theme === 'dark' ? 'light' : 'dark';
            localStorage.setItem('theme', document.body.dataset.theme);
        });
        
        // Check for saved theme preference
        if (localStorage.getItem('theme') === 'dark' || 
            (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && !localStorage.getItem('theme'))) {
            document.body.dataset.theme = 'dark';
        }
        
        // Upload button click event
        uploadBtn.addEventListener('click', () => {
            fileInput.click();
        });
        
        // File input change event
        fileInput.addEventListener('change', (e) => {
            if (e.target.files.length > 0) {
                handleFiles(e.target.files);
            }
        });
        
        // Drag and drop events
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
            dropArea.addEventListener(eventName, preventDefaults, false);
        });
        
        function preventDefaults(e) {
            e.preventDefault();
            e.stopPropagation();
        }
        
        ['dragenter', 'dragover'].forEach(eventName => {
            dropArea.addEventListener(eventName, highlight, false);
        });
        
        ['dragleave', 'drop'].forEach(eventName => {
            dropArea.addEventListener(eventName, unhighlight, false);
        });
        
        function highlight() {
            dropArea.classList.add('highlight');
        }
        
        function unhighlight() {
            dropArea.classList.remove('highlight');
        }
        
        dropArea.addEventListener('drop', (e) => {
            const dt = e.dataTransfer;
            const droppedFiles = dt.files;
            
            if (droppedFiles.length > 0) {
                handleFiles(droppedFiles);
            }
        });
        
        // Handle uploaded files
        function handleFiles(newFiles) {
            const validFiles = Array.from(newFiles).filter(file => file.type.startsWith('image/'));
            
            if (validFiles.length === 0) {
                alert('Please upload valid image files.');
                return;
            }
            
            files = [...files, ...validFiles];
            updatePreview();
        }
        
        // Update preview grid
        function updatePreview() {
            if (files.length === 0) {
                previewContainer.style.display = 'none';
                convertBtn.disabled = true;
                return;
            }
            
            previewContainer.style.display = 'block';
            convertBtn.disabled = false;
            imageCount.textContent = `${files.length} ${files.length === 1 ? 'image' : 'images'}`;
            
            previewGrid.innerHTML = '';
            
            files.forEach((file, index) => {
                const reader = new FileReader();
                
                reader.onload = (e) => {
                    const previewItem = document.createElement('div');
                    previewItem.className = 'preview-item';
                    previewItem.dataset.index = index;
                    
                    const img = document.createElement('img');
                    img.src = e.target.result;
                    img.alt = file.name;
                    
                    const removeBtn = document.createElement('button');
                    removeBtn.className = 'remove-btn';
                    removeBtn.innerHTML = '×';
                    removeBtn.addEventListener('click', (e) => {
                        e.stopPropagation();
                        removeImage(index);
                    });
                    
                    previewItem.appendChild(img);
                    previewItem.appendChild(removeBtn);
                    previewGrid.appendChild(previewItem);
                };
                
                reader.readAsDataURL(file);
            });
            
            // Initialize Sortable for reordering
            new Sortable(previewGrid, {
                animation: 150,
                onEnd: (evt) => {
                    // Update files array based on new order
                    const newFiles = [...files];
                    const movedItem = newFiles.splice(evt.oldIndex, 1)[0];
                    newFiles.splice(evt.newIndex, 0, movedItem);
                    files = newFiles;
                }
            });
        }
        
        // Remove image from preview
        function removeImage(index) {
            files.splice(index, 1);
            updatePreview();
        }
        
        // Convert to PDF
        convertBtn.addEventListener('click', async () => {
            if (files.length === 0) return;
            
            loading.style.display = 'block';
            convertBtn.disabled = true;
            
            try {
                const orientation = orientationSelect.value;
                const pdf = new jsPDF({
                    orientation: orientation,
                    unit: 'mm'
                });
                
                // Process each image
                for (let i = 0; i < files.length; i++) {
                    const file = files[i];
                    const img = await loadImage(file);
                    
                    // Calculate dimensions to fit page
                    const pageWidth = pdf.internal.pageSize.getWidth();
                    const pageHeight = pdf.internal.pageSize.getHeight();
                    
                    let imgWidth = pageWidth - 20; // 10mm margin on each side
                    let imgHeight = (img.height * imgWidth) / img.width;
                    
                    // If image is too tall, scale down
                    if (imgHeight > pageHeight - 20) {
                        imgHeight = pageHeight - 20;
                        imgWidth = (img.width * imgHeight) / img.height;
                    }
                    
                    // Center the image on the page
                    const x = (pageWidth - imgWidth) / 2;
                    const y = (pageHeight - imgHeight) / 2;
                    
                    // Add image to PDF
                    pdf.addImage(img, 'JPEG', x, y, imgWidth, imgHeight);
                    
                    // Add new page if not the last image
                    if (i < files.length - 1) {
                        pdf.addPage();
                    }
                }
                
                // Download PDF
                const filename = filenameInput.value || 'images-to-pdf';
                pdf.save(`${filename}.pdf`);
                
            } catch (error) {
                console.error('Error generating PDF:', error);
                alert('An error occurred while generating the PDF. Please try again.');
            } finally {
                loading.style.display = 'none';
                convertBtn.disabled = false;
            }
        });
        
        // Helper function to load image and get dimensions
        function loadImage(file) {
            return new Promise((resolve, reject) => {
                const img = new Image();
                const reader = new FileReader();
                
                reader.onload = (e) => {
                    img.src = e.target.result;
                };
                
                img.onload = () => {
                    resolve(img);
                };
                
                img.onerror = () => {
                    reject(new Error('Failed to load image'));
                };
                
                reader.readAsDataURL(file);
            });
        }
We hope you Like this Post Thanks for coming Here

Thank you
Learning robo team

Post a Comment

Thank you
Learning robo team

Post a Comment (0)

Previous Post Next Post
Learning Robo says...
code copied