Template literals.
Backticks, ${}, multi-line.
Template literals — the ones with backticks — are the modern way to build strings in JavaScript. They interpolate variables with ${'{}'}, they preserve line breaks, and they can be "tagged" with a function for advanced processing. If you're still concatenating strings with +, template literals are simpler and less error-prone. This page covers the syntax, the differences from quotes, and the tagged-template pattern that powers styled-components and GraphQL.
Short answer: Use backticks for any string with a variable or a newline. `Hello, ${'${name}'}` instead of 'Hello, ' + name. Multi-line strings just work — no \n escapes needed. Expression interpolation accepts any JS: ${'${a + b}'}, ${'${user.active ? "yes" : "no"}'}. Tagged templates (fn`...`) let a function process the template — rare in app code, common in libraries. Use backticks by default for anything non-trivial; use quotes for plain literal strings.
✅ The three differences from quotes
Why backticks are the default in modern JavaScript.
Interpolation
`Hi, ${'${name}'}` — embed any expression. Quotes need + concatenation.
Multi-line
Backticks preserve line breaks. Quotes need \n or concatenation.
Tagged templates
fn`...` — a function processes the template. Only backticks support this.
No escaping
Backticks don't need escaped quotes. You can use " and ' freely inside.
✅ Before and after
The same strings, quotes vs backticks.
const name = 'Alice';
const age = 30;
const role = 'admin';
// ❌ Concatenation with quotes
const a = 'Hello, ' + name + '!';
const b = 'Name: ' + name + ', Age: ' + age;
const c = role === 'admin' ? 'Admin access' : 'Limited access';
const d = "Status: " + (age >= 18 ? 'adult' : 'minor');
// ✅ Template literals
const a2 = `Hello, ${name}!`;
const b2 = `Name: ${name}, Age: ${age}`;
const c2 = `${role === 'admin' ? 'Admin access' : 'Limited access'}`;
const d2 = `Status: ${age >= 18 ? 'adult' : 'minor'}`;
console.log(a); console.log(a2);
console.log(b); console.log(b2);
console.log(c); console.log(c2);
console.log(d); console.log(d2);
// Output is identical — only the syntax differs.
Output:
Hello, Alice!
Hello, Alice!
Name: Alice, Age: 30
Name: Alice, Age: 30
Admin access
Admin access
Status: adult
Status: adult
Why template literals are better:
1. No quote escaping
❌ "It's " + user + "'s turn"
✅ `It's ${user}'s turn`
2. No + operators between parts
❌ 'Hello, ' + name + ', you are ' + age
✅ `Hello, ${name}, you are ${age}`
3. Ternaries fit naturally
❌ 'Status: ' + (active ? 'on' : 'off')
✅ `Status: ${active ? 'on' : 'off'}`
4. Fewer bugs
Concatenation with numbers is easy to get wrong:
❌ 'Total: ' + a + b // 'Total: 12' (a=1, b=2, not 3)
✅ `Total: ${a + b}` // 'Total: 3'
5. Expressions, not just variables
✅ `${a + b}`, `${user?.name}`, `${items.length}`
Any expression works.
The one thing to watch:
`${a}${b}` is string concatenation.
`${a + b}` is arithmetic, then string.
Different results. Be intentional.
✅ Multi-line strings
Backticks preserve newlines.
// ❌ Without backticks — escape newlines
const email1 =
'Dear ' + name + ',\n\n' +
'Thank you for your order.\n' +
'Your total is $' + total + '.\n\n' +
'Best regards,\n' +
'The Team';
// ✅ With backticks — natural line breaks
const email2 = `Dear ${name},
Thank you for your order.
Your total is $${total}.
Best regards,
The Team`;
console.log(email2);
// Dear Alice,
//
// Thank you for your order.
// Your total is $99.
//
// Best regards,
// The Team
The output is the same.
The difference is the source code.
Without backticks:
→ Every line needs explicit \n
→ Every variable needs + concatenation
→ Every quote needs escaping
→ The code doesn't look like the output
With backticks:
→ Lines break naturally
→ Variables interpolate with ${}
→ No escaping needed
→ The code looks like the output
For anything more than one line, backticks win.
⚠️ Indentation matters:
const msg = `Hello
World`;
→ "Hello\nWorld" (leading spaces preserved)
→ if you indent the second line for readability,
those spaces are in the string
⚠️ To strip indentation, use a tagged template
or process the string after:
const clean = msg.replace(/^ +/gm, '');
⚠️ This is why template literals for HTML or SQL
need care:
const html = `
${content}
`;
→ leading whitespace is part of the string
→ for HTML, whitespace usually doesn't matter
→ for SQL or config files, it often does
✅ Tagged templates
A function that processes the template.
// Tagged template — the function receives
// the static parts and the dynamic values
function tag(strings, ...values) {
console.log(strings);
console.log(values);
return strings.reduce((result, str, i) => {
return result + str + (values[i] ?? '');
}, '');
}
const name = 'Alice';
const age = 30;
tag`Hello, ${name}. You are ${age}.`;
// strings: ['Hello, ', '. You are ', '.']
// values: ['Alice', 30]
// returns: 'Hello, Alice. You are 30.'
// The function can transform values
function upper(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + String(values[i] ?? '').toUpperCase();
}, '');
}
console.log(upper`Hi ${name}, you are ${age}`);
// "Hi ALICE, you are 30"
Tagged template anatomy:
tag`Hello, ${name}.`
1. `tag` is a function.
2. The template is passed to it.
3. The function receives:
strings: the static parts as an array
values: the interpolated expressions
4. The function returns whatever it wants
— usually a string, but it could be
an object, an array, a React element,
a parsed AST.
Real-world uses:
✅ styled-components
styled.div`color: red; padding: ${padding}`
→ returns a React component
✅ GraphQL (gql tag)
gql`query { user { name } }`
→ returns a query AST
✅ lit-html
html`${content}
`
→ returns a TemplateResult
✅ SQL query builders (sql-template-strings)
sql`SELECT * FROM users WHERE id = ${id}`
→ returns a parameterized query object
Why use tagged templates:
→ The function gets the raw template parts
AND the values separately, so it can
escape, validate, or transform each.
→ This is how SQL injection is prevented:
the values never get concatenated into
the query string — they're passed as
parameters.
→ It's how libraries like styled-components
parse CSS safely.
For app code, you almost never write a tag yourself.
You use ones from libraries. But knowing what
they are makes the library's behavior less magical.
Don't use ${'{a}'}${'{b}'} when you mean ${'{a + b}'}. This is the most common template-literal bug — and it's subtle. `${'${a}${b}'}` concatenates the string forms of a and b. If a = 1 and b = 2, the result is "12", not "3". For strings, the difference doesn't matter. For numbers, it does. When you want arithmetic, put both operands inside one ${'{}'}: ${'${a + b}'}. When you want concatenation, keep them separate. Be explicit about which you mean — the fix is one character, but the bug is silent.
⚠️ Common mistakes
The template-literal mistakes that cost real time.
'${name}' is literal text. Fix: `${name}`.
${'${a}'}${'{b}'} when you meant ${'{a + b}'}Concatenation instead of arithmetic. Fix: put the expression in one ${'{}'}.
Leading spaces become part of the string. Fix: process with .replace() or a tag.
$ without {'{}'}`Price: $${price}` — $ is literal, ${'${price}'} interpolates. Fix: escape $ if needed, or use ${'${"$"}'}.
Three levels deep. Fix: extract into variables.
`hello` works but quotes are simpler. Fix: quotes for plain literals, backticks for interpolation.
${'${}'} evaluates the expression`${'${user.name}'}` — if user is undefined, throws. Fix: ${'${user?.name ?? ""}'}.
Raw interpolation in HTML is an XSS risk. Fix: use a library like lit-html that escapes.
❓ Frequently asked
What are template literals in JavaScript?
Template literals are a string syntax that uses backticks instead of quotes. They support interpolation with ${expression}, multi-line strings without escape characters, and tagged templates. Example: const greeting = `Hello, ${name}!`. Added in ES2015, they're the modern default for any string with variables or newlines.
What is the difference between quotes and backticks?
Three differences. (1) Interpolation: backticks support ${expression}, quotes don't. (2) Multi-line: backticks preserve line breaks, quotes require \n or concatenation. (3) Tagged templates: only backticks can be tagged with a function. For simple strings, there's no difference. For anything with variables or newlines, backticks are cleaner.
How do I use ${} in a template literal?
Put an expression inside ${} inside backticks: `Hello, ${name}`. The expression can be any JavaScript — a variable, a function call, an arithmetic operation, a ternary. `Sum: ${a + b}`, `Status: ${user.active ? 'online' : 'offline'}`. The braces are required — ${} always, not $.
What are tagged templates?
A tagged template is a template literal prefixed with a function name: html`
${content}
`. The function receives the static parts of the template as an array and the interpolated values as additional arguments. It can process them however it wants. This is how styled-components, GraphQL's gql, and lit-html work.Can I nest template literals?
Yes, but be careful with readability. `outer ${`inner ${value}`}` works — the inner template is evaluated first. This is useful for conditional rendering: `${user ? `Hello, ${user.name}` : 'Hello, guest'}`. But three levels of nesting is unreadable. Fix: extract the nested part into a variable.
Do template literals affect performance?
Not meaningfully. Template literals are parsed once and evaluate to a string, just like concatenation. In micro-benchmarks, template literals can be slightly faster. But the difference is in nanoseconds. Choose based on readability. `Hello, ${name}` is clearer than 'Hello, ' + name.
🔗 Continue learning
Next in this series: