• 5 min

Getting Started With Storybook Without a JavaScript Framework

Getting Started With Storybook Without a JavaScript Framework
Table of Content

We all want to use well-documented UI components in our frontend. With Storybook, you can do that reasonably quickly with React, Angular, Vue, or any other framework.

But since the documentation lacks clear information about how to set up Storybook without any JavaScript framework, I’m going to write it all down for you because it is possible to use plain HTML and CSS.

If you want to learn more about why you should use Storybook, check out Why You Should Always Use Storybook When Developing User Interfaces by Tyler Hawkins.


Add Storybook by running the following command in the terminal:

npx sb init

This command will add all the dependencies for Storybook and create initial files so that you can get started right away.

After the installation, you will see this question: “Do you want to manually choose a Storybook project type to install?” Type “yes.” Then “Please choose a project type from the list” will appear. For this, type “HTML.”

Now the CLI will set everything up to use Storybook with plain HTML.

Run npm run storybook when the installation is finished.

Global Setup

When you check your directory, you will see a folder named .storybook. In this folder, there are two files: main.js and preview.js.

In the main.js file, you can configure what directory will be checked for *.stories.js files (other file extensions are possible). Storybook also has a plugin system called add-ons that you can add here as well.

In the preview.js file, you can add everything that needs to be loaded while previewing your UI components.

For example, add your global CSS file or icon font to have it available in all the components.

Example Story File for Plain HTML

In the stories folder, you will find the files Button.stories.js. It looks like this:

import { createButton } from './Button'export default {    title: 'Example/Button',    argTypes: {        label: { control: 'text' },        primary: { control: 'boolean' },        backgroundColor: { control: 'color' },        size: {            control: { type: 'select', options: ['small', 'medium', 'large'] }        },        onClick: { action: 'onClick' }    }}const Template = ({ label, ...args }) => {    // You can either use a function to create DOM elements or use a plain html string!    // return `<div>${label}</div>`;    return createButton({ label, ...args })}export const Primary = Template.bind({})Primary.args = {    primary: true,    label: 'Button'}export const Secondary = Template.bind({})Secondary.args = {    label: 'Button'}export const Large = Template.bind({})Large.args = {    size: 'large',    label: 'Button'}export const Small = Template.bind({})Small.args = {    size: 'small',    label: 'Button'}

This is an excellent example of what a story file looks like. The code in Button.js will create a <button> element.

import './button.css';export const createButton = ({  primary = false,  size = 'medium',  backgroundColor,  label,  onClick,}) => {  const btn = document.createElement('button');  btn.type = 'button';  btn.innerText = label;  btn.addEventListener('click', onClick);  const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';  btn.className = ['storybook-button', `storybook-button--${size}`, mode].join(' ');  btn.style.backgroundColor = backgroundColor;  return btn;};

Even though it looks good and clear, the way createButton is creating a <button> tag doesn't let us generate a clear code example to copy and paste. So we're going to do it a bit differently.

Plain HTML Story With Code Example

To make this work, we need a Storybook add-on. Run the code below to install it:

npm i @storybook/addon-storysource

After the installation, add it to the .storybook/main.js file like below:

module.exports = {  "stories": [    "../stories/**/*.stories.mdx",    "../stories/**/*.stories.@(js|jsx|ts|tsx)"  ],  "addons": [    "@storybook/addon-links",    "@storybook/addon-essentials",    "@storybook/addon-storysource"  ]}

Create a folder named helpers in the stories folder. In that folder, create a file named code-example.js. In this file, we will create a helper function that generates data for our code example.

function addCodeExample(component, templateConfig) {  if(!component || !templateConfig) return  component.parameters = {    docs: {      source: {        code: templateConfig({          label: component?.args?.label,          className: component?.args?.className        })      }    }  }  return component}export { addCodeExample }

In this function, we take the component and the templateConfig as parameters. These parameters are going to provide us with information from the components themselves.

For this example, I will minimize the length of the Button.stories.js by adding only one example of a button. So copy-paste the code below:

export default {  title: 'Example/Button',  argTypes: {    label: { control: 'text' },    className: { control: 'text' }  },};const Template = ({ label, className }) => {  return `<button class="${className}">${label}</button>`;};export const Primary = Template.bind({});Primary.args = {  label: 'Button',  className: 'button-primary',};

If you check the button component in Storybook, your code example will not be ready to copy-paste yet.

Screenshot Storybook with the Button element

By using the function to generate that example, you will see the difference:

import { addCodeExample } from './helpers/code-example'export default {  title: 'Example/Button',  argTypes: {    label: { control: 'text' },    className: { control: 'text' }  },};const Template = ({ label, className }) => {  return `<button class="${className}">${label}</button>`;};export const Primary = Template.bind({});Primary.args = {  label: 'Button',  className: 'button-primary',};addCodeExample(Primary, Template)

Here, you can see that I added Primary as the first parameter and Template to the next. This will generate the simple HTML code you can copy and paste.

Screenshot Storybook with the Button element and code example


Now that you know how to use Storybook with plain HTML and CSS, you can create your UI components much more effectively!

Storybook is a great tool to use in any web application. I’m super happy with it! If you want, check out their project on GitHub and show some support!

In what kind of application or architecture are you using or planning to use Storybook? Please let me know.


After reading this post, I hope you learned something new or are inspired to create something new! 🤗

If I left you with questions or something to say as a response, scroll down and type me a message. Please send me a DM on Twitter @DevByRayRay when you want to keep it private. My DM’s are always open 😁


I’m Ray, a Frontend Developer since 2009 living in the Netherlands. I write about Frontend Development, JavaScript, TypeScript, Angular, CSS, VueJS and a lot more related topics.

Want to reach me for comments or questions on my blog? Send a DM on Twitter @DevByRayRay