Let’s code a dribble design with Vue.js & Tailwindcss (Working demo) — Part 1 of 2
Article #5 of my “1 article a day till lockdown ends”
Lets pick a small design from dribble and code it with Vue.js& tailwindcss, you will find out how Vue’s two way binding works and how tailwind lets you make beautiful apps while being completely flexible and without writing any css manually.
Let’s pick a design which is easy to implement so that it wont make the article too long and is also intuitive, fun and looks beautiful. I found this design which calculates BMI by letting you select your gender, height, weight & age.
I will make use of Nuxt.js which is a framework for Vue & tailwindcss.
Why Vue & Nuxt?
Vue.js is a progressive framework which lets you makes web apps fast and quickly, it has two way binding and makes use of single file components which will let you make custom html tags like<gender /> or <height-slider />
etc, it let’s you divide your html markup into smaller blocks and make your code cleaner, readable and more maintainable. Nuxt is a framework for a vue. Why do we need a framework for a framework, as Nuxt handles at lot of real world use cases for websites, out the box which are practical, where you will end up writing lesser boilerplate code if you had chosen vue. You can still choose vue if you want to, I just like Nuxt better because of its routing and folder structure.
Why Tailwindcss?
Tailwindcss is a CSS framework with only low level css classes, it provides all the feature of a full fledged CSS framework and yet still provide all the flexibility and freedom CSS provides you, it’s not opinionated and won’t force you to write CSS in a restricted way, like a traditional framework would (Bootstrap), in simpler terms there’s a class form almost every single css rule (which you use most of the time). Technically this would mean it’s a very huge framework, which it is, but purgeCss comes to the rescue, it will remove all excess classes and only keeps whats used in your HTML (Nuxt.js has purgeCSS built in, so you don’t have to do it manually)
Step 1: Let’s create a Nuxt project and select TailwindCSS as our UI Framework.
Once done, open the project in your favourite code editor, I prefer VS Code. you can start the project in development mode by running the command npm run dev
where you will be greeted with a template. Remove all the code from pages/index.vue
and remove the css from layouts/default.vue
. The layouts/default.vue
will act as the entry point of your project, here all the route content will be shown dynamically & your routes will be defined in the pages folder, each .vue file inside the pages folder means a webpage, and the route will be the file name. You can find more about the nuxt routing here and a free udemy course entire dedicated to nuxt.js.
We will be having two page in the app, one is the calculator which will be shown as soon as the site is opened and one would be the result page, we already have a index.vue
file for it in pages folder, add another called result.vue
this will add a new route to our project like example.com/result.
That’s how easy it is to create routes in nuxt.js.The project structure below.
Start the project by running npm run dev
and open localhost:3000
in your browser and see “The Home Page” text which is our index.vue
rendered, try opening localhost:3000/result
you will see “The Result Page”, the result.vue
page rendered.
The default.vue
will be rendering these routes inside inside <nuxt />
component. If you want any component to be shown in both routes, you can just add them in default.vue
it will be automatically shown, instead of repeating the code in both pages, it’s great for navbar, navigation drawers, back top buttons etc.
Step 2: Let’s code the calculator/index/home page.
We will begin by dividing the code into different components
So we have 4 different components here.The Navigation Bar which will be shown in boh the index page and the result page, so we can just include it once in layout/default.vue
. The other three components will be shown in the index/calculator page. Here’s the folder structure I always follow to keep the code clean and readable.
Step 3: Code the components
- The entire app has a dark them, so let’s apply the bg-gray-900 class to our top most div, which is is
layouts/default.vue
. - Make the Navigation bar. It has one div with a icon and some text in the center, with a thich box shadow, we will use css flex to align the content and the shadow classes of tailwindcss. The below HTML code generates the navbar for us
So the above code generate this navbar with zero custom css written. Basically we have a parent div with with two children, a div with a svg icon and a paragrarh tag with some text. I applied flex & items-center to it to divide them on the same line and vertically aligning them in center with items-center.
I will be adding the navbar component in our layouts/default.vue
file so that its available in both routes.
- The Gender component has two divs, we will make use of css grid, it’s not necessary to make use of css grid, this can be easily achievable with other ways too, just wanted explain tailwindcss features for you.
Here’s how CSS Grid works in tailwindcss, more on it here.
The above code generates this layout, its simple and is responsive with tailwinds responsive helpers, the grid-cols-2 is specifying that we our layout will have two columns and there’s a gap of 4 units between then, no more margin hacks with columns.
Let’s pick the gender icons from flaticon and add them inside these cards. This is how it will end up looking. I have added a little opacity to the non selected card with class opacity-75
to hightlight the other one.
Looks good, now let’s design the Height component. I have used a html range slider with some custom css because tailwindcss does not allow customising at this level, I made a small image to act as the slider button, because it had a border radius with opacity which we cannot do with css, yet.
We now have end up with this design in our code, matches the design, though not pixel to pixel, I am still happy with the result. I have added a v-model directive to capture the range slider value whenever a user slides it and used string interpolation to display the value on top of it {{height}}
, that’s a good example of how two way binding works.
Similar to the gender component with two equal divs, lets make a component to get the user’s age and weight.
So far we have achievedmakign most of the calculator part, all that’s left to add in the markup is a button at the bottom.
We will add a fixed button at the bottom which will calculate, and display the result in the second page, where we will make use of events emitted from our components and getting captured in the parent.
This is how the index.vue
page will look at the end. I have also added a button at the bottom, which finishes coding the first page. It’s not pixel perfect but we have made good progress. Here is the code commited so far (I might update it soon once the project is completed) and a live demo .
This article has become long enough hence I will break it in two parts and publish the part 2 later today.
Hope you enjoyed. You can follow me on twitter to get updated on part 2 as I will keep posting about my series over there.
Let me know if you need any help or have suggestions on this.
PS, A very happy Ramadan to everyone. Peace!