Categories
Web Components

Creating Web Components — Lifecycle Callbacks

As web apps get more complex, we need some way to divide the code into manageable chunks. To do this, we can use Web Components to create reusable UI blocks that we can use in multiple places.

In this article, we’ll look at the lifecycle hooks of Web Components and how we use them.

Lifecycle Hooks

Web Components have their own lifecycle. The following events happen in a Web Component’s lifecycle:

  • Element is inserted into the DOM
  • Updates when a UI event is being triggered
  • Element deleted from the DOM

Web Component has lifecycle hooks are callback functions that capture these lifecycle events and let us handle them accordingly.

They let us handle these events without creating our own system to do so. Most JavaScript frameworks provide the same functionality, but Web Components is a standard so we don’t need to load extra code to be able to use them.

The following lifecycle hooks are in a web component:

  • constructor()
  • connectedCallback()
  • disconnectedCallback()
  • attributeChangedCallback(name, oldValue, newValue)
  • adoptedCallback()

constructor()

The constructor() is called when the Web Component is created. It’s called when we create the shadow DOM and it’s used for setting up listeners and initialize a component’s state.

However, it’s not recommended that we run things like rendering and fetching resources here. The connectedCallback is better for these kinds of tasks.

Defining a constructor is optional for ES6 classes, but an empty one will be created when it’s undefined.

When creating the constructor, we’ve to call super() to call the class that the Web Component class extends.

We can have return statements in there and we can’t use document.write() or document.open() in there.

Also, we can’t gain attributes or children in the constructor method.

connectedCallback()

connectedCallback() method is called when an element is added to the DOM. We can be sure that the element is available to the DOM when this method is called.

This means that we can safely set attributes, fetch resources, run set up code or render templates.

disconnectedCallback()

This is called when the element is removed from the DOM. Therefore, it’s an ideal place to add cleanup logic and to free up resources. We can also use this callback to:

  • notify another part of an application that the element is removed from the DOM
  • free resources that won’t be garbage collected automatically like unsubscribing from DOM events, stop interval timers, or unregister all registered callbacks

This hook is never called when the user closes the tab and it can be trigger more than once during its lifetime.

attributeChangedCallback(attrName, oldVal, newVal)

We can pass attributes with values to a Web Component like any other attribute:

<custom-element
  foo="foo"
  bar="bar"
  baz="baz">
</custom-element>

In this callback, we can get the value of the attributes as they’re assigned in the code.

We can add a static get observedAttributes() hook to define what attribute values we observe. For example, we can write:

class CustomElement extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({
      mode: 'open'
    });
  }

  static get observedAttributes() {
    return ['foo', 'bar', 'baz'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    console.log(`${name}'s value has been changed from ${oldValue} to ${newValue}`);
  }
}

customElements.define('custom-element', CustomElement);

Then we should the following from the console.log :

foo's value has been changed from null to foo
bar's value has been changed from null to bar
baz's value has been changed from null to baz

given that we have the following HTML:

<custom-element foo="foo" bar="bar" baz="baz">
</custom-element>

We get this because we assigned the values to the foo, bar, and baz attributes in the HTML with the values of the same name.

adoptedCallback()

The adoptedCallback is called when we call document.adoptNode with the element passed in. It only occurs when we deal with iframes.

The adoptNode method is used to transfer a node from one document to another. An iframe has another document, so it’s possible to call this with iframe’s document object.

Example

We can use it to create an element with text that blinks as follows:

class BlinkElement extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    const shadow = this.attachShadow({
      mode: 'open'
    });
    this.span = document.createElement('span');
    this.span.textContent = this.getAttribute('text');
    const style = document.createElement('style');
    style.textContent = 'span { color: black }';
    this.intervalTimer = setInterval(() => {
      let styleText = this.style.textContent;
      if (style.textContent.includes('red')) {
        style.textContent = 'span { color: black }';
      } else {
        style.textContent = 'span { color: red }';
      }

}, 1000)
    shadow.appendChild(style);
    shadow.appendChild(this.span);
  }

  disconnectedCallback() {
    clearInterval(this.intervalTimer);
  }

  static get observedAttributes() {
    return ['text'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'text') {
      if (this.span) {
        this.span.textContent = newValue;
      }

    }
  }
}

customElements.define('blink-element', BlinkElement);

In the connectedCallback , we have all the code for initializing the element. It includes adding a span for the text that we passed into the text attribute as its value, and the styles for blinking the text. The style starts with the creation of the style element and then we added the setInterval code to blink the text by changing the color of the span from red to black and vice versa.

Then we attached the nodes to the shadow DOM which we created at the beginning.

We have the observedAttributes static method to set the attributes to watch for. This is used by the attributeChangedCallback to watch for the value of the text attribute and set it accordingly by getting the newValue .

To see the attributeChangedCallback in action, we can create the element dynamically and set its attribute as follows:

const blink2 = document.createElement('blink-element');
document.body.appendChild(blink2);
blink2.setAttribute('text', 'bar');
blink2.setAttribute('text', 'baz');

Then we should bar and baz if we log newValue in the attributeChangedCallback hook.

Finally, we have the disconnectedCallback which is run when the component is removed. For example, when we remove an element with removeChild as in the following code:

const blink2 = document.createElement('blink-element');
document.body.appendChild(blink2);
blink2.setAttribute('text', 'bar');
document.body.removeChild(blink2);

The lifecycle hooks allow us to handle various DOM events inside and outside the shadow DOM. Web Components have hooks for initializing, removing, and attribute changes. We can select which attributes to watch for changes.

There’re also hooks for adopting elements in another document.

Categories
Web Components

Introduction to Creating Web Components

As web apps get more complex, we need some way to divide the code into manageable chunks. To do this, we can use Web Components to create reusable components that we can use in multiple places.

Web Components are also isolated from other pieces of code so it’s harder to accidentally modify them from other pieces of code and create conflicting code.

In this article, we’ll look at the different parts of a Web Component and how to create basic ones.

Parts of a Web Component

A Web Component has 3 main parts. Together they encapsulate the functionality that can be reused whenever we like without fear of code conflicts.

  • custom element — a set of JavaScript APIs that allow us to define custom elements and their behavior, which can be used as we desired in the UI
  • shadow DOM — set of JavaScript APIs for attaching the encapsulated shadow DOM tree of the element. It’s rendered separately from the main document DOM. this keeps the element’s features private, so they can be scripted without the fear of conflicting with other parts of the document
  • HTML templates — the template or slot elements enable us to write markup templates that aren’t displayed on the rendered page. They can be reused multiple times as the basis of the custom elements structure.

Creating Web Components

To create Web Components, we do the following steps:

  1. Create a class or function to specify the web component functionality.
  2. Register our new custom element using the CustomElementRegistry.define() method, passing the element name to be defined and the class or function which the functionality is specified, and optionally what element it inherits from
  3. Attach a shadow DOM to the custom element using the Element.attachSHadow() method. Add child elements, event listeners, etc. to the shadow DOM using normal DOM methods
  4. Define HTML templates using the template and slot tags. We use regular DOM methods to clone the template and attach it to our shadow DOM.
  5. Use custom element wherever we like on our page like any other regular HTML element

Basic Examples

The CustomElementRegistry keeps a list of custom elements that are defined. This object lets us register new custom elements on a page and return information about what custom elements are registered etc.

To register a new custom element on a page, we use the CustomElementRegistry.define() method. It takes the following arguments:

  • a string representing the name of the element. A dashed is required to be used in them. They can’t be single words.
  • a class object that defines the behavior of the element
  • an optional argument containing an extends property which specifies the built-in element our element inherits from if any

We can define a custom element as follows:

class WordCount extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({
      mode: 'open'
    });
    const span = document.createElement('span');
    span.textContent = this.getAttribute('text').split(' ').length;
    const style = document.createElement('style');
    style.textContent = 'span { color: red }';
    shadow.appendChild(style);
    shadow.appendChild(span);
  }
}

customElements.define('word-count', WordCount);

In the code above, we attach a shadow DOM to our document by calling attachShadow . mode set to 'open' means that the shadow root is accessible from JavaScript outside the root. It can also be 'closed' which means the opposite.

Then we create a span element, where we set the text content to the text attribute’s length after we split the words in it wherever there’s a space.

Next, we created a style element and then set the content to color: red .

Finally, we attached them both to the shadow DOM root.

Notice that in our class, we extended the HTMLElement . We’ve to do this to define a custom element.

We can use our new element as follows:

<word-count text='Hello world.'></word-count>

There’re 2 types of custom elements. They are:

  • autonomous custom elements — which are standalone and don’t inherit from standard HTML elements. We can create them by referencing the name directly. For example, we can write <word-count>, or document.createElement("word-count").
  • customized built-in elements — these inherit from basic HTML elements. We can extend one of the built-in HTML elements to create these kinds of elements. We can use them by writing <p is="word-count">, or document.createElement("p", { is: "word-count" }).

The kind of custom element we created before are autonomous custom elements. We can create customized elements by writing:

class WordCount extends HTMLParagraphElement {
  constructor() {
    super();
    const shadow = this.attachShadow({
      mode: 'open'
    });
    const span = document.createElement('span');
    span.textContent = this.getAttribute('text').split(' ').length;
    const style = document.createElement('style');
    style.textContent = 'span { color: red }';
    shadow.appendChild(style);
    shadow.appendChild(span);
  }
}

customElements.define('word-count', WordCount, {
  extends: 'p'
});

Then put in our page by writing:

<p is='word-count' text='Hello world.'></p>

As we can see, autonomous custom elements and customized built-in elements aren’t that different. The only differences are that we extend HTMLParagraphElement instead of HTMLElement .

Then we used the is attribute to reference the custom element instead of using the element name in the customized built-in element.

Internal vs. External Styles

We can also reference external styles as follows instead of using internal styles as we had above. For example, we can write:

const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');
shadow.appendChild(linkElem);

This references styles from style.css . We created a link element just like we do in HTML and normal DOM manipulation.

Creating Web Components is simple. We just have to define a class or function for the functionality and then put it in the custom elements registry by using the customElements.define method.

We can extend existing elements like p elements or create ones from scratch. Also, we can add internal styles or reference external ones by creating a link element and referencing external files.

Categories
Bootstrap HTML

Bootstrap 5 — Tables

Bootstrap 5 is in alpha when this is written and it’s subject to change.

Bootstrap is a popular UI library for any JavaScript apps.

In this article, we’ll look at how to style tables with Bootstrap 5.

Tables

Bootstrap table styles are opt-in because of the widespread of use of tables in other UI components.

The table styles aren’t inherited in Bootstrap.

So nested tables can be styles independently of the parent.

For example, we can use the table class to style tables.

We can create a simple table by writing:

<table class="table">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td>james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

Variants

There are many styling variants for a table.

We can style them with the following classes:

<table class="table-primary">...</table>  
<table class="table-secondary">...</table>  
<table class="table-success">...</table>  
<table class="table-danger">...</table>  
<table class="table-warning">...</table>  
<table class="table-info">...</table>  
<table class="table-light">...</table>  
<table class="table-dark">...</table>

They also work on rows:

<tr class="table-primary">...</tr>  
<tr class="table-secondary">...</tr>  
<tr class="table-success">...</tr>  
<tr class="table-danger">...</tr>  
<tr class="table-warning">...</tr>  
<tr class="table-info">...</tr>  
<tr class="table-light">...</tr>  
<tr class="table-dark">...</tr>

And they also work on table cells:

<tr>  
  <td class="table-primary">...</td>  
  <td class="table-secondary">...</td>  
  <td class="table-success">...</td>  
  <td class="table-danger">...</td>  
  <td class="table-warning">...</td>  
  <td class="table-info">...</td>  
  <td class="table-light">...</td>  
  <td class="table-dark">...</td>  
</tr>

Accented Tables

We can add the .table-striped class to add zebra striping to table rows within the tbody .

For example, we can write:

<table class="table table-striped">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td>james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

Stripes also work with other table variants:

<table class="table table-dark table-striped">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td>james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

Hoverable Rows

To make rows hoverable, we can add the table-hover class:

<table class="table table-hover">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td>james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

Now we see the row that we hovered on highlighted.

The hover effect can be combined with stripes:

<table class="table table-striped table-hover">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td>james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

Active Tables

We can highlight a table row or cell with the table-active class:

<table class="table">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td class="table-active">james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

We add the table-active class on the cell so it’ll be highlighted.

This also works with other variants:

<table class="table table-success">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td class="table-active">james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

The styling works by setting the background with the --bs-table-bg property.

Then the gradient on the table is added with the background-image: linear-gradient(var( — bs-table-accent-bg), var( — bs-table-accent-bg)); CSS property.

When .table-striped , .table-hover or .table-active classes are added, the --bs-table-accent-bg is set to semitransparent color to change the color of the background.

--bs-table-accent-bg color with the highest contrast is generated for the highlights.

Text and border colors are generated the same way.

Table Borders

We can add borders with the table-bordered class:

<table class="table table-bordered">  
  <thead>  
    <tr>  
      <th scope="col">#</th>  
      <th scope="col">First</th>  
      <th scope="col">Last</th>  
      <th scope="col">Age</th>  
    </tr>  
  </thead>  
  <tbody>  
    <tr>  
      <th scope="row">1</th>  
      <td>james</td>  
      <td>smith</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">2</th>  
      <td>mary</td>  
      <td>jones</td>  
      <td>20</td>  
    </tr>  
    <tr>  
      <th scope="row">3</th>  
      <td colspan="2">Larry</td>  
      <td>50</td>  
    </tr>  
  </tbody>  
</table>

Conclusion

We can add tables with various effects like stripes, hover, and various colors.

Categories
Bootstrap HTML

Bootstrap 5 — Table Captions, Figures, and Form Fields

Bootstrap 5 is in alpha when this is written and it’s subject to change.

Bootstrap is a popular UI library for any JavaScript apps.

In this article, we’ll look at how to style tables, figures, and form fields with Bootstrap 5.

Captions

We can add a caption to the top of the table with the caption-top class:

<table class="table caption-top">
  <caption>List of people</caption>
  <thead class="table-dark">
    <tr>
      <th scope="col">#</th>
      <th scope="col">First</th>
      <th scope="col">Last</th>
      <th scope="col">Age</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1</th>
      <td>james</td>
      <td>smith</td>
      <td>20</td>
    </tr>
    <tr>
      <th scope="row">2</th>
      <td>mary</td>
      <td>jones</td>
      <td>20</td>
    </tr>
    <tr>
      <th scope="row">3</th>
      <td colspan="2">Larry</td>
      <td>50</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th>footer</th>
      <td>footer</td>
      <td>footer</td>
      <td>footer</td>
    </tr>
  </tfoot>
</table>

Responsive Tables

We can make tables responsive with the table-responsive class

To make it always responsive, we can use the table-responsive class:

<div class="table-responsive">
  <table class="table">
    <thead class="table-dark">
      <tr>
        <th scope="col">#</th>
        <th scope="col">First</th>
        <th scope="col">Last</th>
        <th scope="col">Age</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>james</td>
        <td>smith</td>
        <td>20</td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>mary</td>
        <td>jones</td>
        <td>20</td>
      </tr>
      <tr>
        <th scope="row">3</th>
        <td colspan="2">Larry</td>
        <td>50</td>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <th>footer</th>
        <td>footer</td>
        <td>footer</td>
        <td>footer</td>
      </tr>
    </tfoot>
  </table>
</div>

We make the table always responsive with the class in a div outside the table.

Also, we can make them responsive at a given breakpoint.

For example, we can write:

<div class="table-responsive-sm">
  <table class="table">
    <thead class="table-dark">
      <tr>
        <th scope="col">#</th>
        <th scope="col">First</th>
        <th scope="col">Last</th>
        <th scope="col">Age</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>james</td>
        <td>smith</td>
        <td>20</td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>mary</td>
        <td>jones</td>
        <td>20</td>
      </tr>
      <tr>
        <th scope="row">3</th>
        <td colspan="2">Larry</td>
        <td>50</td>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <th>footer</th>
        <td>footer</td>
        <td>footer</td>
        <td>footer</td>
      </tr>
    </tfoot>
  </table>
</div>

to make it responsive when the screen is wide enough to hit the sm breakpoint or wider.

sm can be substituted with md , lg , xl , or xxl .

Customizing in SASS

The table style presets can be changed in SASS.

The $table-striped-bg-factor, $table-active-bg-factor and $table-hover-bg-factor variables are used to determine the contrast in table variants.

Theme colors are lightened by the $table-bg-level variable.

Figures

We can add figures with captions with the figure tag.

The figcaption tag adds a caption for the figure.

Bootstrap 5 provides classes to make styling them easier.

For example, we can write:

`<figure class="figure">
  <img src="`http://placekitten.com/200/200`" class="figure-img img-fluid rounded" alt="cat">
  <figcaption class="figure-caption">A cat.</figcaption>
</figure>`

With Bootstrap 5’s text utilities, aligning the figure captions are easy:

`<figure class="figure">
  <img src="`http://placekitten.com/200/200`" class="figure-img img-fluid rounded" alt="cat">
  <figcaption class="figure-caption text-right">A cat.</figcaption>
</figure>`

With the text-right class, we aligned the caption to the right.

Form Controls

We can add form controls with Bootstrap 5 styles with the included classes.

For example, we can write:

<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control" id="email" placeholder="name@example.com">
</div>

<div class="mb-3">
  <label for="text" class="form-label">Example textarea</label>
  <textarea class="form-control" id="text" rows="3"></textarea>
</div>

to add some form controls.

We have the form-control class to add the form control styles.

form-label class add the form label styles.

Sizing

To change the size of the controls, we can use the .form-control-lg and .form-control-sm classes:

<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control-lg" id="email" placeholder="name@example.com">
</div>

We make the form control large with the form-control-lg class.

Likewise, we can make them smaller with the .form-control.sm class:

<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control-sm" id="email" placeholder="name@example.com">
</div>

Readonly

We can add the readonly boolean attribute to prevent users from changing the input value of the form.

For example, we can write:

<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control" id="email" placeholder="name@example.com" readonly>
</div>

The form input will be grayed out.

Readonly Plain Text

If we want to have a readonly form field without the any styles, then we can use the .form-control-plaintext class to make the field display as plain text.

For example, we can write:

<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control-plaintext" id="email" placeholder="name@example.com" readonly>
</div>

Now there’re no borders and other things displayed.

Conclusion

We can add styles to tables, figures, and form fields.

Categories
Bootstrap HTML

Bootstrap 5 — Radio Buttons, Checkboxes, and File Inputs

Bootstrap 5 is in alpha when this is written and it’s subject to change.

Bootstrap is a popular UI library for any JavaScript apps.

In this article, we’ll look at how to style radio buttons, checkboxes, and file inputs with Bootstrap 5.

Radio Buttons and Checkboxes without Labels

We can add radio buttons and checkboxes without labels.

To do that, we can write:

<div>
  <input class="form-check-input" type="checkbox" id="checkboxNoLabel" value="">
</div>

<div>
  <input class="form-check-input" type="radio" name="radioNoLabel" id="radioNoLabel1" value="">
</div>

to add them.

Toggle Buttons

Bootstrap lets us turn checkboxes and radio buttons into toggle buttons.

To do that, we can write:

<input type="checkbox" class="btn-check" id="btn-check" autocomplete="off">
<label class="btn btn-primary" for="btn-check">toggle</label>

to add the toggle button.

It’ll display differently depending on if it’s toggled on or off.

The id of the input and the for attribute of the label have to match.

Radio Toggle Buttons

We can do the same for radio buttons.

For example, we can write:

<div class="btn-group">
  <input type="radio" class="btn-check" name="options" id="apple" autocomplete="off" checked>
  <label class="btn btn-secondary" for="apple">apple</label>

<input type="radio" class="btn-check" name="options" id="orange" autocomplete="off">
  <label class="btn btn-secondary" for="orange">orange</label>

<input type="radio" class="btn-check" name="options" id="grape" autocomplete="off">
  <label class="btn btn-secondary" for="grape">grape</label>
</div>

to add a button group.

Each button is a group is a radio button.

We use the btn-group class to style the button group.

The input type is set to radio .

btn-check is the class to make them display as toggle buttons.

And the id of the input has to match the for attribute value of the label .

Outlined Styles

The toggle can have outlined styles instead of a background color.

For example, we can write:

<div class="btn-group">
  <input type="radio" class="btn-check" name="options" id="apple" autocomplete="off" checked>
  <label class="btn btn-outline-secondary" for="apple">apple</label>

<input type="radio" class="btn-check" name="options" id="orange" autocomplete="off">
  <label class="btn btn-outline-secondary" for="orange">orange</label>

<input type="radio" class="btn-check" name="options" id="grape" autocomplete="off">
  <label class="btn btn-outline-secondary" for="grape">grape</label>
</div>

to make the buttons that aren’t chosen display an outline.

We add the word outline in the class name for the label.

For checkboxes, we can write:

<input type="checkbox" class="btn-check" id="btn-check-outlined" autocomplete="off">
<label class="btn btn-outline-primary" for="btn-check-outlined">apple</label><br>

to make the toggle button displayed with outline styles instead of a background color.

File Browser

Bootstrap 5 provides a file browser to let users select a file.

For example, we can write:

<div class="form-file">
  <input type="file" class="form-file-input" id="customFile">
  <label class="form-file-label" for="customFile">
    <span class="form-file-text">Choose a file...</span>
    <span class="form-file-button">Browse</span>
  </label>
</div>

to add a file input with an input with the type set to file .

Also, we add the label with the form-file-label class.

Inside it, we add our placeholder, which is the span with the form-file-text class.

We also have a span with the form-file-button class to display a button we can click to show the file browser to let us select a file.

To disable the file input, we can add the disabled prop to the input.

For example, we can write:

<div class="form-file">
  <input type="file" class="form-file-input" id="customFile" disabled>
  <label class="form-file-label" for="customFile">
    <span class="form-file-text">Choose file...</span>
    <span class="form-file-button">Browse</span>
  </label>
</div>

to disable the file input.

If we have longer placeholder text, it’ll be truncated with an ellipsis added at the end:

<div class="form-file">
  <input type="file" class="form-file-input" id="customFile">
  <label class="form-file-label" for="customFile">
    <span class="form-file-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque quis nunc ultricies enim ullamcorper pretium at cursus tellus. Curabitur sit amet leo arcu. Integer vitae tincidunt odio. Duis id nunc dignissim, fringilla lacus ut, rutrum ligula. Morbi euismod accumsan augue, sit amet finibus ipsum ultrices ac. Ut convallis quis lacus in volutpat. Pellentesque volutpat dui et enim mattis, egestas posuere nisl maximus. Aenean commodo laoreet enim, sit amet tincidunt nisl porttitor non. Ut vestibulum mauris urna, eget consectetur tellus maximus at. Suspendisse pharetra ut erat sed euismod.
    </span>
    <span class="form-file-button">Browse</span>
  </label>
</div>

Conclusion

We can style radio buttons and checkboxes as toggle buttons.

Also, Bootstrap 5 comes with its own file input.