HTML Lesson Viewer with Multimedia Support

By Vandu
Jul 9, 2025

Follow us on


Build a tool to display course lessons using text, video, and PDFs.

HTML Lesson Viewer with Multimedia Support

Building a Responsive Lesson Viewer with HTML, CSS, JavaScript, and Tailwind CSS

Live Preview

In this tutorial, we'll create a responsive Lesson Viewer that can display course content in different formats (text, video, PDF). This component is ideal for e-learning platforms, online courses, or any educational application.

1. Project Overview

Our Lesson Viewer will have:

  • sidebar with course modules and lessons.

  • main content area that displays:

    • Text content (with syntax highlighting)

    • Embedded videos (YouTube)

    • PDF documents (using PDF.js)

  • Mobile responsiveness (collapsible sidebar on small screens).

  • Progress tracking and navigation controls.


2. Setting Up the Project

We'll use:

  • HTML5 for structure.

  • Tailwind CSS for styling.

  • JavaScript for interactivity.

  • PDF.js for rendering PDFs.

Basic HTML Template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Lesson Viewer</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <!-- PDF.js for PDF rendering -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
</head>
<body class="bg-gray-50 font-sans">
    <!-- Our Lesson Viewer will go here -->
</body>
</html>

3. Building the HTML Structure

We'll divide the layout into:

  • sidebar (for course navigation).

  • main content area (for lesson display).

  • footer (for navigation controls).

Sidebar Structure

 
<div class="flex h-screen overflow-hidden">
    <!-- Sidebar -->
    <div class="sidebar bg-white w-64 border-r border-gray-200 flex flex-col">
        <div class="p-4 border-b border-gray-200">
            <h2 class="text-xl font-semibold text-gray-800">Course Content</h2>
            <p class="text-sm text-gray-500">Introduction to Web Development</p>
        </div>
        <div class="flex-1 overflow-y-auto">
            <div class="space-y-1 p-2">
                <!-- Modules and lessons will go here -->
            </div>
        </div>
        <div class="p-4 border-t border-gray-200">
            <div class="flex items-center justify-between mb-2">
                <span class="text-sm font-medium text-gray-700">Progress</span>
                <span class="text-sm text-gray-500">25%</span>
            </div>
            <div class="progress-bar rounded-full">
                <div class="progress-fill rounded-full" style="width: 25%"></div>
            </div>
        </div>
    </div>

    <!-- Main Content Area -->
    <div class="content-area flex-1 flex flex-col overflow-hidden">
        <!-- Header -->
        <header class="bg-white border-b border-gray-200 flex items-center justify-between p-4">
            <button id="sidebar-toggle" class="md:hidden text-gray-500 focus:outline-none">
                <i class="fas fa-bars text-xl"></i>
            </button>
            <h1 class="text-xl font-semibold text-gray-800">Introduction to HTML</h1>
            <div class="flex items-center space-x-4">
                <button class="text-gray-500 hover:text-gray-700 focus:outline-none">
                    <i class="far fa-bookmark text-xl"></i>
                </button>
                <button class="text-gray-500 hover:text-gray-700 focus:outline-none">
                    <i class="fas fa-ellipsis-v text-xl"></i>
                </button>
            </div>
        </header>

        <!-- Lesson Content -->
        <main class="flex-1 overflow-y-auto p-4 md:p-6 bg-white">
            <!-- Text, Video, and PDF content will go here -->
        </main>

        <!-- Footer Navigation -->
        <footer class="bg-white border-t border-gray-200 p-4">
            <div class="flex justify-between items-center max-w-4xl mx-auto">
                <button class="px-4 py-2 border border-gray-300 rounded text-gray-700 hover:bg-gray-50 flex items-center disabled:opacity-50" disabled>
                    <i class="fas fa-arrow-left mr-2"></i> Previous
                </button>
                <div class="text-sm text-gray-500">
                    Lesson 1 of 12
                </div>
                <button class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 flex items-center">
                    Next <i class="fas fa-arrow-right ml-2"></i>
                </button>
            </div>
        </footer>
    </div>
</div>

4. Styling with Tailwind CSS

We'll enhance the UI with:

  • Responsive behavior (collapsible sidebar on mobile).

  • Interactive elements (hover effects, active states).

  • Custom CSS for PDF rendering.

Custom CSS (Inside <style> Tag)

.content-area {
    transition: all 0.3s ease;
}
.sidebar {
    transition: transform 0.3s ease;
}
@media (max-width: 768px) {
    .sidebar {
        transform: translateX(-100%);
        position: fixed;
        z-index: 50;
        height: 100vh;
        top: 0;
    }
    .sidebar.open {
        transform: translateX(0);
    }
    .overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.5);
        z-index: 40;
    }
    .overlay.open {
        display: block;
    }
}
#pdf-viewer {
    width: 100%;
    height: 70vh;
    border: 1px solid #e2e8f0;
    overflow-y: auto;
}
.lesson-item:hover {
    background-color: #f8fafc;
}
.lesson-item.active {
    background-color: #e2e8f0;
    border-left: 4px solid #4f46e5;
}
.progress-bar {
    height: 6px;
    background-color: #e2e8f0;
}
.progress-fill {
    height: 100%;
    background-color: #4f46e5;
    transition: width 0.3s ease;
}

5. Adding JavaScript Functionality

We'll implement:

  • Mobile sidebar toggle.

  • Lesson switching (text, video, PDF).

  • PDF rendering with PDF.js.

JavaScript Code

 
// Initialize PDF.js
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js';

document.addEventListener('DOMContentLoaded', function() {
    // Mobile sidebar toggle
    const sidebarToggle = document.getElementById('sidebar-toggle');
    const sidebar = document.querySelector('.sidebar');
    const overlay = document.querySelector('.overlay');
    
    sidebarToggle.addEventListener('click', function() {
        sidebar.classList.toggle('open');
        overlay.classList.toggle('open');
    });
    
    overlay.addEventListener('click', function() {
        sidebar.classList.remove('open');
        overlay.classList.remove('open');
    });
    
    // Lesson item click handler
    const lessonItems = document.querySelectorAll('.lesson-item');
    lessonItems.forEach(item => {
        item.addEventListener('click', function() {
            // Remove active class from all items
            lessonItems.forEach(i => i.classList.remove('active'));
            // Add active class to clicked item
            this.classList.add('active');
            
            // Update header title
            const title = this.querySelector('span').textContent;
            document.querySelector('header h1').textContent = title;
            
            // Determine content type and show appropriate content
            const icon = this.querySelector('i');
            if (icon.classList.contains('fa-file-alt')) {
                showTextContent();
            } else if (icon.classList.contains('fa-play-circle')) {
                showVideoContent();
            } else if (icon.classList.contains('fa-file-pdf')) {
                showPdfContent();
            }
        });
    });
    
    // PDF navigation
    const prevPageBtn = document.getElementById('prev-page');
    const nextPageBtn = document.getElementById('next-page');
    const pageInfo = document.getElementById('page-info');
    
    let pdfDoc = null,
        pageNum = 1,
        pageRendering = false,
        pageNumPending = null;
    
    function showTextContent() {
        document.getElementById('text-content').classList.remove('hidden');
        document.getElementById('video-content').classList.add('hidden');
        document.getElementById('pdf-content').classList.add('hidden');
    }
    
    function showVideoContent() {
        document.getElementById('text-content').classList.add('hidden');
        document.getElementById('video-content').classList.remove('hidden');
        document.getElementById('pdf-content').classList.add('hidden');
    }
    
    function showPdfContent() {
        document.getElementById('text-content').classList.add('hidden');
        document.getElementById('video-content').classList.add('hidden');
        document.getElementById('pdf-content').classList.remove('hidden');
        
        // Load a sample PDF (replace with your PDF URL)
        const url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf';
        
        pdfjsLib.getDocument(url).promise.then(function(pdfDoc_) {
            pdfDoc = pdfDoc_;
            pageInfo.textContent = `Page 1 of ${pdfDoc.numPages}`;
            
            // Render the first page
            renderPage(1);
        });
    }
    
    function renderPage(num) {
        pageRendering = true;
        
        pdfDoc.getPage(num).then(function(page) {
            const viewport = page.getViewport({ scale: 1.5 });
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;
            
            const renderContext = {
                canvasContext: context,
                viewport: viewport
            };
            
            const renderTask = page.render(renderContext);
            
            renderTask.promise.then(function() {
                pageRendering = false;
                
                const pdfViewer = document.getElementById('pdf-viewer');
                pdfViewer.innerHTML = '';
                pdfViewer.appendChild(canvas);
                
                if (pageNumPending !== null) {
                    renderPage(pageNumPending);
                    pageNumPending = null;
                }
            });
        });
        
        pageInfo.textContent = `Page ${num} of ${pdfDoc.numPages}`;
    }
    
    function onPrevPage() {
        if (pageNum <= 1) return;
        pageNum--;
        queueRenderPage(pageNum);
    }
    
    function onNextPage() {
        if (pageNum >= pdfDoc.numPages) return;
        pageNum++;
        queueRenderPage(pageNum);
    }
    
    prevPageBtn.addEventListener('click', onPrevPage);
    nextPageBtn.addEventListener('click', onNextPage);
    
    // Initially show text content
    showTextContent();
});

6. Testing and Final Touches

  • Test on different devices (mobile, tablet, desktop).

  • Ensure PDF rendering works (adjust scale if needed).

  • Add real course content (replace sample data).


© 2025 Pay18News. All rights reserved.