How to Structure CSS in Vue Like a Pro

Mía Salazar
7 min readJul 10, 2020

Vue is one of the frameworks available out there with more growth in the last few years. It’s easy to learn, easy to integrate with other libraries or frameworks and has an extended and very well detailed documentation.

The number of stars on GitHub. Image from codeinwp

However, when it comes to styling and HTML componentization, it might present some issues: How can I write CSS in a scalable, reusable and readable way? How can I optimize my CSS? Which is the best way to add styles to my elements?

In order to try to give an answer to this dilemma, we’ll address some ideas.

Atomic Design

An option to cope with this styling in CSS, is writing it in small and separated elements following Atomic Design methodology. For those who might not know, Atomic Design is a methodology for creating reusable CSS components. This system has five levels of building blocks, from the smallest and less complex components to complicated pages. These levels are:

  • Atoms: Atoms are the most basic components of Atomic Design. Some examples of atoms can be < label>, <input> and others HTML tags such as <h1>, <p> or <button>.
  • Molecules: Molecules are a combination of atoms that are closely related and that have full meaning when grouped. E.g., an <input>, its <label> and its submit button.
  • Organisms: Organisms are made out of molecules, and are more complex as they are used to build more elaborate sections. For example: Headers, footers…
  • Templates: A template is a group of organisms that forms the layout of a page. They provide context to atoms, molecules and organisms.
  • Pages: The highest level of atomic design components are pages, that show representative and real content.
Example of a molecule from atomicdesign.bradfrost

Advantages of atomic design

Disadvantages of atomic design

  • If documentation or communication between designers and developers is poor, this situation can lead to multiple designs for the same component.
  • In the same way, having different CSS styles for the same button combined with low specificity tend to end up in inheritance problems.
  • Besides, this method involves creating a folder for each type of atomic design element, CSS files and Vue components. That’s a lot of files.
  • Categorizing components in atoms, molecules and organisms can be tricky sometimes, and you waste your time debating between one building block or another.
Example of atomic structure and the amount of files

Vue’s Single File Component

For complex projects, using Single File Components might be the perfect option. They have .vue extension and you can write on the same file HTML, CSS (including CSS preprocessors languages such as SASS or LESS) and javascript.

<template>  <div class="footer__social-item-container">    <div v-for="(icon, index) in icons" :key="index" class="footer__social-item">      <a :href="`${}`" class="footer__link" aria-label="Sígueme en redes sociales"><i :class="'fa-' + icon.icon" class="fab footer__social-icon"></i></a>    </div>  </div></template><script>export default {  name: 'SocialLink',  data: () => ({    icons: [      { icon: 'github', link: '' },      { icon: 'codepen', link: '' },      { icon: 'linkedin', link: '' },      { icon: 'medium', link: '' },    ],  }),}</script><style scoped lang="scss">
.footer {
.social-icon { color: $white; font-size: 1.7rem; transition: 600ms; }}</style>

Example of a Single File Component

Advantages of Single File Component

  • As we already said, you have HTML, CSS, Javascript code on the same file, creating prettier templates and reducing the time you spend looking for files.
  • When you create a Vue component, you can reuse it. If you write your CSS in the component itself, it is also reused.
  • Vue reusability can help you erase code.
  • The page only loads the components required on each page, therefore, it only loads the needed CSS. Your web at full speed.
  • You can include the scoped attribute for your CSS in the Vue component. What does that mean? No inheritance or specificity problems. The CSS is only applied to that component.
<style scoped lang=”scss”>.footer {  &__social-icon {    color: $white;    font-size: 1.7rem;    transition: 600ms;   &:hover {      color: $pink;      font-size: 2rem;      transform: rotate(-30deg)    }  }}</style>

An example of the scope attribute.

Disadvantages of Single File Component

  • When you need to create global styles, you only have two options: repeat the CSS or create a global CSS stylesheet.
  • Vue components are hermetic. You can’t just simply change the styles of a component in just one page: Components only load their own CSS. Therefore, you can only add styles to the component container, if you want to add styles to elements inside of it, you are in big trouble.
  • If you still want to change the styles of a component in a concrete page, you would have to use dynamic classes for each case. This will result in more code inside your component and it can be messy.

However, here are a few ideas to improve your Single File Components.

There are three ways to access the styles inside a component from outside:

  • You can use the /deep/ selector in the CSS of your page to modify the elements inside of a component. However, this solution is not the best and it’s not highly recommended.
  • Creating smaller and more concrete components makes the interface lighter and lets you keep better track of your project.
  • To make your components more reusable, you can create a simple component and then place a slot inside of it. Slots allow you to compose components.
<style scoped>.header {  display: flex;  justify-content: space-between  font-size: 18px;  background-color: $gray;}/deep/ .nav {  background-color: $pink;}</style>

Using /deep/ selector

<template>  <article class=”card-component”>    <slot></slot>  </article></template>

An example of a simple component with a slot

<template>  <Card>    <h1 class=”card-title”>This is a card</h1>  </Card></template>

An example of a component composed in a page


Tailwind is the CSS framework that has the highest satisfaction rate, nevertheless, what makes it special? Tailwind doesn’t include any component classes and doesn’t come with automatically prestyles components. However, it provides utility classes, each one with a single purpose, that help us build our own components

Example of utility classes from Tailwind homepage

Advantages of Tailwind

  • It’s a very customizable and adaptable framework.
  • Tailwind provides many utility classes that can be used to solve Vue problem with general styles.
  • You can work faster because you don’t have to switch between HTML and CSS files or scroll up and down from <template> to <styles> to write CSS.
  • Users won’t need to download again the CSS file. When using Tailwind, you will add or remove classes, but you won’t change your CSS stylesheet.
  • It’s fast. Building a project with Tailwind avoid writing many CSS’s lines due to the fact that you directly use the utility classes.
  • Changing the styles on one page won’t affect others. You just add already written classes to elements, therefore, you won’t interfere with other pages’ styles.
  • You won’t have to think of class names.
  • It’s fully responsive!
<input class=”bg-white focus:outline-none focus:shadow-outline border border-gray-300 rounded-lg py-2 px-4 block w-full appearance-none leading-normal” type=”email” placeholder=””>

A component with many Tailwind utility classes from Tailwind homepage

Disadvantages of Tailwind

  • Tailwind can’t meet the accessibility or high-contrast mode needs
  • It’s pretty heavy, it comes with 36.4kb minified, being 14.3kb heavier than Bootstrap. You can customize it to make it lighter, but you will have to configure it.
  • When you start using it you will have to memorize a lot of class names and it’s not easy as they are not semantic.
  • Tailwind generates hundreds of classes that you will never use.
  • You will need another CSS file or to add some styles in your Single File Components. Tailwind doesn’t take into consideration weird pseudo-elements or pseudo-classes.
  • Besides, Tailwind is useful for general styles, but it can’t live up to all the designer’s needs.


Each project has different needs, for small projects Tailwind can be the best option as it’s fast and very powerful. On the other hand, if you need custom styles, atomic design can be the best solution. It will allow you to have a very tidy structure and you will have full control of your CSS.

However, for big projects, atomic design can be messy, and it can make you waste time searching files and thinking of which type of element is each component. Besides, Tailwind might be just not enough, especially if we have an already agreed design.

For that reason, when creating a big project, it would be more convenient to use Single File Components, as they allow to reuse code and are only loaded when need. However, you would also need a way to create global styles. If the team is a fan of CSS frameworks, Tailwind can save you a headache, but you will have to configure it in order not to worsen the size of your application. If your team prefers not to use a framework, a global stylesheet is a better solution.

To sum up, the best way to structure your CSS is to have a clear knowledge of the priorities and the future of the project, and then choose the best way to add beautiful styles to your components and pages.



Mía Salazar

I’m a Front-End developer that loves pizza, cookies, write and code