Scalable size of dark theme toggle button

Viewed 66

I have created a dark theme toggle button using CSS, HTML, and JavaScript:

id("theme-btn").addEventListener("change", function() {
  if (this.checked) {
    qs(".box").setAttribute('style', 'background-color:#CCCCCC;')
    qs(".ball").setAttribute('style', 'transform:translatex(100%);')
    document.body.classList.remove("light");
    document.body.classList.add("dark");
  } else {
    qs(".box").setAttribute('style', 'background-color:black; color:white;')
    qs(".ball").setAttribute('style', 'transform:translatex(0%);')
    document.body.classList.remove("dark");
    document.body.classList.add("light");
  }
});

// Helper functions
function id(id) {
  return document.getElementById(id);
}

function qs(selectors) {
  return document.querySelector(selectors);
}
body.dark {
  background-color: #616161;
  color: white;
}

body.light {
  background-color: white;
  color: black;
}

input[type="checkbox"] {
  display: none;
}

.btn {
  align-self: flex-end;
  margin: 5px 10px;
}

.box {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* BOX-WIDTH */
  width: 90px;
  /* BOX-WIDTH/2 */
  height: 45px;
  background-color: black;
  transition: all 1s ease;
  position: relative;
  /* BOX-WIDTH/4 */
  border-radius: 22.5px;
  cursor: pointer;
}

.box .ball {
  /* BOX-WIDTH/2 */
  width: 45px;
  /* BOX-WIDTH/2 */
  height: 45px;
  background-color: grey;
  transition: all 1s ease;
  position: absolute;
  border-radius: 50%;
  border: 3px solid black;
}

.box .scenary {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  transition: all 1s ease;
  padding: 5px 10px 0px 10px;
}

.box .scenary svg {
  /* BOX-WIDTH/3 */
  width: 30px;
}
<div class="btn">
  <input type="checkbox" name="theme-btn" id="theme-btn">
  <label for="theme-btn">
    <span class="box">
      <span class="ball"></span>
      <span class="scenary">
        <span class="moon">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-moon">
            <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
          </svg>
        </span>
        <span class="sun">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun">
            <circle cx="12" cy="12" r="5"></circle>
            <line x1="12" y1="1" x2="12" y2="3"></line>
            <line x1="12" y1="21" x2="12" y2="23"></line>
            <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
            <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
            <line x1="1" y1="12" x2="3" y2="12"></line>
            <line x1="21" y1="12" x2="23" y2="12"></line>
            <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
            <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
          </svg>
        </span>
      </span>
    </span>
  </label>
</div>

As you might observe, it works quite well in this situation (i.e., width and height of box equal to 90 and 45). However, when I changed the width and height of box to 60 and 30, respectively in the CSS file, some problems popped up: (Please run the code snippet below)

  1. When switching to dark mode, some part of the sun image will be visible, which of course is not ideal and annoying.
  2. It seemed the slider path length of going right and left are different. But I couldn't figure out where did the problem come from...

As mentioned in the title, I think it would be nice to make this code snippet of dark theme toggle button to be scalable. (Preferably having variables defined in the CSS file -> I am not sue if this is possible) I.e., when one changes the width and height of the box, everything will behave properly and nicely.

I am new to web development. Any advice and help would be of great appreciation.


Code snippet with width and width of box changed to 60 and 30:

id("theme-btn").addEventListener("change", function() {
  if (this.checked) {
    qs(".box").setAttribute('style', 'background-color:#CCCCCC;')
    qs(".ball").setAttribute('style', 'transform:translatex(100%);')
    document.body.classList.remove("light");
    document.body.classList.add("dark");
  } else {
    qs(".box").setAttribute('style', 'background-color:black; color:white;')
    qs(".ball").setAttribute('style', 'transform:translatex(0%);')
    document.body.classList.remove("dark");
    document.body.classList.add("light");
  }
});

// Helper functions
function id(id) {
  return document.getElementById(id);
}

function qs(selectors) {
  return document.querySelector(selectors);
}
body.dark {
  background-color: #616161;
  color: white;
}

body.light {
  background-color: white;
  color: black;
}

input[type="checkbox"] {
  display: none;
}

.btn {
  align-self: flex-end;
  margin: 5px 10px;
}

.box {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* BOX-WIDTH */
  width: 60px;
  /* BOX-WIDTH/2 */
  height: 30px;
  background-color: black;
  transition: all 1s ease;
  position: relative;
  /* BOX-WIDTH/4 */
  border-radius: 15px;
  cursor: pointer;
}

.box .ball {
  /* BOX-WIDTH/2 */
  width: 30px;
  /* BOX-WIDTH/2 */
  height: 30px;
  background-color: grey;
  transition: all 1s ease;
  position: absolute;
  border-radius: 50%;
  border: 3px solid black;
}

.box .scenary {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  transition: all 1s ease;
  padding: 5px 10px 0px 10px;
}

.box .scenary svg {
  /* BOX-WIDTH/3 */
  width: 20px;
}
<div class="btn">
  <input type="checkbox" name="theme-btn" id="theme-btn">
  <label for="theme-btn">
    <span class="box">
      <span class="ball"></span>
      <span class="scenary">
        <span class="moon">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-moon">
            <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
          </svg>
        </span>
        <span class="sun">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun">
            <circle cx="12" cy="12" r="5"></circle>
            <line x1="12" y1="1" x2="12" y2="3"></line>
            <line x1="12" y1="21" x2="12" y2="23"></line>
            <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
            <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
            <line x1="1" y1="12" x2="3" y2="12"></line>
            <line x1="21" y1="12" x2="23" y2="12"></line>
            <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
            <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
          </svg>
        </span>
      </span>
    </span>
  </label>
</div>

1 Answers
    .box .ball {
      /* BOX-WIDTH/2 */
      width: 30px;
      /* BOX-WIDTH/2 */
      height: 30px;
      background-color: grey;
      transition: all 1s ease;
      position: absolute;
      border-radius: 50%;
      border: 3px solid black;
      box-sizing: border-box;
    }

In above css i added new property "box-sizing:border-box" because by default its value "content-box" it means when you transform on click it not included width, border, margin etc.. so we make to "border-box" so it includes its width margin pading etc. For more information read this. https://www.w3schools.com/css/css3_box-sizing.asp

Related