Skip to main content

Command Palette

Search for a command to run...

Template Literals in JavaScript: The Modern Way to Work with Strings

Published
15 min read

Introduction

If you've been writing JavaScript for a while, you've probably spent time building strings by concatenating multiple pieces together. It can get messy, error-prone, and hard to read. Template literals are a modern JavaScript feature that completely transforms how you work with strings. They make your code cleaner, more readable, and less prone to mistakes. In this blog, we'll explore template literals in detail and see why they've become the preferred way to build strings in modern JavaScript.


1. Problems with Traditional String Concatenation

Before template literals, JavaScript developers had to use concatenation to build strings dynamically. This approach has several problems.

The Basic Problem: Mixing Strings and Variables

const name = "Rajeev";
const age = 25;
const city = "Mumbai";

// Old way: Using concatenation
const message = "Hello, my name is " + name + " and I am " + age + " years old. I live in " + city + ".";
console.log(message); // Hello, my name is Rajeev and I am 25 years old. I live in Mumbai.

While this works, it's tedious and error-prone. You have to carefully count your quotes and plus signs.

Problem 1: Hard to Read

const product = "Laptop";
const price = 50000;
const discount = 10;
const finalPrice = price - (price * discount / 100);

// This is hard to read
const receipt = "Product: " + product + "\nPrice: Rs." + price + "\nDiscount: " + discount + "%\nFinal Price: Rs." + finalPrice;
console.log(receipt);

The string gets lost in a sea of plus signs and quotes.

Problem 2: Easy to Make Mistakes

const firstName = "Ananya";
const lastName = "Sharma";

// Forgot a space!
const fullName = firstName + "" + lastName; // "AnanyaSharma"

// Another mistake
const greeting = "Welcome" + firstName; // "WelcomAnanya" - typo in variable name

Small typos can go unnoticed and cause bugs.

Problem 3: Escaping Quotes

// Escaping gets messy
const quote = "She said, \"Hello, how are you?\" to me.";
console.log(quote); // She said, "Hello, how are you?" to me.

// With single quotes inside double quotes
const message = "It's a beautiful day";
console.log(message); // It's a beautiful day

// But what if you mix them?
const mixed = "He said, \"It's a beautiful day\" to me.";
console.log(mixed); // He said, "It's a beautiful day" to me.

You have to escape quotes with backslashes, making the code look messy.

Problem 4: Multi-line Strings Are Awkward

// Trying to create a multi-line string
const poem = "Roses are red,\nViolets are blue,\nSugar is sweet,\nAnd so are you.";
console.log(poem);

// Or you have to break it into multiple lines
const multiLine = "This is line 1 " +
                  "This is line 2 " +
                  "This is line 3";
console.log(multiLine);

Both approaches are awkward and require manual line breaks or concatenation.

Problem 5: Conditional Strings Are Complex

const user = "Priya";
const isAdmin = true;
const itemCount = 5;

// Building conditional strings with concatenation is verbose
const message = "Hello " + user + "! " + 
                (isAdmin ? "You are an administrator. " : "") + 
                "You have " + itemCount + " items.";

console.log(message); // Hello Priya! You are an administrator. You have 5 items.

Complex expressions inside string concatenation are hard to follow.


2. Template Literal Syntax

Template literals use backticks (`) instead of quotes, and they solve all the problems we just discussed.

Basic Syntax:

// Old way with quotes
const simple = "Hello World";

// New way with backticks (template literal)
const template = `Hello World`;

console.log(simple); // Hello World
console.log(template); // Hello World

Both produce the same result, but template literals have powerful features that regular strings don't have.

Backticks Are Key:

// These are three different things:

// Regular string with double quotes
const double = "Hello";

// Regular string with single quotes
const single = 'Hello';

// Template literal with backticks
const template = `Hello`;

// Template literals have special powers that others don't

Remember: Use backticks (`) for template literals, not regular quotes.

When to Use Each:

// Use regular strings for simple text
const name = "Deepak";

// Use template literals when you need to embed variables or multi-line text
const greeting = `Hello, ${name}!`;

// Or when building complex strings
const html = `
  <div class="card">
    <h1>${name}</h1>
  </div>
`;

3. Embedding Variables in Strings

This is the most powerful feature of template literals. You can embed variables and expressions directly inside the string using ${...} syntax.

Basic Variable Embedding:

const firstName = "Vikram";
const lastName = "Singh";
const age = 28;

// The old way
const oldWay = "Name: " + firstName + " " + lastName + ", Age: " + age;

// The new way with template literals
const newWay = `Name: \({firstName} \){lastName}, Age: ${age}`;

console.log(newWay); // Name: Vikram Singh, Age: 28

Much cleaner! The variables appear directly in the string where you need them.

Embedding Expressions:

You can put any JavaScript expression inside ${}, not just variables:

const price = 1000;
const quantity = 5;

// Simple arithmetic
const total = `Total cost: Rs.${price * quantity}`;
console.log(total); // Total cost: Rs.5000

// Method calls
const name = "ananya sharma";
const greeting = `Hello, ${name.toUpperCase()}!`;
console.log(greeting); // Hello, ANANYA SHARMA!

// Ternary operators
const age = 21;
const ageGroup = `Age group: ${age >= 18 ? "Adult" : "Minor"}`;
console.log(ageGroup); // Age group: Adult

// Function calls
function getDiscount(amount) {
  return amount * 0.1;
}

const originalPrice = 500;
const discount = getDiscount(originalPrice);
const finalPrice = `Original: Rs.\({originalPrice}, Discount: Rs.\){discount}, Final: Rs.${originalPrice - discount}`;
console.log(finalPrice); // Original: Rs.500, Discount: Rs.50, Final: Rs.450

Complex Expressions:

const student = {
  name: "Shreya",
  marks: 85,
  subject: "Mathematics"
};

// Accessing object properties inside template literal
const result = `\({student.name} scored \){student.marks} in ${student.subject}`;
console.log(result); // Shreya scored 85 in Mathematics

// Array operations
const fruits = ["Apple", "Banana", "Mango"];
const fruitList = `Fruits: ${fruits.join(", ")}`;
console.log(fruitList); // Fruits: Apple, Banana, Mango

// Nested template literals
const items = 3;
const itemList = `You have \({items} items: \){items > 0 ? `${items} things` : "nothing"}`;
console.log(itemList); // You have 3 items: 3 things

Escaping in Template Literals:

// Backticks don't need escaping inside template literals
const quote = `She said, "Hello!" to me.`;
console.log(quote); // She said, "Hello!" to me.

// Single quotes also don't need escaping
const message = `It's a beautiful day`;
console.log(message); // It's a beautiful day

// But if you need a backtick, you must escape it
const code = `This is a backtick: \` symbol`;
console.log(code); // This is a backtick: ` symbol

// Backslashes
const path = `C:\\Users\\Name\\Documents`;
console.log(path); // C:\Users\Name\Documents

4. Multi-line Strings

One of the best features of template literals is how easy it is to create multi-line strings.

Multi-line Without Line Breaks:

// Old way: concatenation with \n
const oldPoem = "Roses are red,\nViolets are blue,\nSugar is sweet,\nAnd so are you.";

// New way: just press Enter inside template literal
const newPoem = `Roses are red,
Violets are blue,
Sugar is sweet,
And so are you.`;

console.log(newPoem);
// Output:
// Roses are red,
// Violets are blue,
// Sugar is sweet,
// And so are you.

The template literal preserves the actual line breaks in your code.

Creating HTML Strings:

const productName = "Laptop";
const price = 50000;
const inStock = true;

const html = `
  <div class="product">
    <h2>${productName}</h2>
    <p class="price">Rs.${price}</p>
    <p class="status">${inStock ? "In Stock" : "Out of Stock"}</p>
  </div>
`;

console.log(html);
// Output:
//   <div class="product">
//     <h2>Laptop</h2>
//     <p class="price">Rs.50000</p>
//     <p class="status">In Stock</p>
//   </div>

Creating JSON:

const user = {
  name: "Arjun",
  age: 24,
  email: "arjun@example.com"
};

const jsonString = `
{
  "name": "${user.name}",
  "age": ${user.age},
  "email": "${user.email}"
}
`;

console.log(jsonString);

Creating SQL Queries:

const userId = 5;
const userName = "Priya";
const userEmail = "priya@example.com";

const sqlQuery = `
  INSERT INTO users (id, name, email)
  VALUES (\({userId}, '\){userName}', '${userEmail}')
`;

console.log(sqlQuery);

Preserving Indentation:

const menu = `
  Menu
  ====
  1. Coffee     Rs.100
  2. Tea        Rs.50
  3. Juice      Rs.80
  4. Water      Rs.20
`;

console.log(menu);
// Output preserves all the spacing

5. Use Cases in Modern JavaScript

Template literals are used everywhere in modern JavaScript. Let's explore practical use cases.

Use Case 1: Logging and Debugging

const user = "Rajesh";
const action = "logged in";
const timestamp = new Date().toLocaleString();

// Clear, readable logging
console.log(`\({user} \){action} at ${timestamp}`);
// Output: Rajesh logged in at 3/26/2026, 2:30:45 PM

Use Case 2: Error Messages

const errorCode = 404;
const resource = "User Profile";
const method = "GET";

// Before: Hard to read
const oldError = "Error " + errorCode + ": " + method + " request for " + resource + " failed";

// After: Clear and readable
const newError = `Error \({errorCode}: \){method} request for ${resource} failed`;

console.log(newError); // Error 404: GET request for User Profile failed

Use Case 3: Building Dynamic URLs

const baseUrl = "https://api.example.com";
const endpoint = "users";
const userId = 123;

const apiUrl = `\({baseUrl}/\){endpoint}/${userId}`;
console.log(apiUrl); // https://api.example.com/users/123

// With query parameters
const searchTerm = "javascript";
const limit = 10;
const searchUrl = `\({baseUrl}/search?q=\){searchTerm}&limit=${limit}`;
console.log(searchUrl); // https://api.example.com/search?q=javascript&limit=10

Use Case 4: Building Dynamic CSS

const primaryColor = "#FF6B6B";
const fontSize = "16px";
const fontFamily = "Arial";

const styles = `
  body {
    font-family: ${fontFamily};
    font-size: ${fontSize};
    color: ${primaryColor};
  }
`;

console.log(styles);

Use Case 5: Creating Reusable Components

function createButton(text, color, size) {
  return `
    <button style="background-color: \({color}; padding: \){size};">
      ${text}
    </button>
  `;
}

const btn1 = createButton("Click Me", "blue", "10px");
const btn2 = createButton("Submit", "green", "15px");

console.log(btn1);
// Output:
//     <button style="background-color: blue; padding: 10px;">
//       Click Me
//     </button>

Use Case 6: Building Data Displays

const students = [
  { name: "Aman", marks: 85 },
  { name: "Bhavna", marks: 92 },
  { name: "Chirag", marks: 78 }
];

const report = `
STUDENT REPORT
==============
\({students.map(s => `\){s.name.padEnd(15)} - ${s.marks}/100`).join("\n")}
`;

console.log(report);
// Output:
// STUDENT REPORT
// ==============
// Aman            - 85/100
// Bhavna          - 92/100
// Chirag          - 78/100

Use Case 7: Configuration Objects

const appName = "MyApp";
const version = "1.0.0";
const environment = "production";
const apiKey = "secret123";

const config = `
{
  "app": "${appName}",
  "version": "${version}",
  "environment": "${environment}",
  "apiKey": "${apiKey}",
  "timestamp": "${new Date().toISOString()}"
}
`;

console.log(config);

6. Comparison: Old vs New

Let's see side-by-side comparisons of old string concatenation versus template literals.

Example 1: Simple Greeting

// OLD WAY
const firstName = "Priya";
const lastName = "Sharma";
const greeting_old = "Hello, " + firstName + " " + lastName + "!";

// NEW WAY
const greeting_new = `Hello, \({firstName} \){lastName}!`;

console.log(greeting_old); // Hello, Priya Sharma!
console.log(greeting_new); // Hello, Priya Sharma!

Example 2: Calculation

const subtotal = 1000;
const tax = 100;
const shipping = 50;

// OLD WAY
const receipt_old = "Subtotal: Rs." + subtotal + "\nTax: Rs." + tax + "\nShipping: Rs." + shipping + "\nTotal: Rs." + (subtotal + tax + shipping);

// NEW WAY
const receipt_new = `
Subtotal: Rs.${subtotal}
Tax: Rs.${tax}
Shipping: Rs.${shipping}
Total: Rs.${subtotal + tax + shipping}
`;

console.log(receipt_old);
console.log(receipt_new);

Example 3: Building HTML

const title = "Welcome";
const content = "This is the main content";
const footer = "Copyright 2026";

// OLD WAY
const html_old = "<div>" +
  "<h1>" + title + "</h1>" +
  "<p>" + content + "</p>" +
  "<footer>" + footer + "</footer>" +
"</div>";

// NEW WAY
const html_new = `
<div>
  <h1>${title}</h1>
  <p>${content}</p>
  <footer>${footer}</footer>
</div>
`;

console.log(html_old);
console.log(html_new);

Readability Comparison:

Aspect Old Concatenation Template Literals
Readability Hard to follow Easy to read
Mistakes Easy to make errors Less error-prone
Multi-line Awkward with \n or + Natural
Expressions Breaks flow Inline with ${}
Maintenance Difficult Easy

7. Tagged Template Literals

Advanced feature: You can tag template literals with a function to process them in a custom way.

Basic Tagged Template:

function highlight(strings, ...values) {
  console.log("Strings:", strings);
  console.log("Values:", values);
  
  let result = "";
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
    if (i < values.length) {
      result += "[HIGHLIGHTED: " + values[i] + "]";
    }
  }
  return result;
}

const name = "Vikram";
const age = 25;

const output = highlight`My name is \({name} and I am \){age} years old`;
console.log(output);
// Output: My name is [HIGHLIGHTED: Vikram] and I am [HIGHLIGHTED: 25] years old

Practical Example: HTML Sanitization

function sanitizeHTML(strings, ...values) {
  let result = "";
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
    if (i < values.length) {
      // Escape HTML special characters in values
      const escaped = String(values[i])
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;");
      result += escaped;
    }
  }
  return result;
}

const userInput = "<script>alert('hacked')</script>";
const html = sanitizeHTML`<p>${userInput}</p>`;
console.log(html); // <p>&lt;script&gt;alert('hacked')&lt;/script&gt;</p>

8. Common Patterns and Best Practices

Pattern 1: Conditional Rendering

const isLoggedIn = true;
const username = "Sneha";

const status = `
  \({isLoggedIn ? `Welcome back, \){username}!` : "Please log in."}
`;

console.log(status); // Welcome back, Sneha!

Pattern 2: Mapping Arrays

const items = ["Bread", "Milk", "Eggs"];

const list = `
Shopping List:
\({items.map((item, index) => `\){index + 1}. ${item}`).join("\n")}
`;

console.log(list);
// Output:
// Shopping List:
// 1. Bread
// 2. Milk
// 3. Eggs

Pattern 3: Formatting Numbers and Dates

const amount = 5000;
const date = new Date();

const receipt = `
Transaction Date: ${date.toLocaleDateString()}
Amount: Rs.${amount.toLocaleString()}
Time: ${date.toLocaleTimeString()}
`;

console.log(receipt);
// Output:
// Transaction Date: 3/26/2026
// Amount: Rs.5,000
// Time: 2:30:45 PM

Pattern 4: Default Values with OR operator

const user = { name: "Raj" }; // no email

const profile = `
Name: ${user.name}
Email: ${user.email || "Not provided"}
Phone: ${user.phone || "Not provided"}
`;

console.log(profile);
// Output:
// Name: Raj
// Email: Not provided
// Phone: Not provided

Pattern 5: Nested Template Literals

function renderUser(user) {
  return `<div class="user">${user.name}</div>`;
}

const users = [
  { name: "Arjun" },
  { name: "Bhavna" }
];

const html = `
<div class="users">
  ${users.map(user => renderUser(user)).join("")}
</div>
`;

console.log(html);

9. Real-World Example: Building a Blog Post Component

Let's create a practical example that combines multiple features:

function createBlogPost(post) {
  const { title, author, date, content, tags, likes, comments } = post;
  const formattedDate = new Date(date).toLocaleDateString();
  
  return `
    <article class="blog-post">
      <div class="header">
        <h1>${title}</h1>
        <div class="meta">
          <span class="author">By ${author}</span>
          <span class="date">${formattedDate}</span>
        </div>
      </div>
      
      <div class="content">
        ${content}
      </div>
      
      <div class="tags">
        ${tags.length > 0 ? `
          <strong>Tags:</strong>
          \({tags.map(tag => `<span class="tag">#\){tag}</span>`).join(" ")}
        ` : ""}
      </div>
      
      <div class="footer">
        <span class="likes">
          \({likes} \){likes === 1 ? "like" : "likes"}
        </span>
        <span class="comments">
          \({comments} \){comments === 1 ? "comment" : "comments"}
        </span>
      </div>
    </article>
  `;
}

// Usage
const blogPost = {
  title: "Understanding Template Literals",
  author: "Ashish Singodiya",
  date: "2026-03-26",
  content: "Template literals are one of the best features in modern JavaScript...",
  tags: ["javascript", "es6", "strings"],
  likes: 42,
  comments: 7
};

const html = createBlogPost(blogPost);
console.log(html);

10. Performance Consideration

Template literals are not slower than string concatenation. In fact, modern JavaScript engines optimize them equally well.

// All three are equally performant in modern browsers
const a = "Hello " + name;
const b = `Hello ${name}`;
const c = "Hello ".concat(name);

// Use whichever is most readable for your use case

The choice should be based on readability, not performance.


Conclusion

Template literals have revolutionized how we work with strings in JavaScript. Here's a summary of their benefits:

  1. Cleaner Code: Variables are embedded directly where needed

  2. Better Readability: No more confusing chains of + operators

  3. Multi-line Strings: Just press Enter, no need for \n

  4. Fewer Mistakes: Less chance of forgetting quotes or spaces

  5. Powerful Expressions: Anything inside ${} is evaluated

  6. Modern Standard: Supported in all modern browsers and Node.js

If you're still using string concatenation in 2026, it's time to switch to template literals. They're easier to write, easier to read, and easier to maintain. Start using them in your projects today, and you'll wonder how you ever lived without them.

Template literals aren't just a nice feature to have, they're a modern standard that every JavaScript developer should be comfortable using. Make them a habit, and your code will be cleaner and more professional.