banner
isolcat

isolcat

I am not afraid of storms, for I am learning how to sail my ship
github

Wrap element plus components and beautify with UnoCSS.

Preface#

In daily development, in order to avoid reinventing the wheel and wasting development time, we often use third-party component libraries such as element plus and vant-ui. However, in order to improve the overall aesthetics of the project, we usually do not directly use third-party component libraries as they are. We will modify them to better fit the overall UI style of the project. At this time, we can extract the third-party component library and package it into a common component library. This operation of encapsulating the third-party component library is called secondary encapsulation.

Benefits of Secondary Encapsulation#

  • More concise code
  • Easier project maintenance
  • Stronger component reusability

Introduction to Unocss#

Since we want to encapsulate the original third-party component library, it is inevitable to modify its styles. Modifying CSS is often the most headache-inducing part (at least for me 🥹). At this time, I saw antfu's article on reimagining atomic CSS, and I strongly recommend reading this article before continuing. It will give you a deeper understanding of atomic CSS. In summary, according to the words of the master:

Atomic CSS is an architectural approach to CSS that tends to use small and single-purpose classes, and names them based on visual effects.

Unocss is the high-performance and highly flexible instant atomic CSS engine created by antfu. As for why it is an engine rather than a CSS framework, it is because Unocss does not provide any core utility classes, and all functions can be provided through presets and inline configurations.

Advantages of Unocss#

  • Flexibility (property mode, tens of thousands of pure CSS icons, no need to worry about style conflicts)
  • Strong style reusability
  • No need to think about class names! (This is a great help for people who have difficulty naming things) 🤣

Since both secondary encapsulation and Unocss can greatly improve development efficiency and make everyone happy, let's try to combine these two things. Here, we will take the loading component of element plus as an example to demonstrate a simple secondary encapsulation, and then use Unocss to beautify it.

Core of Secondary Encapsulation#

Here, we use the component encapsulation method of vue3, which is slightly different from the encapsulation method of vue2. For the encapsulation method of vue2, please refer to Red Dust's article.

$attrs#

An object containing all the passed-through attributes of the component.

This is the official definition of $attrs in Vue, which refers to attributes and event handling functions that are passed in by the parent component and are not declared as props or custom events of the child component. For example, when we nest a <button> inside a <div> tag in a component, if we want to apply pass-through attributes such as class or v-on listeners directly to the inner <button>, we can use v-bind="$attrs" to achieve this.

Inheriting v-on Listeners#

In vue3, the $listeners event listener in version 2 has been directly removed, and its functionality has been merged into $attrs. For example, when writing a click event, in the component encapsulation, the click of the atomic component will still trigger the onclick event of the parent component.

<!-- Child component -->
<button>click me</button>
<!-- Parent component -->
<MyButton @click="onClick" />

Component Encapsulation#

Project Initialization#

Enter the following command in the command line:

pnpm create vite element-plus-unocss --template vue

Use vite+pnpm to quickly initialize the project.

cd element-plus-unocss
pnpm i
pnpm run dev

After successful execution, the project initialization is complete.

Importing Component Library#

The component library we want to encapsulate is element plus, so we need to import it:

pnpm install element-plus

Here, we still follow the recommended automatic import by the official website. I won't go into details here. Just click on the link to configure it. The following is the focus.

Secondary Encapsulation#

Here, we choose the loading component for demonstration. Add the child component loading.vue to the components folder, and directly copy the example from the official link (you can make some modifications if necessary):

<template>
  <el-button
    v-loading.fullscreen.lock="fullscreenLoading"
    type="primary"
    @click="openFullScreen1"
  >
    Click me
  </el-button>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { ElLoading } from 'element-plus'

const fullscreenLoading = ref(false)
const openFullScreen1 = () => {
  fullscreenLoading.value = true
  setTimeout(() => {
    fullscreenLoading.value = false
  }, 2000)
}
</script>

Now, create the Myloading.vue component, import it, and modify its code:

<template>
  <Loading
    v-bind="$attrs"
    element-loading-text="Loading~"
    element-loading-background="rgba(122, 122, 122, 0.8)"
  />
</template>

<script setup>
import Loading from "./loading.vue";
</script>
<style>
.el-loading-mask .el-loading-spinner .el-loading-text {
  font-size: 20px;
}
</style>

The result is as follows:

image.png

This means that the secondary encapsulation of our component is successful.

Beautifying Components with UnoCSS#

At this point, we find that the click me button seems lifeless and does not make people want to click it at all. So, how can we make this button look more appealing and make people want to click it? This is where our heavyweight character UnoCSS comes in.

Installing and Importing UnoCss#

pnpm i -D unocss

Configure vite.config.js:

import Unocss from 'unocss/vite'

export default {
  plugins: [
    Unocss({ /* options */ }),
  ],
}

And import UnoCSS into main.js: import 'uno.css'

Configuring Presets#

Configuring presets is an important advantage of UnoCSS. With just a few simple presets, you can build your own custom framework in minutes. Attributify is one of the characteristics of Windi CSS, which is also retained in UnoCSS. Here, we install preset-attributify and unocss/preset-uno:

pnpm i -D @unocss/preset-attributify
pnpm i -D @unocss/preset-uno

Modified vite.config.js:

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Unocss from '@unocss/vite'
import presetUno from '@unocss/preset-uno'
import presetAttributify from '@unocss/preset-attributify'

import vue from '@vitejs/plugin-vue'
export default defineConfig({
    plugins: [vue(), AutoImport({
            resolvers: [ElementPlusResolver()],
        }),
        Components({
            resolvers: [ElementPlusResolver()],
        }),
        Unocss({
            presets: [presetUno(), presetAttributify()]
        })
    ]
})

Now we have a default preset + attribute mode custom framework. After writing a long string of CSS classes, they will be grouped according to the attribute mode, making the code more tidy and greatly improving readability:

<button 
  bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
  text="sm white"
  font="mono light"
  p="y-2 x-4"
  border="2 rounded blue-200"
>
  Button
</button>

Modifying Component Styles#

In order to make the button look more appealing, we can try adding a jumping animation to the click me text. At this time, we open the UnoCSS playground and find that the official demo already has a bouncing style. We can directly copy it and modify our child component:

<div  class="
      text-5xl
      fw300
      animate-bounce-alt
      animate-count-infinite
      animate-duration-1s"
    >
      click me
</div>

At this time, we feel that the default font color of the button seems to be too dark. We can further modify it in the parent component:

<Loading
    element-loading-text="Loading~"
    v-bind="$attrs"
    element-loading-background="rgba(122, 122, 122, 0.8)"
    class="text-lg 
           fw300 
           m2 
           op70"
  />

If we want to know what the cv actually is, we can download a UnoCSS plugin, search for it directly in vscode, and install it. Then, it will display the source code of this class when placed on it, which is convenient for subsequent development.

Alright, let's take a look at the appearance of the button after beautification:

GIF 2022-10-22 23-10-45.gif

Constantly jumping, doesn't it make people want to click it more? 😂

Conclusion#

As a newcomer to atomic CSS, UnoCSS is refreshing. It draws on the advantages of its predecessor taiwind CSS and incorporates the characteristics of its own windiCSS, making it surprisingly easy to use. Although it is still in the testing phase, I highly recommend everyone to give it a try. It will definitely give you a feeling of "What? You can do this too!" You can even use UnoCSS to build your own component library. Here is a link to my own component library project, which is an attempt with UnoCSS: https://github.com/isolcat/CatIsol-UI

Component library preview address: https://cat-isol-ui.vercel.app 😽

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.