In the ever-evolving landscape of web development, writing clean and maintainable code is paramount. This post will guide you through a method that combines the power of Tailwind CSS with Vue's Composition API and the Single File Component (SFC) syntax. This approach not only enhances code readability but also simplifies the process of styling Vue components.
Project setup
Before diving into the coding process, make sure to set up your project with Tailwind CSS and Vue. We can use npm
or yarn
to install the necessary packages, follow these steps to set your project:
Tailwind setup with Vue using Vite
Leveraging Composition API and SFC Syntax
To take advantage of Vue's Composition API and SFC syntax, create a component using the <script setup>
syntax. This modern approach simplifies the component structure and promotes cleaner code organization.
<!-- src/components/TailwindClasses.vue -->
<template>
<div class="bg-blue-500 text-white text-xl font-bold flex items-center justify-center px-4 py-8">
{{ message }}
</div>
</template>
<script setup>
const message = ref('Tailwind is messy')
</script>
Although, the div has multiple Tailwind CSS classes directly applied, which can become messy and hard to manage as the component grows. Consider using a more modular approach with utility classes stored in variables.
Applying Tailwind Classes Dynamically
Lets suppose we have to set a different color
by props. It will even more messy trying to handle variants on template.
But we can dynamically apply Tailwind CSS classes to our component by utilizing the array variables within the template. This approach enhances maintainability and allows for easy modifications.
<!-- src/components/MyComponent.vue -->
<template>
<div :class="computedClasses">
{{ message }}
</div>
</template>
<script setup>
// SECTION - Setup and component logic
import { ref, computed, defineProps } from "vue";
const message = ref("Tailwind can be clean!");
/***
* (optional) We will use props to pass in the color now,
* actually this can use any other data/method to set
* variant classes
*/
const props = defineProps({
color: {
type: String,
default: "blue",
},
});
// SECTION - Style classes
// Combine classes using computed
const computedClasses = computed(() => {
// Defining colors we want
const colors = {
blue: ["bg-blue-500", "text-white"],
red: ["bg-red-500", "text-white"],
yellow: ["bg-yellow-500", "text-black"],
};
return [
colors[props.color],
"text-xl font-bold",
"px-4 py-8",
"flex items-center justify-center",
];
});
</script>
Separating component logic and style classes into distinct sections with comments makes it easier for developers to understand and maintain the code, promoting a clean and modular structure.
The use of clear annotations, such as "SECTION" is a great practice to enhance code organization and readability.
You can use a extension like Comment Anchors or Better Comments to highlight sections on VSCode.
Conclusion
By combining Tailwind CSS, Vue's Composition API, and the SFC syntax, you can write clean, modular, and maintainable code. Integrating Tailwind CSS with Vue using the Composition API and SFC syntax is a powerful combination. It provides a clear and concise way to handle styles while maintaining a high level of flexibility and readability. This approach aligns well with the principles of clean code, making it a recommended choice for Vue developers.
You can check this example on CodeSandbox
Top comments (5)
I've used TailwindCSS with Vue for a while, and I agree with you that putting every class in a row in the template isn't maintainable.
However, I don't feel like handling the classes like that in the component logic is the way to go either. It's a bit more readable, but feels like unnecessary overhead.
So I've stopped using TailwindCSS for now. I do like the idea of TailwindCSS though.
What I am using now is regular old CSS using BEM methodology.
Oh, I didn't aware about BEM. Surely I will study about.
When I come with this solution I had most of component styling from data and need to prototype fast, but I agree with you, plain CSS is gold and Vue already provided
scoped
avoiding style leaks.I think a meaningful step in my scenario should be converting Tailwind classes into CSS after some level of component maturity. I found this repo Tailwind to CSS sometime ago, I didn't refactored my components this way yet, but it seems promising. At same time I would apply BEM conventions as you suggested.
Thank you for the insights
You have to define multiple computed variables when you writing a complicated Component.You have to read the Css Code in where the logic should be.
I agree with you.
But I forgot to describe the scenario of this implementation. I had some design prototypes to make using Tailwind to be quick. Although these projects were not yet fully concrete, not even a Figma sketch. It was like, “Hey, take this page, change some components, change the style of others, and show it to me for feedback.”
I know, we could choose to use
@apply
Tailwind - Extracting classes with @apply or create a theme attailwind.config
, create a bunch of css classes and use functions to add or remove them as needed, but at this stage of implementation this would increase complexity and premature abstractions in my point of view. (I'll update the post!)Not all classes should be in the script, only those that need to interact with the data. In my case, the most complex component has only 5 computed classes (but can be divided into 3 components with 1 computed class each).
Structuring components with reusability in mind gave me the maintainability to decide when my component library is mature enough to revamp the styling code with plain CSS, or not.
Thanks for the insights!
Clean code is always good !