JavaScript Template Literals: String Interpolation & Multiline Strings
Template literals (also called template strings) are one of the most useful features in modern JavaScript. They make working with strings cleaner, more readable, and more powerful.
What are Template Literals?
Template literals are strings enclosed in backticks (`) instead of quotes (' or "):
// Old way (regular strings)
const name = "Alice";
const greeting = "Hello, " + name + "!";
console.log(greeting); // Hello, Alice!
// New way (template literal)
const name = "Alice";
const greeting = `Hello, ${name}!`;
console.log(greeting); // Hello, Alice!
The ${} syntax lets you embed expressions directly in the string.
Key Features
1. String Interpolation with ${}
const x = 10;
const y = 20;
// Can do any expression inside ${}
console.log(`${x} + ${y} = ${x + y}`); // 10 + 20 = 30
const price = 99.99;
console.log(`The price is $${price.toFixed(2)}`); // The price is $99.99
const count = 5;
console.log(`You have ${count > 1 ? 'items' : 'item'}`); // You have items
You can put any valid JavaScript expression inside ${}.
2. Multiline Strings
// Old way (awkward)
const poem = "Roses are red,\n" +
"Violets are blue,\n" +
"Templates are great,\n" +
"And so are you!";
// New way (clean)
const poem = `Roses are red,
Violets are blue,
Templates are great,
And so are you!`;
console.log(poem);
// Output (preserves line breaks):
// Roses are red,
// Violets are blue,
// Templates are great,
// And so are you!
Template literals preserve whitespace and line breaks exactly as written.
3. Function Calls Inside Expressions
function uppercase(str) {
return str.toUpperCase();
}
const name = "alice";
console.log(`Hello, ${uppercase(name)}!`); // Hello, ALICE!
const data = {
firstName: "John",
lastName: "Doe"
};
console.log(`Full name: ${data.firstName} ${data.lastName}`); // Full name: John Doe
4. Conditional Logic Inside Expressions
const age = 17;
console.log(`You are ${age >= 18 ? 'an adult' : 'a minor'}.`);
// You are a minor.
const items = ['apple', 'banana', 'orange'];
console.log(`Items: ${items.length > 0 ? items.join(', ') : 'none'}`);
// Items: apple, banana, orange
Real-World Examples
Example 1: HTML Templating
const user = {
id: 1,
name: "Alice",
email: "alice@example.com"
};
const html = `
<div class="user-card">
<h2>${user.name}</h2>
<p>Email: ${user.email}</p>
<button data-user-id="${user.id}">View Profile</button>
</div>
`;
console.log(html);
Much cleaner than string concatenation!
Example 2: API Requests
const userId = 123;
const baseUrl = 'https://api.example.com';
const url = `${baseUrl}/users/${userId}`;
console.log(url); // https://api.example.com/users/123
// With query parameters
const page = 2;
const limit = 10;
const queryUrl = `${baseUrl}/posts?page=${page}&limit=${limit}`;
Example 3: Error Messages
function divide(a, b) {
if (b === 0) {
throw new Error(`Cannot divide ${a} by zero`);
}
return a / b;
}
try {
divide(10, 0);
} catch (e) {
console.error(e.message); // Cannot divide 10 by zero
}
Example 4: SQL Queries (With Caution!)
const userId = 123;
const query = `SELECT * FROM users WHERE id = ${userId}`;
// β οΈ WARNING: This is vulnerable to SQL injection!
// Only safe for demonstration. Use parameterized queries in production.
Tagged Template Literals
Tagged templates let you process template literals with a function:
Basic Syntax
function highlight(strings, ...values) {
let result = '';
for (let i = 0; i < strings.length; i++) {
result += strings[i];
if (i < values.length) {
result += `β${values[i]}β`;
}
}
return result;
}
const name = "Alice";
const age = 25;
console.log(highlight`Name: ${name}, Age: ${age}`);
// Output: Name: βAliceβ, Age: β25β
Real Example: HTML Escaping
function html(strings, ...values) {
let result = '';
for (let i = 0; i < strings.length; i++) {
result += strings[i];
if (i < values.length) {
// Escape HTML special characters
const escaped = String(values[i])
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
result += escaped;
}
}
return result;
}
const userInput = '<script>alert("XSS")</script>';
const safe = html`<p>${userInput}</p>`;
console.log(safe); // <p><script>alert("XSS")</script></p>
Template Literals vs String Concatenation
Readability Comparison
// Concatenation (hard to read)
const message = "User " + user.name + " logged in at " +
new Date().toLocaleString() +
". Email: " + user.email;
// Template literal (much cleaner)
const message = `User ${user.name} logged in at ${new Date().toLocaleString()}. Email: ${user.email}`;
Performance
Template literals are faster than concatenation:
// Slow
let str = '';
for (let i = 0; i < 1000; i++) {
str += 'Item ' + i + ', ';
}
// Fast
const items = [];
for (let i = 0; i < 1000; i++) {
items.push(`Item ${i}`);
}
const str = items.join(', ');
// Or use template literal directly
const str2 = Array.from({length: 1000}, (_, i) => `Item ${i}`).join(', ');
Common Mistakes
β Mistake 1: Using Quotes Instead of Backticks
// WRONG
const greeting = "Hello, ${name}!"; // Won't interpolate!
console.log(greeting); // Hello, ${name}!
// CORRECT
const greeting = `Hello, ${name}!`; // Interpolates correctly
console.log(greeting); // Hello, Alice!
Remember: Use backticks (`) not quotes (' or ")
β Mistake 2: Not Escaping Special Characters
// WRONG - can have XSS vulnerabilities
const userInput = '<img src=x onerror="alert(1)">';
const html = `<p>${userInput}</p>`;
// CORRECT - use a library or proper escaping
import DOMPurify from 'dompurify';
const safe = DOMPurify.sanitize(`<p>${userInput}</p>`);
β Mistake 3: Complex Logic in Templates
// WRONG - too complex inside ${}
const result = `Result: ${arr.filter(x => x > 5).map(x => x * 2).reduce((a, b) => a + b, 0)}`;
// CORRECT - compute first, then template
const filtered = arr.filter(x => x > 5);
const doubled = filtered.map(x => x * 2);
const sum = doubled.reduce((a, b) => a + b, 0);
const result = `Result: ${sum}`;
Keep expressions simple inside ${}.
Browser Compatibility
Template literals are supported in:
- β All modern browsers (Chrome, Firefox, Safari, Edge)
- β Node.js (all recent versions)
- β Internet Explorer (any version)
If you need IE support, use a transpiler like Babel.
Best Practices
- Use template literals by default - More readable than concatenation
- Keep expressions simple - Move complex logic outside the template
- Escape user input - Always sanitize when inserting user data into HTML
- Use tagged templates carefully - Document what they do
- Prefer native methods - Use
.toLocaleString(),.padStart(), etc. instead of manual formatting - Format multiline strings - Use template literals for readable multiline strings
Examples in Popular Libraries
React with JSX (uses template-like syntax)
const App = () => {
const user = { name: 'Alice' };
return <h1>Hello, {user.name}!</h1>;
};
Styled Components
import styled from 'styled-components';
const Button = styled.button`
background: ${props => props.primary ? 'blue' : 'gray'};
color: white;
padding: ${props => props.size}px;
`;
GraphQL Queries
import { gql } from 'apollo-client';
const query = gql`
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
`;
Conclusion
Template literals are essential modern JavaScript:
- Cleaner syntax - No more string concatenation
- Readable - Multiline strings preserve formatting
- Powerful - Embed expressions and function calls
- Tagged templates - Advanced processing when needed
Use them everywhere. Once you start, you'll never go back to string concatenation.