As web development capabilities and tools evolve, web development framework styling has mirrored that evolution. Moving away from inline styles to CSS-in-JS solutions has made the development experience more consistent.
With the styled-components library, developers can utilize CSS within JavaScript or JavaScript frameworks instead of creating traditional separate CSS files when styling. It has seen huge success in React, and now it is available for Vue projects.
In this post, we’ll see why utilizing styled-components is advantageous when styling in Vue.
Styled-components gives you the freedom to make your own custom styled components in Vue. You can style the HTML tags and give them the name of your choice to make your code more readable.
With styled-components, everything is done with the help of props. You can dynamically change the style of your components without using classes. It gives you the power to use the ternary operators inside the string literals of the styled components.
Styled-components makes the styling and design of your components concurrent and similar throughout the entire application without much effort. The theming capabilities provide a central place to define the basic design elements such as color, size, and spacing, and can be easily integrated into all of the components in the app.
Seeing tremendous growth, the styled-components community provides help for any issue and has a popular library for developers.
Now that we’ve seen the benefits of the styled-components, it’s time to install the library in our Vue project and look at how we can use its different features.
Before installing the library, have a Vue project up and running on your local machine. With a project set up, install the library with the following command:
npm i vue-styled-components
If you used Vue CLI to set up the project, the folder structure will look something like this:
With all the styles removed from our Vue app, HelloWorld.vue
looks like the following:
// HelloWorld.vue <template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script>
Let’s run the project to see the following output in the browser:
As we can see, there is a simple h1
header tag with no styles applied. We will style this h1
with styled-components, and we must create a new folder in the src
directory to store them. In that folder, create a Header.js
file. The project structure will look as follows:
Then, add the following lines of code in Header.js
:
import styled from "vue-styled-components"; export const StyledHeader = styled.h1` font-size: 1.5em; text-align: center; color: red; background-color: grey; `;
Finally, we can register StyledHeader
in HelloWorld.vue
and use it instead of h1
:
<template> <div class="hello"> <StyledHeader>{{ msg }}</StyledHeader> </div> </template> <script> import {StyledHeader} from "../styled-components/Header" export default { name: 'HelloWorld', components:{ StyledHeader }, props: { msg: String } } </script>
Now, let’s start the server and see how the plain and boring header tag changes:
As we can see, the required styles have been applied without using any CSS!
Styled components, like any other components, have the ability to accept props. For example, we can create an input field and pass a prop to it. Here, we’ll create a new component named Input.js
in the components
folder and add the following code to it:
import styled from "vue-styled-components"; export const StyledInput = styled.input` font-size: 1.25em; padding: 0.5em; margin: 0.5em; color: blueviolet; border: none; background-color: lavender; border-radius: 3px; &:hover { box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.1); } `;
The next step is to use it in HelloWorld.vue
:
<template> <div class="hello"> <StyledHeader>{{ msg }}</StyledHeader> <StyledInput/> </div> </template> <script> import {StyledInput} from "../styled-components/Input" import {StyledHeader} from "../styled-components/Header" export default { name: 'HelloWorld', components:{ StyledInput,StyledHeader }, props: { msg: String } } </script>
Saving the changes will reflect them in the browser, confirming our input is rendered:
But this looks weird without a proper input. Let’s pass it as a prop to StyledInput
along with the type:
<template> <div class="hello"> <StyledHeader>{{ msg }}</StyledHeader> <StyledInput placeholder="Password" type="text"/> </div> </template> ...
Running this gives us the following output:
This is one of the strongest features of styled-components. It allows developers to set dynamic styles without using tons of classes.
Because styled-components can take props and apply style based on props, let’s give custom props to StyledHeader
.
Let’s modify our Header.js
file as follows:
import styled from "vue-styled-components"; const hdrProps = { primary: Boolean }; export const StyledHeader = styled("h1", hdrProps)` font-size: 1.5em; text-align: start; color: ${(props) => (props.primary ? "white" : "red")}; background-color: ${(props) => (props.primary ? "green" : "yellow")}; `;
Here, we have defined the props for our StyledHeader
. The styled function takes the HTML element with the props as an argument, after which we can specify the behavior of our CSS based on the value of that prop.
Let’s run the project without giving any prop to our previously created header, and see the following output in the browser:
This is working exactly as we have specified. Now, let’s provide a primary
prop to our StyledHeader
, and check whether the styles are applied correctly:
<template> <div class="hello"> <StyledHeader primary>{{ msg }}</StyledHeader> <StyledInput placeholder="Password" type="text"/> </div> </template> <script> import {StyledInput} from "../styled-components/Input" import {StyledHeader} from "../styled-components/Header" export default { name: 'HelloWorld', components:{ StyledInput,StyledHeader }, props: { msg: String } } </script>
As we can see, the StyledHeader
is accepting primary
as a prop. After saving the changes, our project renders the following output:
With this, we have successfully changed the style based on our props, giving us the basic concept behind the approach. Styles with props can be changed with button events, form submissions, and more. We can now leverage the full power of dynamic styling with styled-components.
Styled-components also provides the ability to make components follow the same style. This creates a consistent style for applications and removes a lot of repetitious code.
By simply adding the following line of code in Header.js
, we can apply the following to use the same styles for h2
:
export const StyledHeader2 = StyledHeader.withComponent("h2");
After using this component in the HelloWorld.vue
file, we will get the following output:
Sometimes, components must change based on a specific scenario but retain the same styles. For this instance, styled-components can use a prop to change the component being rendered.
If we apply the as
prop to change the StyledHeader
, we can change it to a button:
<template> <div class="hello"> <StyledHeader as=button>{{ msg }}</StyledHeader> <StyledInput placeholder="Password" type="text"/> </div> </template>
The browser then gives us the following output:
Inspecting the role
, we can clearly see that it is a button:
If changes must be made to the component styling without rewriting it, we can override or add new styles to it.
By creating a new component named NewHeader.js
, we can override the color
attribute from the previously created Header.js
.
Then, let’s add the following code in the NewHeader.js
:
import { StyledHeader } from "./Header"; export const NewHeader = StyledHeader.extend` color: purple; border-color: purple; `;
Let us now render and use it in our HelloWorld.vue
file:
<template> <div class="hello"> <StyledHeader >{{ msg }}</StyledHeader> <NewHeader >{{ msg }}</NewHeader> <StyledInput placeholder="Password" type="text"/> </div> </template> <script> import {StyledInput} from "../styled-components/Input" import {NewHeader} from "../styled-components/NewHeader" import {StyledHeader} from "../styled-components/Header" export default { name: 'HelloWorld', components:{ StyledInput,StyledHeader,NewHeader }, props: { msg: String } } </script>
After saving the changes, we get the following output:
As we can see, we have overridden the color of Header.js
and used its styling in our newly created NewHeader.js
.
Styled-components is a powerful library that solves most of the pain points we would find using plain CSS. While the learning curve can be steep initially, the benefits are worth it.
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
One Reply to "Theming Vue.js with styled-components"
I don’t understand why I would need styled components in vue. It already has excellent support for css and sass. And if you need dynamic css you can always use a method or computed that returns an object and bind it to the style