Tagged Template Literals - The Magic Behind Styled Components
Tags: react, javascript, webdev, tutorial
Published: 2021-08-01 08:11:48

### Intro & Background
If you have some experience with React, you probably came across [styled-components](https://styled-components.com/). In the last few years, the concept of css-in-js became more popular, and there are multiple libraries that are available for us to use. styled-components is one of them, but you can also find [Emotion](https://emotion.sh/docs/styled), [Radium](https://formidable.com/open-source/radium/), [JSS](https://cssinjs.org/), and more. In this post I'm **not going** to cover the pros and cons of traditional stylesheet files vs. styled-components, and instead - I'm going to focus on tagged template literals - the "magic" that let us use the `styled-components` syntax.

### styled-component basics - a quick reminder
Let's take the following simple syntax for example:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=styled-example.jsx
%}
{% codesandbox en9vg %}
The `StyledDiv` in the example above is actually a React component that returns a `div` block with the css of `color: red; font-weight: bold;`.
Well... kind of. Actually - it's a bit more complicated than that. The output of the above is a div with specific css class-names having the above css definitions inside:

{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=styled-example-output.html %}

<br />
Some of you are probably using this without giving it too much of a thought. If we take a closer look we can see the usage of the backtick (`` ` ``) right after the `styled.div`.
This syntax in Javascript is called **Tagged Template Literals**.

### Template Literals
Let's start with `Template Literals`, and then move on to the more interesting concept.
In javascript - template literals are strings that can contain expressions within them:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=template-literals-1.js %}

As you can see from the example above - expressions can be variables, but are not limited to them:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=template-literals-2.js %}

We can use either variable or function inside a template literal, and the value that will be used is basically the string representation of the expression:

{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=template-literals-3.js %}

Now that we understand the power of template literals - it's time to move on to tagged template literals - or just tagged templates.

### Tagged Templates - Whats the fuzz?
With tagged templates, we have the power to parse the template literal ourselves using our own "home-made" function.
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-1.js %}
Note that in the example above - the variable `strB` contains the string `String A` (and not `String B` as you might expect).

#### Let's break it down
1. The function `funcA` returns the string `String A`.
2. By using the function `funcA` as a tagged template - we completely ignored the string that was sent, and we just return something else.
3. We can use it with an empty string, and the output will be the same.

Check it out:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-2.js %}

### Advanced features
The function we use in a tagged template can return everything that we want - we are not limited to only return strings:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-3.js %}

Building tagged templates have an option to also accept variables that can be used:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-4.js %}

The first argument is a special object, which behave as an array and provides access to all the "native strings" in the original string that was passed to the tag-template function (`strings[0]`, `strings[1]`, `strings[2]`), alongside a `raw` property, which allows you to access the original raw strings.

The rest of the arguments are the expressions that we used inside the template literal.

### Time to build - let's start with something basic
Now that we know a bit more about template literals it's time to move on to some more complex examples.
We already know that template literals don't have to return strings, so how about creating a simple example of a tagged template that returns a react component with the relevant style?
We will start by creating a simple div example to just wrap our text with some styling on it:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-cmp-1.jsx %}

The tagged template is the following code:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-cmp-2.jsx %}
The full example is available here:
{% codesandbox oz3oo %}

> Check out the helper functions (the `cssObjFromStr`). we are going to focus on it in the next example.

### Using props in the component
The basic example gave us a nice intro, but what about the component's props? We use them all the time in React, and losing them is not an option. Moving to the next example, we will add the option to also use props as part of our component that we would like to style:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-props-1.jsx %}

We will use the `onClick` prop on the div element.
The full example is here:
{% codesandbox n6q3q %}

### Using props in the template
Props are not only relevant to the components, but also to the template itself. We want to use the props of the component inside the template itself - colors, elements behavior, and more.
To do this we will need to pass the props from the `<Div...>` to the `cssObjFromStr` method:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-props-2.jsx %}

But this is not enough.
Let's assume that we use the `<Div>` element with the property `textColor="blue"`:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-props-3.jsx %}

The issue we face here is that the `<div>` component (inside the `cmp`) will get the `textColor` property, which is not a valid property of a `div` element.
A specific solution can be to extract the `textColor` from the `props`, and pass the rest of the properties down to the `<div>` element:
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-props-4.jsx %}

Working example can be found here:
{% codesandbox eeeef %}

The styled-components solution is a bit more elegant (and much more generic) - all props that start with `$` are considered "private props" and will not pass down to the actual jsx component.
We will use the same concept, but in our example, we will use the _ (underscore) to create private props.
{% gist https://gist.github.com/dekelb/27bea33b73351f939037f8bec49528b5 file=tagged-templates-props-5.jsx %}

Full working example can be found here:
{% codesandbox vjffb %}

### Summary
The styled-component library contains much more than that, with the entire built-in HTML tags, wrapped-components, classes and inheritance (instead of inline-style), global themes and more, however styled-components is just an example of how to use the tagged template literals, which is eventually "just" a native javascript feature as of ECMAScript 2015 (also known as ES6).
<hr style="margin:10px auto;"/><sub>Cover photo by [Gerd Altmann @ pixabay](https://pixabay.com/users/geralt-9301/)</sub>