vue logo

Easily build unique, accessible, and lightweight Vue components

tl;dr: Checkout Vuetensils if you care about building accessible and lightweight Vue projects, but prefer to use your own custom styles.

Over the last few years, I have built several web sites and apps with Vue.js. Some of them were built on top of 3rd party libraries such as Vuetify or Bootstrap-vue, and others were totally custom.

Both approaches offer great benefits, but I take pride in the work that I do, and many projects have that one thing that you walk away with thinking, “I could have done that better.”

Generally speaking, when I use a 3rd party library, I feel guilty for one or more of the following:

  • It bloats my bundle size because I have to import more code than I actually use.
  • The project ends up looking like any other project that uses the same library.
  • I’ve had to customize the project by overwriting styles with some hacky CSS due to specificity issues, and therefore more CSS goes unused.
  • The 3rd party library didn’t actually do a great job of writing semantic or accessible components.

On the other hand when I design/code everything myself, my gripes are:

  • It would have taken half the time if I just used a library.
  • Whenever a new feature requirement comes up that we haven’t already accounted for, I’m going to have to build that by hand as well.
  • Getting semantics and accessibility right is hard, and doing it from scratch for each project is a lot of work.
  • I don’t know how many times I’ve implemented the same code for a modal

Lately, I’ve been approaching more projects by building them from scratch. With each project, I have a bit more useful code that I can just copy over to the next and just replace the styles. Which lead me to the thought:

What if there was a Vue library that handled all the semantics and accessibility, but let me use my own custom styles?

Why accessibility matters

There are already a plethora of blog posts out there on why accessibility matters, so I won’t go into too much detail, but here are the main points I care about.

  • Avoid lawsuits: For 2019, the average of ADA related lawsuit has reached 8 per day (source).
  • Better business: There’s actually a surprising number of users with some sort of impairment. If they can’t use your site, you lose clicks, emails, sales, conversions, etc.
  • Better code: Since focusing on accessibility, I have seen a big improvement in my code. Semantics plays a large role for accessibility, and as a result, I end up with better SEO.
  • Feels great: Not to mention, I just feel like a better person when I am writing code that is more inclusive. It feels like a disservice to forego accessibility.

All that is good, but there’s one catch: accessibility is not easy.

You have to educate yourself on the many ARIA roles, account for keyboard navigation, make sure the focus states make sense, and so much more. In fact, it’s also very easy for very talented developers to try implementing accessibility, just to make it even worse than if they did nothing at all.

What’s the solution? Reach for a library that already has these things taken care of (see below).

Introducing Vuetensils

Vuetensils is a Vue component library composed of “naked” (mostly unstyled) components that focus on accessibility, semantics, and completely custom design.

It includes components for my UI needs such as alerts, modals, dropdowns, inputs, and more, as well as a few functional components like an image lazy loader, and a component for awaiting promises, and a wrapper for intersection observer.

The components follow best practices from the WAI-ARIA and WCAG standards as much as possible, and offer support for features like keyboard navigation, focus trapping, and managing aria roles and attributes.

What are “naked” components?

Vuetensils components are almost entirely unstyled. This is on purpose. They are designed to be starting points providing the functional requirements while expecting you to write the CSS (ie. dress them up).

As a result, the components are completely unique to your project, there are no messy CSS overrides, no unused styles that bloat the project, and they handle the accessibility part so you don’t have to.

Usage:

To get started, you can install Vuetensils into your project with:

npm install vuetensils

Import only the components you need for your app.

You can do so globally:

// main.js
import Vue from "vue"
import { VAlert } from "vuetensils"

Vue.component("VAlert", VAlert)

Or registered locally:

<script>
  // SomeComponent.vue
  import { VAlert } from "vuetensils"

  export default {
    components: {
      VAlert,
    },
    // ...
  }
</script>

Use the components in your template:

<template>
  <div class=" some-component ">
    <VAlert>Hey, I'm an alert!</VAlert>
  </div>
</template>

Bring your own styles:

/* Some CSS file */
.vts-alert {
  border: 1px solid currentColor;
  border-radius: 4px;
  padding: 0 10px;
  color: #900;
  background: #fdd;
}

The result is an alert element that has nice ARIA attributes and nice functionality with your own custom styles:

Vutensils custom alert example

Closing remarks

Starting with “naked” components actually opens this library up to a lot of interesting options.

  • Build accessible websites or apps (basic use).
  • Themes designs for use with Vuetensils.
  • Extend components to create your own custom, accessible UI library.

Vuetensils came as the result of scratching my own itch. I want my projects to have totally custom styles, and also be accessible, but I don’t want to build everything from scratch, and I don’t want a bunch of unused code lying around.

As a result, it’s probably not for everyone.

You may not have the same needs, and that is totally ok. There is nothing wrong with using a 3rd party library like those I mentioned above. In fact, those are excellent projects. They just serve a different need.

I hope this sort of thing picks up, and people give more focus on making the web accessible for all. Ideally, this makes it easier to get started doing so, and maybe the concept of “bring your own styles” picks up.