Resizable dimensions for the dark mode switch

My latest project involves creating a toggle button for switching between light and dark themes 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>

The functionality of the toggle button is great with a box width of 90 and height of 45. However, upon changing the dimensions to 60 and 30 respectively, issues arise when transitioning to dark mode:

  1. In dark mode, part of the sun image becomes visible, which is not ideal.
  2. There seems to be an inconsistency in the path length when sliding left and right, but I can't pinpoint the source of the problem.

To address these challenges, I am looking to make this code more scalable in terms of design adjustments. It would be beneficial to have variables defined in the CSS file for easy customization as per different dimensions. Any guidance or suggestions from experienced developers are highly appreciated.


Updated code snippet below reflects changes made to the width and height attributes of the box:

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>

Answer №1

    .box .ball {
      /* Adjusting the size of the ball to be half of the box width */
      width: 30px;
      height: 30px;
      background-color: grey;
      transition: all 1s ease;
      position: absolute;
      border-radius: 50%;
      border: 3px solid black;
      box-sizing: border-box;
    }

In the CSS above, I included a new property "box-sizing:border-box" to ensure that when transforming on click, it includes the width, border, margin, padding, etc. By default, its value is "content-box," which means these properties are not included in the transformation. Changing it to "border-box" ensures they are included. For more information, you can read about it here: https://www.w3schools.com/css/css3_box-sizing.asp

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I keep getting double results from the Multiple Checkbox Filter

Currently, I am facing an issue with a checkbox filter on a product page that I'm developing. The filter is functioning correctly, but I encounter duplicate results when an item matches multiple criteria. For instance, if I select both 'Size 1&ap ...

Error not caught: AngularJS module error

Initially, I was hesitant to ask this question, but after struggling for two hours without any success, I've decided to seek some assistance. I'm trying to integrate the ngResource module into my application. Prior to this, everything was functi ...

Out of the blue, the CSS functionality in my React app completely ceased to

I've been developing this website using React and Material UI, and I chose to implement standard CSS for styling. However, after closing my code editor and reopening it, some parts of the CSS do not seem to be loading properly. I'm completely puz ...

Obtaining the class value using the getAttribute function

Is there a way to extract and store the value of the class (for example, "AAABC") in a variable? I've attempted various keywords with the getAttribute method, but have had no success. Using terms like "class" returned "gwt-Label", while others yielded ...

jquery logic for iterating through all elements in a select menu encountering issues

In search of a solution to iterate through all options in a dropdown list using code, comparing each to a variable. When a match is found, I aim to set that particular value as the selected item in the dropdown and then exit the loop. Here's what I&ap ...

Utilize Javascript to extract information from an array of XML objects

I have an XML object that I need to parse in order to extract startdate and end date data. My goal is to compare and group appointments with the same date together, but I don't have much experience manipulating XML - I'm more comfortable with JSO ...

Tips for ensuring all my onclick event are clickable in iOS browser

Currently, I am developing a web page using HTML5 and JQuery Mobile. I have encountered an issue where the onclick function does not work on iOS device browsers. Is there a way to change all onclick events to be accessible through tapping instead? This wou ...

ways to assign local file path as image url in json

Hey there, I am a new tool for angularjs. Take a look at the json file below: [ { "name": "WORLD", "population": 6916183000, "flagurl":"C:\xampp\htdocs\selva \Flag_of_the_People's_Republic_of_China.svg" }, { "na ...

Unable to stop the default form submission in Vue 3

Using the latest version of Vue 3 I am encountering an issue with preventing form submission. Here is my HTML form: <form id="app" @submit="onSubmit"> <input type="text"> <input type="text"> ...

My onClick AngularJS function contains a for loop that is not functioning properly upon initial click

When I click on a student's name in my AngularJS app, the program is supposed to show the student's full name and list of tuitions. However, I am encountering an issue where the for loop does not work on the first click, but it works fine on the ...

remove a specific element from an array

Hey there! I'm attempting to remove only the keys from an array. Here's the initial array: {everyone: "everyone", random: "random", fast response time: "fast response time", less conversations: "less conversatio ...

Tips for submitting a form using javascript while preventing the default action

Looking for a way to submit a form in Javascript and prevent the default action? Let's explore how you can achieve this. Initially, my HTML form with the ID "contact_form" had an input element like so: <input id="contact_send_msg" type="submit" val ...

Apply a chosen style to the element that was clicked on, while removing the style from the rest

Here is an example of my ul li structure: <div id="categoryTree"> <ul> <li id="cat_15"> <a class="hasSubCat" href="javascript:void(0);"><img src="images/icons/folder.gif" border="0" alt="Folder" title=" Folder ">N ...

Turning multiple .html files into a single csv using beautifulsoup

I am dealing with a situation where I have 13,000 html files stored in a folder and my goal is to consolidate all the data into a single csv file. Although I believe I have made progress in extracting the data, I am encountering challenges when it comes t ...

The Mystery of the Undefined Return Value in JavaScript's Map Function

My array contains around 1000 elements. I'm encountering a situation where the map function returns undefined for certain indexes. Is there a method to only retrieve values that meet a specific condition? I want to filter out elements with values less ...

Sharing data between promises in Node.jsExplanation: In Node.js, passing values

Can someone assist with passing an object that I am creating step by step using promises with firebase? I would like to know if there is a more efficient way to construct the object without passing it through the promise chain. Below is the code snippet I ...

Ways to eliminate extra space from the edges of a container

Trying to wrap my page in a Material UI container component, but there's this persistent whitespace on the outside that no matter how much I tweak the margin and padding, it just won't disappear. Any CSS wizard out there with a workaround to make ...

The process of uploading a file is interrupted by an AJAX Timeout

My HTML form includes a file input field that utilizes AJAX to upload the selected file, complete with a progress bar. However, I encountered an issue where the request would hang without any response. To prevent this from happening in the future, I aim t ...

Using v-model with variables in Vue

In my form, I am encountering an issue with a textarea field when inserting a value from the database (using Laravel 10 and Inertia) where it is not being displayed. However, in other instances, the value appears as expected. It seems that there is a confl ...

Obtain individual information from XML

After fetching data from the server using ajax, I am looking to retrieve only a specific part of the data which is the name. How can I modify my code to achieve this? const url = 'https://jsonplaceholder.typicode.com/users' const xhr = new XMLH ...