Using a fabulous open source library like Styled-Components often comes with the nice effect of appreciating what you can do with it more and more and more. If you are like me, at some point you get curious about what happens behind the (library-)scenes. I recently checked the Styled-Components Github repository to know better what's going on when using the library. As you can imagine the library does A LOT of cool things, so in the first attempt I limited my investigations to the library's practical entry point.
Remember, creating a styled component with the Styled-Components library is as simple as a that...
const Button = styled.a`
font-size: 14px;
`;
...or as that
const BorderedButton = styled(Button)`
border: 2px solid white;
`;
Please pay special attention to the differences of how the styled
function is used in the examples above.
- we call
a
as a method of thestyled
object passing it css as an argument - we call the
styled
function passing it the previously created styled component as an argument and add css as a next argument
So how does the library provide that exposed possibilities for us? Let's take a look.
A CSS-in-JS holy grail named styled
Theoretically and taking into account Styled-Component's package.json
information, the technical runtime entry point to the library is the src/index.js file. But that said, the practical entry point enabling us to do all the cool things is the styled.js file being part of the /src/constructors
directory. Next see what this file looks like (status 01/2019, branch master):
In a nutshell this file does the following:
- some internal imports (lines 2-4)
- one
const styled
declaration referencing a function (line 8) - one forEach loop (lines 11-13)
- finally the export of our holy grail
styled
🎉 (line 15)
The styled function and its function object methods
Confused of that headline? Remember, in Javascript functions are objects! As a result developers can make use of this by i.e. adding methods to that function object. Styled-Components and the real entry point returned by styled.js
makes heavy use of this. Line 8 shows a const styled
declaration referencing a function, but more on that later. For now just keep in mind that a function referenced by the styled
const was created. Now take a special look at the lines 11 to 13.
We see a forEach loop iterating an array of defined domElements. Each iteration attaches a method with the name of the iterated dom element to the styled
function object. And voilá! There it is, the first hard-working component factory attaching dom element methods to the styled
function object like a boss. The body of each attached method is nothing else than the result of a styled
function call returning a properly built component constructor for each dom node. Having reached this point at runtime we can already call such an attached method like this in our own codebase:
const Button = styled.a`
...this will be the method argument in the form of css to the styled.a call...
`;
const Container = styled.div`
...this will be the method argument in the form of css to the styled.div call...
`;
So far we know (some kind of) what's going on when we use styled.a
or styled.div
in our codebases using Styled-Components. That said we've gone "half the way" to demystify what styled.js exports for us. Remember when I wrote "Line 8 shows a const styled
declaration referencing a function, but more on that later."? It is that function we need to talk about more right now to demystify the other half. Here we go.
The styled function: how it's constructed and distributed
Constructed and distributed? Yes!
As you can see in line 8, styled
itself is declared as a function. It is either called directly by us developers using the distributed default export of the styled
function or by calling the function object method which requires internal construction as described above. So in concrete this means for us:
This...
const Container = styled('div')` ...css... `;
and this
const Container = styled.div` ...css... `
returnes exactly the same. But remember: we can conveniently use the second option in our codebase, as Styled-Components takes care of building the proper component constructor executing first option internally to add the function object method (here: .div
).
The styled
function takes a tag
as a parameter and returns the result of calling the function constructWithOptions
(line 8) which receives two arguments.
-
a
StyledComponent
function - Have you noticed I never mentionedReact
in this post so far? Well, here we go. Let's not forget Styled-Components is part of theReact
ecosystem. As a result thisStyledComponent
argument is used to actually create a React component giving access to React EventHandlers and all the other cool things React does for us. -
the
tag
we've passed to thestyled
function - The argument is of typeTarget
which is either a dom node string or an already styled component. Check this line to find the origin of how theTarget
type is defined using Flow. Thetag
argument is simply passed through toconstructWithOptions
without any modifications.
Receiving these two arguments, the constructWithOptions()
function execution returns another function that let's us create a styled component already considering the tag
we want to use in our codebase. Using the returned function in the most basic form, the only thing to we need to pass it is pure css within a tagged template literal argument. Check out this post of Max Stoiber in case you want to go into detail about how this part of Javascript works.
So to close the cycle of styled.js
... Now as we know what the styled function returns and how it is distributed or used for internal construction, we also know better what the different method bodies of the styled
function object methods do. styled.a
works as the styled(domElement)
execution in line 12 of styled.js distributes a "tag-predefined" styled component constructor to it! 🎉
Thx for reading!
As you can see, styled
provides a lot of things. On the one hand a function, on the other hand it acts as an object providing predefined methods for each dom node to build styled components. In my opinion this approach the library provides us to style our components is pure gold.
I hope this post helps you to better understand what styled.js does and how it exposes stuff we can use. Please note all information is based on the Styled-Component's master branch by Jan 2019. In case there'll be changes I don't notice, feel free to contact me in order to update this post.
This post was originally posted here.
Top comments (7)
styled
really does have such a clever API. Good post and clear explanation!it definitely has.
thx Mehdi!
Looks nice and easy understand.
Is there a tutorial from zero?
How about CSS position?
thx!
I highly recommend its "Getting Started" section (styled-components.com/docs/basics#...) to start with Styled Components.
Don't know exactly what you mean about CSS position. Can you clarify?
I've read your doc. I want to try on my mac but don't know how.
CSS position means set the position of component.
Nice article!
Some constructive feedback: to make this post future proof, you can link to a GitHub file in a specific commit, for example github.com/styled-components/style...
This makes that all your links to GitHub files will work even if the master branch files are changed.
Cheers!
great hint, thx!
updated the github links considering this.