1

I'm trying to create a button toggle in html without using png or svg files. I created the toggle element and assigned id's to each relevant element, styled with CSS, and then went on to using JavaScript to implement an animation whenever the toggle is clicked.

The HTML is written like this:

<div class="dark-mode-toggle">
    <p>Dark Mode:</p>
    <button class="toggle" id="toggle" title="toggle dark mode">
        <div class="toggle-circle" id="circle"></div>
    </button>
</div>

This is the CSS:

.toggle {
    width: 48px;
    height: 24px;
    border: 1px solid black;
    border-radius: 15px;
    padding-left: 3px;
}

.toggle-circle {
    height: 16px;
    width: 16px;
    border: 1px solid black;
    border-radius: 10px;
}

I wanted to do this by using a JS event listener for the toggle element, listening for a click, and then calling a function whenever the element is clicked. I wrote this:

const toggle = document.getElementById("circle")
const toggleBorder = document.getElementById("toggle")

toggle.addEventListener('click', function() {
    if (toggleBorder.style.padding-left === '3px') {
        toggleBorder.style.padding-left === '20px'
    }

    else {
        toggleBorder.style.padding-left === '3px'
    }
});

It didn't work at all, when debugging I found clicking the toggle returns this in the console: Cannot read properties of null (reading 'style') at HTMLDivElement.

This led me to conclude that the const toggleBorder isn't being read properly, and sure enough when I type toggleBorder in the console it returns null. What's strange to me is that typing toggle into the console does return the proper HTML element, and the syntax of both the consts are identical.

Why does one const target the element while the other returns as null?

I've spell checked. Changed the toggleBorder const between getElementById and getElementsByClassName but this made no change. Researched online but didn't find anything specifically addressing the issue I encountered.

EDIT: Thank you for the replies, I was able to correct my errors but ran into an issue getting the function to return the button to it's original position when clicked a second time, only the first click worked. I resolved this by writing my function this way:


    const toggle = document.getElementById("circle")
    const toggleBorder = document.getElementById("toggle")

    toggle.addEventListener('click', function() {
        if (toggle.style.transform = 'TranslateX(0px)') {
            toggle.style.transform = 'TranslateX(22px)'
            toggle.style.transition = '350ms'
            toggle.style.backgroundColor = 'green'
            toggle.style.border = '1px solid white'
            toggleBorder.style.backgroundColor = 'black'
            toggleBorder.style.transition = '400ms'
        }
        if (toggle.style.transform = 'TranslateX(22px)') {
            toggle.addEventListener('click', function () {
                toggle.style.transform = 'TranslateX(0px)'
                toggle.style.backgroundColor = 'black'
                toggle.style.border = '1px solid black'
                toggleBorder.style.backgroundColor = 'white'
            })
        }
    });

But now the issue I'm facing is that clicking a third time does not change the toggle back to it's "dark mode" variant (TranslateX(22px)).

  • 1
    Perhaps you mean `paddingLeft` instead of `padding-left`? The latter is not a valid identifier in JS and will be parsed as `padding - left` (i.e. `padding` minus `left`). – InSync Apr 13 '23 at 22:17
  • 1
    Inside the If...else where you make the assignments, you are actually using a conditional (===) instead of (=). – Albert Apr 13 '23 at 22:18
  • 1
    accessing the `style` attribute only accesses inline styles, not styles set in external CSS – pilchard Apr 13 '23 at 22:20
  • Does this answer your question? [How to get an HTML element's style values in JavaScript?](https://stackoverflow.com/questions/2664045/how-to-get-an-html-elements-style-values-in-javascript) – pilchard Apr 13 '23 at 22:21
  • also once you fix your syntax errors: [Why is this function working on second click only?](https://stackoverflow.com/questions/72179259/why-is-this-function-working-on-second-click-only) – pilchard Apr 13 '23 at 22:36
  • @InSync I corrected this, thank you, I wasn't previously aware of this. – edible-zebra Apr 13 '23 at 23:14

2 Answers2

1

Inside the If...else where you make the assignments, you are actually using a conditional (===) instead of (=):

toggleBorder.style.padding-left === '20px'

change to:

toggleBorder.style.paddingLeft = '20px'

and also change this line

toggleBorder.style.padding-left === '3px'

change into:

toggleBorder.style.paddingLeft = '3px'

You also need to change the conditional to use paddingLeft (instead of padding-left).

Albert
  • 487
  • 1
  • 4
  • 16
  • Ironically, it's the 2nd click where the function stops working now. Clicking sets the padding to 20px, but clicking again doesn't reset the padding to 3px. Initially I believed that perhaps this is because the inline style created by JS displays 20px whilst the CSS displays 3px, and the JS places priority on the CSS doc which still reads 3px, thus 'if' is called rather than 'else'. This doesn't seem to be the case however. I switched to inline styles for the padding and deleted the CSS rule, but the behavior is identical. – edible-zebra Apr 13 '23 at 23:19
-1

const toggle = document.getElementById("circle")
const toggleBorder = document.getElementById("toggle")
toggleBorder.style.paddingLeft = '3px'

toggle.addEventListener('click', function() {
console.log(toggleBorder.style.paddingLeft);
    if (toggleBorder.style.paddingLeft == '3px') {
        toggleBorder.style.paddingLeft = '20px'
    }

    else {
        toggleBorder.style.paddingLeft = '3px'
    }
});
.toggle {
    width: 48px;
    height: 24px;
    border: 1px solid black;
    border-radius: 15px;
    padding-left: 3px;
}

.toggle-circle {
    height: 16px;
    width: 16px;
    border: 1px solid black;
    border-radius: 10px;
}
<div class="dark-mode-toggle">
    <p>Dark Mode:</p>
    <button class="toggle" id="toggle" title="toggle dark mode">
        <div class="toggle-circle" id="circle"></div>
    </button>
</div>
DCR
  • 14,737
  • 12
  • 52
  • 115