JavaScript Tutorial

Template Literals in JavaScript: Complete Guide with Examples

Master JavaScript template literals including string interpolation, multi-line strings, expression embedding, nested templates, tagged templates, and real-world examples with best practices.

Welcome back! ๐Ÿ‘‹ In the previous lesson, you learned all about string methods. Now let's explore one of the most beloved ES6 features โ€” Template Literals!

Before ES6, building dynamic strings in JavaScript was clunky and error-prone โ€” full of + operators, escaped quotes, and broken multi-line strings. Template literals changed everything. They give you a clean, powerful, and readable way to work with strings.

You'll use template literals in every single JavaScript project you ever write. Let's master them completely!


What are Template Literals?

Template literals are strings wrapped in backticks (`) instead of single or double quotes. They allow you to:

  • Embed variables and expressions directly inside strings
  • Write multi-line strings naturally
  • Build complex dynamic strings without messy concatenation
// Old way โ€” messy
let name = "Mihir";
let greeting = "Hello, " + name + "! Welcome back.";

// Template literal โ€” clean โœ…
let greeting = `Hello, ${name}! Welcome back.`;

console.log(greeting); // Hello, Mihir! Welcome back.

Syntax

`string text ${expression} string text`
  • Backticks ` โ€” wrap the entire string (not quotes)
  • ${} โ€” the interpolation slot โ€” anything inside is evaluated as JavaScript
  • Everything outside ${} is treated as plain text

1. String Interpolation

Embedding variables or expressions directly into a string using ${}.

Variables

let name  = "Mihir";
let role  = "Developer";
let city  = "Mumbai";

console.log(`Name: ${name}`);
console.log(`${name} is a ${role} from ${city}.`);
// Output: Mihir is a Developer from Mumbai.

Expressions

Any valid JavaScript expression works inside ${} โ€” math, comparisons, function calls, ternary operators โ€” anything.

let a = 10;
let b = 5;

console.log(`Sum:      ${a + b}`);       // 15
console.log(`Product:  ${a * b}`);       // 50
console.log(`Power:    ${a ** b}`);      // 100000
console.log(`Is even:  ${a % 2 === 0}`); // true

Function Calls

function getDiscount(price, percent) {
  return price - (price * percent / 100);
}

let price = 5000;
console.log(`Original: โ‚น${price}`);
console.log(`After 20% off: โ‚น${getDiscount(price, 20)}`);
// Output:
// Original: โ‚น5000
// After 20% off: โ‚น4000

Ternary Operator Inside ${}

let marks = 78;
console.log(`Result: ${marks >= 40 ? "Pass โœ…" : "Fail โŒ"}`);
// Output: Result: Pass โœ…

let stock = 0;
console.log(`Status: ${stock > 0 ? `${stock} in stock ๐ŸŸข` : "Out of stock ๐Ÿ”ด"}`);
// Output: Status: Out of stock ๐Ÿ”ด

Object Properties

let user = { name: "Priya", age: 26, role: "Editor" };

console.log(`User: ${user.name} (${user.role}), Age: ${user.age}`);
// Output: User: Priya (Editor), Age: 26

Array Values

let scores = [92, 85, 78];

console.log(`Scores: ${scores[0]}, ${scores[1]}, ${scores[2]}`);
console.log(`Total: ${scores.reduce((s, n) => s + n, 0)}`);
// Output:
// Scores: 92, 85, 78
// Total: 255

2. Multi-line Strings

Before template literals, writing multi-line strings required \n escape characters. Now you just press Enter.

Old Way โ€” Painful โŒ

let message = "Dear Mihir,\n\nThank you for signing up.\nWelcome to our platform!\n\nRegards,\nThe Team";
console.log(message);

Template Literal Way โ€” Clean โœ…

let name = "Mihir";

let message = `Dear ${name},

Thank you for signing up.
Welcome to our platform!

Regards,
The Team`;

console.log(message);
// Output:
// Dear Mihir,
//
// Thank you for signing up.
// Welcome to our platform!
//
// Regards,
// The Team

Building HTML Strings

let product = {
  name:   "Wireless Headphones",
  price:  4999,
  rating: 4.5,
};

let card = `
<div class="product-card">
  <h2>${product.name}</h2>
  <p class="price">โ‚น${product.price.toLocaleString()}</p>
  <p class="rating">โญ ${product.rating}/5</p>
  <button>Add to Cart</button>
</div>
`;

console.log(card);

Building Email Templates

function createWelcomeEmail(user) {
  return `
Subject: Welcome to LearnJS, ${user.name}!

Hi ${user.name},

Welcome aboard! ๐ŸŽ‰ Your account has been created successfully.

Here are your details:
  - Name:  ${user.name}
  - Email: ${user.email}
  - Plan:  ${user.plan}

Start learning at: https://learnjs.com/dashboard

Happy coding!
The LearnJS Team
  `.trim();
}

let newUser = { name: "Mihir", email: "mihir@example.com", plan: "Pro" };
console.log(createWelcomeEmail(newUser));

3. Nested Template Literals

You can put a template literal inside another template literal's ${}.

let isAdmin = true;
let username = "Mihir";

let header = `Welcome, ${username}! ${isAdmin ? `You have <strong>Admin</strong> access ๐Ÿ”‘` : `You are logged in as a User ๐Ÿ‘ค`}`;

console.log(header);
// Output: Welcome, Mihir! You have <strong>Admin</strong> access ๐Ÿ”‘
let cartItems = 3;

let cartMessage = `๐Ÿ›’ Cart: ${cartItems > 0
  ? `${cartItems} item${cartItems > 1 ? "s" : ""} โ€” ready to checkout!`
  : "Your cart is empty"}`;

console.log(cartMessage);
// Output: ๐Ÿ›’ Cart: 3 items โ€” ready to checkout!

4. Expressions and Logic Inside ${}

Since ${} evaluates any JavaScript expression, you can put quite a lot of logic right inside.

Math Operations

let radius = 7;
console.log(`Area of circle: ${(Math.PI * radius ** 2).toFixed(2)}`);
// Output: Area of circle: 153.94

Method Calls

let name = "  mihir shah  ";
console.log(`Hello, ${name.trim().split(" ").map(w => w[0].toUpperCase() + w.slice(1)).join(" ")}!`);
// Output: Hello, Mihir Shah!

Logical Operators

let user = { name: "Priya", nickname: "" };

console.log(`Hello, ${user.nickname || user.name}!`);
// Output: Hello, Priya! (nickname is empty, falls back to name)
let config = null;
console.log(`Theme: ${config?.theme ?? "dark"}`);
// Output: Theme: dark

5. Tagged Template Literals

A more advanced feature โ€” tagged templates let you process a template literal with a function. The function receives the string parts and interpolated values separately, giving you full control over how the output is built.

Syntax

tagFunction`string ${value} string`

Basic Tagged Template

function tag(strings, ...values) {
  console.log("Strings:", strings); // Array of string parts
  console.log("Values:",  values);  // Array of interpolated values
}

let name = "Mihir";
let role = "Developer";

tag`Hello, ${name}! You are a ${role}.`;
// Strings: ['Hello, ', '! You are a ', '.']
// Values:  ['Mihir', 'Developer']

Real-World Use โ€” Highlight Interpolated Values

function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => {
    let value = values[i - 1];
    return result + (value ? `**${value}**` : "") + str;
  });
}

let name  = "Mihir";
let score = 95;
let grade = "A+";

console.log(highlight`Student ${name} scored ${score} and earned grade ${grade}.`);
// Output: Student **Mihir** scored **95** and earned grade **A+**.

Real-World Use โ€” Safe HTML (Escape User Input)

function safeHTML(strings, ...values) {
  let result = strings[0];
  values.forEach((value, i) => {
    let safe = String(value)
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;");
    result += safe + strings[i + 1];
  });
  return result;
}

let userInput = '<script>alert("hacked!")</script>';
let username  = "Mihir";

console.log(safeHTML`<p>Hello, ${username}! Your message: ${userInput}</p>`);
// Output: <p>Hello, Mihir! Your message: &lt;script&gt;alert(&quot;hacked!&quot;)&lt;/script&gt;</p>

Template Literals vs String Concatenation

let name  = "Mihir";
let age   = 25;
let city  = "Mumbai";
let score = 92;

// โŒ Old concatenation โ€” hard to read
let msg1 = "Hello, " + name + "! You are " + age + " years old from " + city + " with a score of " + score + ".";

// โœ… Template literal โ€” clean and readable
let msg2 = `Hello, ${name}! You are ${age} years old from ${city} with a score of ${score}.`;

console.log(msg1); // Same output
console.log(msg2); // Same output โ€” but so much cleaner!
FeatureConcatenation +Template Literal
ReadabilityHard with many variablesClean and clear
Multi-lineRequires \nPress Enter naturally
ExpressionsAwkwardDirect inside ${}
HTML buildingVery messyNatural indentation
Method callsClunkyInline in ${}

Real-World Examples

Example 1: Generate a Product Card (HTML)

function renderProductCard(product) {
  let discountBadge = product.discount
    ? `<span class="badge">-${product.discount}% OFF</span>`
    : "";

  return `
<div class="card">
  ${discountBadge}
  <img src="${product.image}" alt="${product.name}" />
  <h3>${product.name}</h3>
  <p class="price">
    โ‚น${product.price.toLocaleString()}
    ${product.originalPrice ? `<del>โ‚น${product.originalPrice.toLocaleString()}</del>` : ""}
  </p>
  <p class="rating">โญ ${product.rating} (${product.reviews} reviews)</p>
  <button class="${product.inStock ? "btn-primary" : "btn-disabled"}">
    ${product.inStock ? "Add to Cart ๐Ÿ›’" : "Out of Stock"}
  </button>
</div>`.trim();
}

let product = {
  name: "Wireless Headphones",
  price: 3999,
  originalPrice: 4999,
  discount: 20,
  rating: 4.5,
  reviews: 1240,
  inStock: true,
  image: "/images/headphones.jpg",
};

console.log(renderProductCard(product));

Example 2: Build a Report Table

let students = [
  { name: "Mihir", marks: 92, grade: "A" },
  { name: "Priya", marks: 85, grade: "B" },
  { name: "Rahul", marks: 60, grade: "C" },
  { name: "Sara",  marks: 45, grade: "D" },
];

let rows = students
  .map(s => `  ${s.name.padEnd(10)} | ${String(s.marks).padStart(5)} | ${s.grade}`)
  .join("\n");

let report = `
โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘      STUDENT REPORT      โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฆโ•โ•โ•โ•โ•โ•โ•โ•ฆโ•โ•โ•โ•โ•โ•ฃ
โ•‘ Name       โ•‘ Marks โ•‘  G  โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฌโ•โ•โ•โ•โ•โ•โ•โ•ฌโ•โ•โ•โ•โ•โ•ฃ
${rows}
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฉโ•โ•โ•โ•โ•โ•โ•โ•ฉโ•โ•โ•โ•โ•โ•
Total Students: ${students.length}
Average Marks:  ${(students.reduce((s, st) => s + st.marks, 0) / students.length).toFixed(1)}
`.trim();

console.log(report);

Example 3: Dynamic SQL-style Query Builder

function buildQuery({ table, fields = "*", where = null, limit = null }) {
  let query = `SELECT ${fields} FROM ${table}`;

  if (where) query += `\nWHERE ${where}`;
  if (limit) query += `\nLIMIT ${limit}`;

  return query + ";";
}

console.log(buildQuery({ table: "users" }));
// SELECT * FROM users;

console.log(buildQuery({
  table:  "products",
  fields: "name, price",
  where:  "price < 1000 AND inStock = true",
  limit:  10,
}));
// SELECT name, price FROM products
// WHERE price < 1000 AND inStock = true
// LIMIT 10;

Example 4: Notification Message Builder

function buildNotification(type, data) {
  const messages = {
    like:    `โค๏ธ ${data.from} liked your post "${data.post}"`,
    comment: `๐Ÿ’ฌ ${data.from} commented: "${data.text}"`,
    follow:  `๐Ÿ‘ค ${data.from} started following you`,
    mention: `๐Ÿ”” ${data.from} mentioned you in "${data.post}"`,
  };

  return messages[type] ?? `๐Ÿ”” New notification from ${data.from}`;
}

console.log(buildNotification("like",    { from: "Priya",  post: "My JS Journey" }));
console.log(buildNotification("comment", { from: "Rahul",  text: "Great post!" }));
console.log(buildNotification("follow",  { from: "Sara"  }));
console.log(buildNotification("share",   { from: "Arjun", post: "Arrow Functions" }));
// Output:
// โค๏ธ Priya liked your post "My JS Journey"
// ๐Ÿ’ฌ Rahul commented: "Great post!"
// ๐Ÿ‘ค Sara started following you
// ๐Ÿ”” New notification from Arjun

Common Mistakes

Mistake 1: Using Quotes Instead of Backticks

let name = "Mihir";

// โŒ Using quotes โ€” ${name} is treated as plain text
let msg = "Hello, ${name}!";
console.log(msg); // Hello, ${name}!  โ† Not interpolated!

// โœ… Use backticks for interpolation
let msg = `Hello, ${name}!`;
console.log(msg); // Hello, Mihir! โœ…

Mistake 2: Unnecessary String Conversion

let count = 5;

// โŒ Redundant .toString() โ€” template literals handle it
let msg = `You have ${count.toString()} messages`;

// โœ… Just use the value directly
let msg = `You have ${count} messages`;
// Output: You have 5 messages โœ…

Mistake 3: Complex Logic Inside ${} โ€” Hurts Readability

let users = [{ name: "Mihir" }, { name: "Priya" }];

// โŒ Too much logic crammed inside โ€” hard to read
let msg = `Users: ${users.filter(u => u.name.length > 4).map(u => u.name.toUpperCase()).join(", ")}`;

// โœ… Compute first, then embed
let longNames = users.filter(u => u.name.length > 4).map(u => u.name.toUpperCase()).join(", ");
let msg = `Users: ${longNames}`;
console.log(msg); // Users: MIHIR โœ…

Mistake 4: Forgetting to Trim Multi-line Templates

function getGreeting(name) {
  // โŒ Leading newline from the template indent
  return `
  Hello, ${name}!`;
}
console.log(getGreeting("Mihir"));
// (empty line)
//   Hello, Mihir!   โ† extra indent

// โœ… Use .trim() to clean up
function getGreeting(name) {
  return `
  Hello, ${name}!`.trim();
}
console.log(getGreeting("Mihir")); // Hello, Mihir! โœ…

Practical Exercise

Create a file called template-literals.js:

// ๐ŸŽฏ Template Literals Practice

// 1. User profile card
function renderProfile(user) {
  let statusIcon = user.online ? "๐ŸŸข Online" : "๐Ÿ”ด Offline";
  let premiumBadge = user.premium ? " ๐Ÿ‘‘ Premium" : "";

  return `
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐Ÿ‘ค ${user.name.padEnd(24)}โ”‚
โ”‚  ๐Ÿ“ง ${user.email.padEnd(24)}โ”‚
โ”‚  ๐Ÿ™๏ธ  ${user.city.padEnd(23)}โ”‚
โ”‚  ${statusIcon.padEnd(27)}โ”‚
โ”‚  Plan: ${(user.plan + premiumBadge).padEnd(22)}โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜`.trim();
}

console.log("=== ๐Ÿ‘ค User Profiles ===\n");
console.log(renderProfile({
  name: "Mihir Shah", email: "mihir@example.com",
  city: "Mumbai", online: true, plan: "Pro", premium: true,
}));

console.log();
console.log(renderProfile({
  name: "Priya Nair", email: "priya@example.com",
  city: "Pune", online: false, plan: "Free", premium: false,
}));


// 2. Invoice generator
function generateInvoice(order) {
  let itemRows = order.items
    .map(item => `  ${item.name.padEnd(20)} โ‚น${String(item.price).padStart(6)} x${item.qty}  = โ‚น${item.price * item.qty}`)
    .join("\n");

  let subtotal = order.items.reduce((s, i) => s + i.price * i.qty, 0);
  let tax      = Math.round(subtotal * 0.18);
  let total    = subtotal + tax;

  return `
${"=".repeat(45)}
         INVOICE #${order.id}
${"=".repeat(45)}
Customer : ${order.customer}
Date     : ${order.date}
${"โ”€".repeat(45)}
ITEMS:
${itemRows}
${"โ”€".repeat(45)}
  Subtotal : โ‚น${subtotal.toLocaleString()}
  GST 18%  : โ‚น${tax.toLocaleString()}
  TOTAL    : โ‚น${total.toLocaleString()}
${"=".repeat(45)}
  Thank you for your order! ๐Ÿ™
${"=".repeat(45)}`.trim();
}

console.log("\n=== ๐Ÿงพ Invoice ===\n");
console.log(generateInvoice({
  id: "INV-2024-001",
  customer: "Mihir Shah",
  date: "13 Feb 2024",
  items: [
    { name: "JavaScript Course", price: 1999, qty: 1 },
    { name: "React Course",      price: 2499, qty: 1 },
    { name: "Node.js Course",    price: 1799, qty: 1 },
  ],
}));

Run it:

node template-literals.js

Expected Output:

=== ๐Ÿ‘ค User Profiles ===

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐Ÿ‘ค Mihir Shah              โ”‚
โ”‚  ๐Ÿ“ง mihir@example.com       โ”‚
โ”‚  ๐Ÿ™๏ธ  Mumbai                 โ”‚
โ”‚  ๐ŸŸข Online                  โ”‚
โ”‚  Plan: Pro ๐Ÿ‘‘ Premium       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

=== ๐Ÿงพ Invoice ===

=============================================
         INVOICE #INV-2024-001
=============================================
Customer : Mihir Shah
Date     : 13 Feb 2024
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ITEMS:
  JavaScript Course     โ‚น  1999 x1  = โ‚น1999
  React Course          โ‚น  2499 x1  = โ‚น2499
  Node.js Course        โ‚น  1799 x1  = โ‚น1799
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  Subtotal : โ‚น6,297
  GST 18%  : โ‚น1,133
  TOTAL    : โ‚น7,430
=============================================
  Thank you for your order! ๐Ÿ™
=============================================

Key Takeaways

Congratulations! ๐ŸŽ‰ You now fully understand template literals in JavaScript.

โœ… Template literals use backticks ` โ€” not quotes.

โœ… String interpolation โ€” ${} embeds any expression directly into the string.

โœ… Multi-line strings โ€” just press Enter โ€” no \n needed.

โœ… Inside ${} you can use variables, math, method calls, ternary operators, function calls โ€” any valid JS expression.

โœ… Nested template literals โ€” a template literal inside another template's ${} is perfectly valid.

โœ… Tagged templates โ€” process template literals with a function for advanced use cases like safe HTML and highlighting.

โœ… Always .trim() multi-line template literal returns to remove leading/trailing newlines.


Best Practices

  1. โœ… Always use template literals instead of + concatenation โ€” cleaner and more readable
  2. โœ… Keep ${} expressions simple โ€” complex logic should be computed before embedding
  3. โœ… Use .trim() on multi-line templates returned from functions
  4. โœ… Use template literals for HTML strings โ€” natural indentation and readability
  5. โœ… Use template literals for multi-line strings โ€” never \n concatenation
  6. โœ… Use nested templates sparingly โ€” one level is fine, more gets unreadable
  7. โœ… Use tagged templates for security-sensitive output like user-generated HTML
  8. โœ… Don't call .toString() inside ${} โ€” template literals convert values automatically

What's Next?

Excellent work! ๐ŸŽ‰ Template literals will make every string you write from here on cleaner and more expressive.

Next up, let's dive into one of the most important data structures in JavaScript:

Arrays and Array Methods โ†’ โ€” ordered lists, powerful built-in methods, and everything you need to work with collections of data like a pro!

Let's keep going! ๐Ÿ’ช