Template Literals in JavaScript: Write Cleaner Strings

Introduction
String handling in JavaScript used to be one of those things you just accepted as annoying. You had + operators scattered everywhere, escaped quotes inside quotes, and multi-line strings that looked like someone had an argument with their keyboard. Then ES6 came along and fixed most of it in one go.
The Problem With Old-School Concatenation
Here is a typical piece of pre-ES6 code that builds a greeting:
var name = "Priya";
var age = 28;
var city = "Mumbai";
var message = "Hello, my name is " + name + ". I am " + age + " years old and I live in " + city + ".";
It works. It also looks like you assembled it with scotch tape. Every string segment needs its own quote pair, and every variable needs its own + on each side. Miss one space and you get "I am28years old". Add a variable mid-sentence and you are counting plus signs to make sure you have the right number.
Multi-line strings were worse:
var html = "<div class='card'>" +
"<h2>" + title + "</h2>" +
"<p>" + description + "</p>" +
"</div>";
This is technically fine but reading it is a chore. You have to mentally strip the quotes and plus signs to understand the actual structure.
Template Literal Syntax
Template literals use backticks instead of single or double quotes:
const greeting = `Hello, world`;
That alone changes nothing. The power comes from two features built on top of that syntax: interpolation and native multi-line support.
Embedding Variables Directly in Strings
Inside a template literal, you can drop any JavaScript expression directly into the string using ${}:
const name = "Priya";
const age = 28;
const city = "Mumbai";
const message = `Hello, my name is \({name}. I am \){age} years old and I live in ${city}.`;
The string reads exactly like it will appear at runtime. No plus signs, no closing and reopening quotes. You just write the sentence and put variables where they belong.
The ${} syntax accepts any valid JavaScript expression, not just variables:
const price = 450;
const quantity = 3;
console.log(`Total: ${price * quantity} rupees`);
// Total: 1350 rupees
const user = { name: "Arjun", role: "admin" };
console.log(`Welcome, \({user.name}. Your role is \){user.role}.`);
// Welcome, Arjun. Your role is admin.
const score = 72;
console.log(`Result: ${score >= 60 ? "Pass" : "Fail"}`);
// Result: Pass
Ternaries, method calls, object properties, arithmetic, all of it works inside ${} without any extra setup.
Multi-Line Strings Without the Mess
With regular strings, a newline inside quotes is a syntax error. The old workaround was \n or concatenating across lines:
// Old way
var poem = "Line one\n" +
"Line two\n" +
"Line three";
Template literals preserve whitespace and line breaks naturally:
const poem = `Line one
Line two
Line three`;
What you type is what you get. This makes building HTML fragments or multi-line output much more readable:
const card = `
<div class="card">
<h2>${title}</h2>
<p>${description}</p>
<span class="tag">${category}</span>
</div>
`;
Compare that to the concatenation version from earlier and the difference is obvious. The structure is visible. You can read it like HTML.
Where Template Literals Actually Show Up
Building URLs and query strings
const baseUrl = "https://api.example.com";
const userId = 42;
const endpoint = `\({baseUrl}/users/\){userId}/orders`;
Before: baseUrl + "/users/" + userId + "/orders". The template version is just clearer.
Constructing SQL or query strings
const table = "products";
const limit = 10;
const query = `SELECT * FROM \({table} WHERE active = true LIMIT \){limit}`;
Generating error messages
function divide(a, b) {
if (b === 0) {
throw new Error(`Cannot divide ${a} by zero`);
}
return a / b;
}
Logging with context
console.log(`[\({new Date().toISOString()}] User \){userId} logged in from ${ip}`);
React and JSX (or template-based rendering)
Template literals come up a lot in dynamic class names and inline styles:
const className = `btn \({isActive ? "btn-primary" : "btn-secondary"} \){isDisabled ? "disabled" : ""}`;
Tagged Templates
Tagged templates are an advanced form of template literals. You place a function name directly before the backtick, and that function gets to control what the template produces:
function tag(strings, ...values) {
console.log(strings); // ["Hello, ", "!"]
console.log(values); // ["Sameer"]
}
tag`Hello, ${"Sameer"}!`;
The tag function receives the static string parts as an array and the interpolated values as separate arguments. Whatever the function returns becomes the final value.
A simple practical use is highlighting dynamic values for debugging:
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
const val = values[i] !== undefined ? `[${values[i]}]` : "";
return result + str + val;
}, "");
}
const user = "Arjun";
const score = 94;
console.log(highlight`Student \({user} scored \){score} marks.`);
// Student [Arjun] scored [94] marks.
A Side-by-Side Comparison
Before:
function greet(user) {
return "Hello, " + user.name + "! You have " + user.messages + " unread message" + (user.messages === 1 ? "" : "s") + ".";
}
After:
function greet(user) {
const plural = user.messages === 1 ? "" : "s";
return `Hello, \({user.name}! You have \){user.messages} unread message${plural}.`;
}
The second version takes less mental energy to parse. You can see the sentence structure without untangling the concatenation logic.
Conclusion
Template literals are one of those features that feels minor until you use it for a week and then cannot imagine going back. The code you write is closer to the output you intend, and that gap matters when you are reading code three months after you wrote it.




