Every public facing website, no matter what industry or occupation, has a Frequently Asked Questions section somewhere on the site. If you're working on a website, you'll need one too.
Let's walk through the process of creating an FAQ box using Web Components and discuss the knowledge required to do so. The contents below will outline the individual pieces, then the code at the end will put it all together. If you'd like to skip the explanation and get directly to the code, feel free to do so by scrolling to the bottom. The video shown here shows the code being written in real time and the final product in action.
The video shown here is a part of our Web Dev with Music Playlist, where we code examples, such as this, in real-time and view the results as we go.
Demo the Live Example
The live example can be viewed in action on this page.
FAQ Box Requirements
For this example, we'll create a simple & straightforward faq box, which will:
- present all questions at once.
- hide all answers by default.
- let users toggle answer visibility by clicking on questions.
- let users view more than one answer at once.
Writing the FAQ Component
There are a few different approaches we could take to write our component, including:
- Create the entire popup box and its elements with JavaScript.
- Create an HTML structure with the questions and answers, then use JavaScript to reference the elements and add JavaScript logic.
- Use Web Components to declare FAQ Box elements in the HTML document as if they were native elements.
For this example, we will use the web components option. In the sections below, we'll introduce some of the basic concepts of web components. For a detailed introduction, check out our Introduction to Web Components dev page.
Creating the HTML Structure
We want to be able to structure our HTML so it is evident which components correspond to questions, answers, and containers; you should be able to understand exactly what is happening at a glance. For this example, our structure will look something like:
In the HTML above, we can clearly see what each element is for and how the overall structure is defined:
- faq-box: container for a set of questions and answers
- faq-box-qa: container for a single question and answer pair
- faq-box-question: a single question
- faq-box-answer: an answer tied to its sibling question node
Before we can use this type of HTML, we will need to register those components in some way.
Registering Custom Elements
We will be "registering" the four elements shown above in two ways:
- Implicit: use the custom tag names in the HTML markup and add CSS properties to those tag names.
- Explicit with Custom Elements Registry: create a JavaScript class which extends HTMLElement and register it, along with its selector, with JavaScript's custom elements registry.
For this implementation, we will only explicitly register the faq-box-qa
element, as that will be the only one which requires JavaScript functionality. The others will be handled implicitly.
To register our faq-box-qa
with the registry, we will need to invoke JavaScript's custom elements functionality after our class has been declared:
The customElements object is a global JavaScript object which can be invoked anywhere without any need for importing or unboxing.
Creating the Component Class
In order to provide the show and hide functionality, we will need to implement some JavaScript for our FaqBoxQA class, corresponding to the faq-box-qa
selector, to toggle the visibility of the answer when the question is clicked. To make our component class, we will create a JavaScript class which extends HTMLElement:
The component above will be instantiated once per individual faq-box-qa
component on the DOM; thus, it will not interfere with any other components. In other words, each instance will handle its own state and elements only.
Styling the Custom Elements
The components can be styled in the same manner as normal HTML elements:
The only difference between styling these elements and elements such as div is: custom elements and tags must have their "display" attribute specificed manually. Setting display: block
will ensure that styles are applied in the same way they would be to div
elements.
Full Code Implementation
Below, we'll showcase the full code contents which brings everything together: