skip to Main Content

I want to create the simplest possible HTML toggle button, but I’m having a hard time finding exactly how to do this.

As far as I can see, there is no direct support for toggle button in HTML, the only thing I found is an ARIA attribute "aria-pressed" recommended for that purpose here: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role#toggle_buttons

So, I came up with the following example with just a <button> with an aria-pressed attribute which works, in the sense that the JavaScript handler console.log prints out true, then false, then true etc – that is, it shows toggling, but only of the ‘aria-pressed’ attribute – the look of the button is not changed at all!

Now, the thing is, when I use a <button> as below, with no CSS at all, the button inherits some browser styling defaults; in Firefox at least, I can see (slight) changes in button gray color if I hover (mouseover) the button, and yet some more changes if I click the button and hold it pressed.

So, what I’d like for my "simplest" button, is simply to inherit the existing browser default styling for a "pressed" button, and have the button be styled like that for as long as the ‘aria-pressed’ attribute is true. Preferably, I would not want to write any specific CSS to style the button (as in specific background color etc) – all I want is for the button to inherit the browser defaults for a pressed button, when rendering a "toggled" button when its ‘aria-pressed’ attribute is true.

Is there any way to achieve this, and if so, how?

<!DOCTYPE html>
<html>

<head>
  <title>test</title>
  <style>

  </style>
</head>

<body>
  <button type="button" id="btn-my-toggle" aria-pressed="false">Click me, a toggle button</button>
</body>

<script>
  function on_my_toggle_btn_click(e) {
    //console.log(e, this); // `e` is `click { target: button#btn-my-toggle ... }`;  `this` is `<button id="btn-my-toggle"...`
    let isPressed_str = this.getAttribute('aria-pressed'); // note, typeof here is String!
    let isPressed = (isPressed_str === 'true'); // "cast" to Boolean
    isPressed = !(isPressed); // toggle
    this.setAttribute('aria-pressed', isPressed);
    console.log(this.getAttribute('aria-pressed'));
  }

  let my_toggle_btn = document.getElementById('btn-my-toggle');
  my_toggle_btn.onclick = on_my_toggle_btn_click;
</script>

<html>

2

Answers


  1. This is simpler if you do not want to use a checkbox (like here https://alvarotrigo.com/blog/toggle-switch-css/)

    document.getElementById('btn-my-toggle')
      .addEventListener('click', (e) => e.target.closest('button').classList.toggle('pressed'))
    #btn-my-toggle { border: 1px solid black;} 
    #btn-my-toggle.pressed { border: 1px solid red;} 
    <button type="button" id="btn-my-toggle">Click me, a toggle</button>

    To add the aria is trivial:

    document.getElementById('btn-my-toggle')
      .addEventListener('click', (e) => {
        const tgt = e.target.closest('button');
        tgt.classList.toggle('pressed');
        tgt.setAttribute('aria-pressed', tgt.matches('.pressed'))
      });
    #btn-my-toggle {
      border: 1px solid black;
    }
    
    #btn-my-toggle.pressed {
      border: 1px solid red;
    }
    <button type="button" id="btn-my-toggle">Click me, a toggle</button>
    Login or Signup to reply.
  2. A checkbox is the simplest and most semantic way to create a an interactive element that a user can toggle "on" or "off".

    <input type="checkbox" id="my-toggle">
    <label for="my-toggle">toggle me</label>

    If you want it to visually appear as a button, you can style it with CSS. Here’s an example from the Bootstrap CSS framework:

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
    <input type="checkbox" id="my-toggle" class="btn-check">
    <label class="btn btn-primary" for="my-toggle">toggle me</label>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search