Introduction
Requires a basic understanding of html, vue and tailwindcss.
It turns out that the default styling of the <details>
tag is prety ugly because of this,
most people just decide not to use it and fallback to divs
, h1
and ul
with some kind
of state management to support it.
It basically looks like this closed without the styling
And this when open
But with Tailwind and a bit of vue magic, we can achieve this
With no time to waste, let's get started.
Project Structure
To incorporate this with your vue website, you will need not to start a new npm
or yarn
or pnpm
vue app.
I personally used pnpm and vite for this project
pnpx create-vite .
pnpm install .
pnpm install tailwindcss autoprefixer postcss
tailwindcss init -p
pnpm run dev
All you need is your component file and tailwindcss enabled. It should look nothing less than this.
For best results, Add a vector library you like. But in this project, I will be using font-awesome.
I included the vector library by adding this script tag to the index.html
<script defer src="https://use.fontawesome.com/releases/v5.15.4/js/all.js" integrity="sha384-rOA1PnstxnOBLzCLMcre8ybwbTmemjzdNlILg8O7z1lUkLXozs4DHonlDtnE7fpc" crossorigin="anonymous"></script>
Don't forget to import the index.css file into your main.js file.
App.vue
Nothing much here. Just basic imports and data declaration.
<template>
<custom-details :title="heading" :data="tools" />
</template>
<script>
import CustomDetails from './components/custom-details.vue';
export default {
components: { CustomDetails },
data(){
return {
heading: "Tools for building a website",
tools: ["HTML", "CSS", "JavaScript", "VueJS", "ReactJS", "Vite"]
}
}
}
</script>
custom-details component
In out custom details component, lets write down some templates.
<template>
<details>
<summary>
<div>
<h2> {{title}} </h2>
<i class="fa fa-caret-down"></i>
</div>
</summary>
<ul>
<li v-for="(detail, index) in detailData" :key="index">
{{ detail }}
</li>
</ul>
</details>
</template>
In this template, no style is being added to it to keep it readable and easy to modify. All styles will be written in the
styles
tag.
Time to add some functionality
In our script tag,
<script>
export default {
props: ["title", "data"],
data(){
return {
detailData: this.data instanceof Array ? [...this.data] : []
}
}
}
</script>
Explanation
First, we have to define the data our custom-details will need which are a title and some array of strings data by using the props
attribute.
...
props: ["title", "data"]
...
Then, we have to ensure that the data
being provided by the parent component is an Array, so we check if the data is and array, if not, we return an empty array using the tenery operator.
this.data instanceof Array ? [...this.data] : []
Time to add some styles (the fun part :)
To make our code clean, we are using the styles
tag.
Default styles
To our style.css which is usually automatically imported by your build tool into the main.js
file, add the following to the top.
@tailwind base;
@tailwind utilities;
The @tailwind components;
was not added since we do not require any more styles.
Component styles
To our styles tag should initially look like this.
<style scoped>
</style>
First of, let us add some style to the details
tag.
details{
@apply border border-gray-300 rounded-md my-2 mx-auto;
}
Next, remove default markers of the summary
tag and style it
...
summary::-webkit-details-marker,
summary::marker{
display: none;
}
details > summary{
@apply flex py-2 cursor-pointer;
}
details[open] > summary{
@apply border-b border-gray-300;
}
...
Then, styling the inner summary div
...
summary > div {
@apply flex items-center gap-x-6 w-full text-gray-700 px-4;
}
...
Finally, we then style the list
...
details > ul {
@apply flex flex-col divide-y-2 divide-gray-200;
}
ul > li {
@apply flex px-4 hover:bg-gray-50 cursor-pointer text-sm text-gray-500 font-bold py-1.5
}
Your final CSS should look like this.
<style scoped>
details{
@apply border border-gray-300 rounded-md my-2 mx-auto;
}
details > summary{
@apply flex py-2 cursor-pointer;
}
details[open] > summary{
@apply border-b border-gray-300;
}
summary::-webkit-details-marker,
summary::marker{
display: none;
}
summary > div {
@apply flex items-center gap-x-6 w-full text-gray-700 px-4;
}
details > ul {
@apply flex flex-col divide-y-2 divide-gray-200;
}
ul > li {
@apply flex px-4 hover:bg-gray-50 cursor-pointer text-sm text-gray-500 font-bold py-1.5
}
</style>
If properly followed, the results should give you this.
Thanks for reading and have a good day.
Top comments (2)
Thanks!
It works as expected right?