Markdown & Rich Text Live Previewer

Split-screen live Markdown to HTML parser with word count, character count, and estimated reading time calculator.

Difficulty: Beginner Est. Time: 20 mins Vanilla JS (ES6+) Includes HTML, CSS, JS & README (.ZIP)
Live UI Runner

Markdown & Rich Text Live Previewer

live-sandbox://markdown-previewer

1. Project Overview & Features

The Markdown & Rich Text Live Previewer is an essential frontend project designed to help you bridge the gap between learning JavaScript syntax and building interactive, responsive web applications.

Key Features Implemented:

  • Live Markdown parsing for headings, bold, italics, lists, code, and quotes
  • Real-time word, character, and reading time counter
  • Copy formatted HTML button

2. Step-by-Step Code Walkthrough

A Step 1: Semantic HTML Structure

We structure the interface using clean, semantic HTML elements. This ensures maximum accessibility and provides intuitive hooks for CSS classes and JavaScript query selectors.

HTML (index.html)
<div class="md-app">
  <div class="md-header">
    <h2>Markdown Live Preview</h2>
    <div class="stats">
      <span id="md-words">0 Words</span> Β· <span id="md-chars">0 Chars</span> Β· <span id="md-read">1 min read</span>
    </div>
  </div>

  <div class="md-split">
    <div class="md-editor-col">
      <textarea id="md-input" placeholder="Type Markdown here..."># Hello JavaScript!
Welcome to the **live markdown previewer**.

### Features:
- Real-time *instant rendering*
- Code blocks `const a = 1;`
- Clean and responsive layout

> "Code is like humor. When you have to explain it, it's bad."</textarea>
    </div>
    <div class="md-preview-col" id="md-output"></div>
  </div>
</div>

B Step 2: Styling & Responsive CSS

Modern CSS flexbox and grid layouts are used to make the UI look polished, centered, and responsive across desktop, tablet, and mobile screens.

CSS (style.css)
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
body {
  background: #0f172a;
  color: #f8fafc;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.md-app {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 20px;
  width: 100%;
  max-width: 720px;
  padding: 20px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
}
.md-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
  flex-wrap: wrap;
  gap: 8px;
}
.md-header h2 { font-size: 1.2rem; color: #38bdf8; }
.stats { color: #94a3b8; font-size: 0.85rem; }
.md-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  height: 320px;
}
@media (max-width: 600px) {
  .md-split { grid-template-columns: 1fr; height: auto; }
}
.md-editor-col textarea {
  width: 100%;
  height: 100%;
  min-height: 200px;
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 12px;
  color: #f8fafc;
  padding: 14px;
  font-family: monospace;
  font-size: 0.9rem;
  resize: none;
  outline: none;
}
.md-preview-col {
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 14px;
  overflow-y: auto;
  color: #cbd5e1;
  font-size: 0.92rem;
  line-height: 1.6;
}
.md-preview-col h1, .md-preview-col h2, .md-preview-col h3 { color: #f8fafc; margin-bottom: 8px; }
.md-preview-col ul { padding-left: 20px; margin-bottom: 8px; }
.md-preview-col blockquote { border-left: 3px solid #38bdf8; padding-left: 10px; color: #94a3b8; margin: 8px 0; font-style: italic; }
.md-preview-col code { background: #334155; padding: 2px 6px; border-radius: 4px; font-family: monospace; color: #38bdf8; }

C Step 3: JavaScript Logic & Event Handling

Here is the complete JavaScript code handling the state, event listeners, mathematical logic, and dynamic DOM rendering:

JavaScript (script.js)
const input = document.getElementById('md-input');
const output = document.getElementById('md-output');
const wordsEl = document.getElementById('md-words');
const charsEl = document.getElementById('md-chars');
const readEl = document.getElementById('md-read');

function parseMarkdown(md) {
  let html = md
    .replace(/^### (.*$)/gim, '<h3>$1</h3>')
    .replace(/^## (.*$)/gim, '<h2>$1</h2>')
    .replace(/^# (.*$)/gim, '<h1>$1</h1>')
    .replace(/^\> (.*$)/gim, '<blockquote>$1</blockquote>')
    .replace(/\*\*(.*)\*\*/gim, '<strong>$1</strong>')
    .replace(/\*(.*)\*/gim, '<em>$1</em>')
    .replace(/`(.*?)`/gim, '<code>$1</code>')
    .replace(/^\- (.*$)/gim, '<li>$1</li>')
    .replace(/\n$/gim, '<br>');

  return html;
}

function updatePreview() {
  const text = input.value;
  output.innerHTML = parseMarkdown(text);

  const words = text.trim() ? text.trim().split(/\s+/).length : 0;
  const chars = text.length;
  const readTime = Math.max(1, Math.ceil(words / 200));

  wordsEl.textContent = `${words} Words`;
  charsEl.textContent = `${chars} Chars`;
  readEl.textContent = `${readTime} min read`;
}

input.addEventListener('input', updatePreview);
updatePreview();

3. Core JavaScript Concepts You Learned

Regex Markdown Parsing

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

String Metrics (Words, Chars)

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

Live Input Events

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

DOM innerHTML Sanitization

Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.

4. How to Run Locally on Your Computer

  1. Download the project ZIP: Click the Download Project (.ZIP) button at the top or in the live runner to save markdown-previewer-project.zip.
  2. Extract the archive: Unzip the downloaded file. Inside you will find separate index.html, style.css, script.js, index-standalone.html, and a comprehensive README.md.
  3. Open in any browser: Simply double-click index.html (or index-standalone.html) to open and test immediately in Chrome, Firefox, Safari, or Edge.
  4. Edit in Visual Studio Code: Open the extracted folder in VS Code. Right-click index.html and select "Open with Live Server" to enjoy instant live reloading as you modify HTML, CSS, or JS!

Bonus Challenges for Learners

Ready to level up? Try adding these extra features on your own:

  • Add sound effects or audio feedback for user button clicks.
  • Add custom theme color customizer with CSS variables.
  • Export the results to PDF or copy as a formatted text summary.

Other Beginner Projects You Might Like

Beginner25 mins
Productivity & UI

Smart To-Do List with LocalStorage

A full-featured task manager with local storage persistence, filtering (All, Active, Completed), task counter, and priority levels.

Safe LocalStorage APIArray Methods (map, filter, unshift)Event Delegation & Keyboard Triggers+2
Beginner30 mins
Productivity & UI

Personal Expense & Budget Tracker

Track daily income and expenses with real-time balance calculations, transaction histories, deletion, and local storage support.

Array.prototype.reduce()localStorage PersistenceForm Validation+2