I talked about what custom HTML elements were in my last post. Today, I’m going to walk through the process of getting a new Vue CLI project off the ground so that you can build your own. I’ll be using the <my-blink> tag example again, but will be focusing on the step by step1 instructions for creating the environment in which to build and deploy the tags you will be creating.

Getting the Vue CLI2

The first thing you’ll want to set up is the Vue CLI. This is an amazing tool that will install and configure nearly everything you need to Vue development, and will help you build our components as custom HTML elements.

You’re going to do quite a bit in our command line, so open up your favorite command line and type in the following on Windows:

npm install -g @vue/cli

Or this on Mac or Linux:

sudo npm install -g @vue/cli

This will install a new program on your computer called, funnily enough, vue. This vue application is a great starting point for any new Vue project, whether that’s a SPA3, a mobile application, or custom HTML elements.

Using Vue CLI to create a new project

To create a new Vue project, you can use the new Vue CLI. If you run the following command, it will create and download a whole new Vue project into a folder called my-custom-elements:

vue create --bare --default my-custom-elements

Using --bare will prevent the CLI from creating a needless HelloWorld component and --default will tell the CLI to set up a simple project. There are a lot of extras that you can add to the project using the CLI, but you don’t need any of that at the moment.

Once this is done, change into the new directory and open it in your favorite editor.4

The Vue project structure

Looking at the project structure, there’s a lot that was created for us here! There are a number of Node.js files here that set up some tools for our project and all the libraries we will need to build and compile our tags. You can read up about what package.json is here and get a bit of knowledge about node_modules here.

You should see two other folders in there are well, src and public. I’ll leave an explanation of public for another time, but what you want to focus on is the src folder.

The src folder is where all of your component code will go for the project. This is the location of your source code in the project structure.

In fact, you’re going to create a new folder here. Just right click on the src folder, select New Folder and call the folder components. This is where you will create your components that will become custom elements.

Creating the custom element

Now that you have your project set up, we’re going to create a new component. Right click on the new components folder and select New File. Name this file Blink.vue and set its content to the following:

<template>
<span ref="blinkyText"><slot></slot></span>
</template>

<script>
export default {
  name: "blink",
  mounted() {
    setInterval(() => {
      this.$refs.blinkyText.classList.toggle("onoff");
    }, 500);
  }
};
</script>

<style>
.onoff {
  visibility: hidden;
}
</style>

This creates a Single File Component in Vue for us, which makes creating custom elements very simple and with an existing web developer syntax. This component should be pretty easy to read as is. <slot></slot> will be replaced with whatever is inside our custom tag, so the view is just wrapping a span around that. The CSS, at the bottom, creates a new style class that will hide an element (setting its visibility to hidden). The JavaScript logic will then, when the component is “mounted” or loaded onto the page, take that span that you created and toggle (or add/remove) the class from the span, thereby showing and hiding the content from the slot.

Now you can create this as a custom HTML element.

Building the component into a custom element

By default, this project is not set up to actually create custom elements. It has all the tools needed to do so, but we need to set up a new script to get it to happen.

Open the package.json file. There is a lot already set up in this file, but you want to go to the section that is labeled "scripts" and add a new one. Currently, it will look like this:

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

You’re going to change the build script to something new. Change it to look line this:

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --target wc --name my-blink 'src/components/Blink.vue'",
    "lint": "vue-cli-service lint"
  },

That build script is now changed to create Web Components (--target wc), give the custom element a name (--name my-blink)5, and just build the one component ('src/components/Blink.vue').

Once you add that to package.json and save the file, you can now run the build process to create your custom element. Run the following command on the command line in your project folder:

npm run build

This will build your custom element and put a JavaScript file in the dist folder of your project (which should have just been created). It will also create a demo.html file for you. From that file, you’ll see this:

<meta charset="utf-8">
<title>my-blink demo</title>
<script src="https://unpkg.com/vue"></script>
<script src="./my-blink.js"></script>


<my-blink></my-blink>

This isn’t a full HTML file, so isn’t too useful, but you can see what you will need to do to use this custom element. First, you’ll need to include the Vue framework on the page:

<script src="https://unpkg.com/vue"></script>

Then include your custom element JavaScript file that got built into the dist folder:

<script src="./my-blink.js"></script>

And then use your new tag!

<my-blink></my-blink>

Or, more accurately if you were using this in real life:

<my-blink><h1>Look!!! Blinking text!!!</h1></my-blink>

That’s all there is to it. There are a lot of steps here and we haven’t even talked about more multiple custom elements or getting them to communicate together (which I plan on getting to), but you can see how a simple Vue component can be created into a custom element.


  1. Oooooooh, Baby! [return]
  2. I’m going to assume here that you have Node and NPM installed already. If you don’t, do that first. [return]
  3. Single Page Application [return]
  4. Might I suggest Visual Studio Code? [return]
  5. By the standard, all custom elements built by a developer must contain a -. I’ll get into good naming conventions in another post. [return]