Changing the fas fa icon dynamically with JavaScript for a Dark/Light mode switch

I'm having trouble figuring out why the icon won't change no matter what I do.

$( ".inner-switch" ).on("click", function() {
    if( $( "body" ).hasClass( "dark" )) {
      $( "nav" ).removeClass( "dark-force" );
      $( "body" ).removeClass( "dark" );
      $(this).find("i").toggleClass("fas fa-moon");
    } else {
      $( "body" ).addClass( "dark" );
      $( "nav" ).addClass( "dark-force" );
      $(this).find("i").toggleClass("fas fa-sun");
    }
});
.dark {
    background-color: #222;
}

.dark-force * {
    background-color: #222;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />

<nav class="navbar">
  <div class="hero-body">
    <div class="container">
      <div class="navbar-brand">

        <a href="/">
          <img src="{% static 'portfolio/Logo.png' %}" width=60>
        </a>

        <div class="navbar-end">

          <div class="navbar-item">
            <div class="buttons">
              <a class="button is-primary is-rounded is-outlined">
                <strong>Blog</strong>
              </a>
            </div>
          </div>

          <div class="navbar-item">
            <div class="buttons">
              <a class="button is-primary is-rounded">
                <strong>Say Hello!</strong>
              </a>
            </div>
          </div>

          <div class="navbar-item">
            <div class="buttons">
              <a class="button is-primary is-rounded inner-switch">
                <i class="fas fa-moon"></i>
              </a>
            </div>
          </div>

        </div>
      </div>
    </div>
  </div>
</nav>

The dark mode works fine, but the icon remains stuck on the moon (fas fa-moon). While I may be new to javascript, I have a good understanding of HTML and CSS. Any guidance would be greatly appreciated. Thank you for taking the time to read this! Stay safe and stay positive!

Answer №1

You are getting close and your code is looking great, but you should utilize the addClass and removeClass functions to switch the icon from a sun to a moon and vice versa.

$(this).find("i").removeClass("fa-sun").addClass('fa-moon');

Using toggleClass will not work as expected because the existing icon will still be present alongside the new one.

Check out the Live Working Demo:

$(".inner-switch").on("click", function() {
  if ($("body").hasClass("dark")) {
    $("nav").removeClass("dark-force");
    $("body").removeClass("dark");
    $(this).find("i").removeClass("fa-sun").addClass('fa-moon');
  } else {
    $("body").addClass("dark");
    $("nav").addClass("dark-force");
    $(this).find("i").removeClass("fa-moon").addClass('fa-sun');
  }
});
.dark {
  background-color: #222;
}

.dark-force * {
  background-color: #222;
}

.fa-sun {
 color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<div class="navbar-item">
  <div class="buttons">
    <a class="button is-primary is-rounded inner-switch is-outlined">
      <i class="fas fa-moon"></i>
    </a>
  </div>
</div>

Answer №2

One issue is that the toggle function only switches between the sun and moon classes every other time, when in fact both need to be toggled each time.

$(this).find("i").toggleClass("fa-moon").toggleClass("fa-sun");

It's worth noting that there's no need to toggle the fas class as it is always required. Additionally, there's no need for redundancy by including the code within an if/else statement - since the goal is to toggle both classes every click, this line can simply be incorporated directly into the function.

Here's a functional example:

$(".inner-switch").on("click", function() {
  // toggle moon and sun every time
  $(this).find("i").toggleClass("fa-moon").toggleClass("fa-sun");

  if ($("body").hasClass("dark")) {
    $("nav").removeClass("dark-force");
    $("body").removeClass("dark");
} else {
 $("body").addClass("dark");
    $("nav").addClass("dark-force");
  }
});
.dark {
  background-color: #222;
}

.dark-force * {
  background-color: #222;
}

.button {
  font-size: 3em;
  color: #f00
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />

<div class="navbar-item">
  <div class="buttons">
    <a class="button is-primary is-rounded inner-switch is-outlined">
      <i class="fas fa-moon"></i>
    </a>
  </div>
</div>

Answer №3

Make sure to also switch the font color along with the background color when toggling.

$("#lightswitch i").click(function() {
    var isDark = $("body").is(".dark");
    $("body").toggleClass("dark", !isDark);
    $(this).toggleClass("fa-moon", isDark).toggleClass("fa-sun", !isDark);
});
body.dark {
  background-color: #222;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />

<body>
  <div class="navbar-item">
    <div class="buttons">
      <a id="lightswitch" class="button is-primary is-rounded inner-switch is-outlined">
        <i class="fas fa-moon"></i>
       </a>
     </div>
  </div>
</body>

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

Problem with the purity of :global() CSS-module selectors in NextJS

Currently in the process of migrating an app from CRA to NextJS, I've encountered an issue with the .module.scss files of certain components and pages: Syntax error: Selector ":global(.label-primary)" is not pure (pure selectors must contain ...

Issue with Chrome causing linear-gradient background to break when zoomed out

My current design involves utilizing a gradient background to create an alternating pattern for rows that are absolutely positioned. However, I have run into an issue when zooming out in Chrome. The sizing calculations for the gradient background are not ...

Attempting to replicate a <textarea> to behave like a <div> element

I am currently facing an issue with my HTML and CSS code. I have tried to construct a design using a <div> but it resulted in horizontal scrolling and looked chaotic. How can I make the CSS and HTML look the same without any issues? <textarea c ...

Verification of HTML Drop-down Options

Is there a way to display an alert message if the selection is left blank using plain JavaScript? This is my code for the option menu I have: <div class="interest"> <label for="interest">Interest Area *</label> ...

Personalized marker hover effect on Google Maps

After successfully creating a Google map using data from a JSON array with multiple latitude and longitude coordinates for different locations, I am now looking to display a custom popup (a div with dynamic information) over each marker when hovered. How ...

Transforming color images into black and white using JavaScript

     I have implemented this code to convert colored images to grayscale. function applyGrayscaleEffect() {         var imageData = contextSrc.getImageData(0, 0, width, height);         var data = imageData.data;         var p1 = 0.99;   ...

Guide on utilizing the list of names in a POST request

<td class="widht200"> <input type="text" name="agg" size="2" disabled="disabled"/> </td><td class="widht200"> <input type="text" name="agg" size="2" disabled="disabled"/></td><td class="widht200"> <input type=" ...

Tablesorter experiencing issues with filters when loading Ajax table

I've attempted various methods to solve the issue of filtering in my table, including refreshing and updating with triggers after loading (unsuccessful), as well as relocating the tablesorter files to a loaded URL from the main page (also unsuccessful ...

Rearrange the text next to the Checkbox using Bootstrap

I'm having trouble aligning the "Default checkbox" text next to the checkbox itself checkbox This is what I've attempted so far <div class="col-2"> <label for="Desc" class="col-sm col-form-label">D ...

Exploring the Depths of Angular Reactive Forms with Recursion

Dealing with recursion and form groups app-root.component.html <div [formGroup]="form"> some content <app-root></app-root> </div> Is it possible to implement the same form group and form controls in my recursive structure? For ex ...

Utilize jQuery to reset the input field value within a repeating control

I'm encountering an issue while attempting to clear the content of a textbox within a repeater control. The repeater control is bound in the code behind with its data source. The textbox displays information from the data source. I am using ajax and ...

When the footer div is viewed on a mobile device, the Social Media Icons will stack vertically along with additional text

Seeking help with a bootstrap website issue here. When I switch to mobile view, the images in my footer are stacking vertically outside of the div. The code and an example image are provided below. <!DOCTYPE html> <html> <head> ...

Leveraging JavaScript to identify web browsers

I am looking to implement a feature on my website where if the visitor is using Internet Explorer 8.0 or an earlier version, they will receive an alert prompting them to upgrade their browser before proceeding. For users with other browsers, the page will ...

Exploring methods to reload a parent window from a child window using PHP

After opening a popup window from a modal, I am now trying to refresh the page where my modal is located. I have attempted to write some code that I found here, but it doesn't seem to be working. Here is an example of what I have tried: // This fun ...

Bootstrap's white navbar transitions seamlessly to a transparent state as it hovers

Recently, I've been tackling a design challenge by creating a navigation bar that changes opacity and size of the logo when scrolled past the header. Everything was going smoothly until I encountered an issue with the navbar overlapping a paragraph on ...

JavaScript Birthday Verification: Regular Expression Pattern

I am currently testing out JavaScript form validation. The information provided is not being sent to any database, it's just for format testing purposes. All the regex checks are functioning correctly apart from birth. It seems like there may be an i ...

Ways to select a single checkbox when other checkboxes are selected in JavaScript

var select_all = document.getElementById("select_all"); //reference to select all checkbox var checkboxes = document.getElementsByName("testc"); //retrieving checkbox items //function to select all checkboxes select_all.addEventListener("change", function ...

Ensure that the fail callback function in jQuery ajax is triggered only after all retry attempts have failed

Utilizing ajax in conjunction with jQuery involves utilizing $.ajax which returns a promise known as ajaxPromise. The specific requirement is to have the ajaxPromise only catch failures if all retry attempts for the ajax calls have failed, with the goal of ...

Execute function upon successful Ajax call

I am currently working on a project where we are retrieving information from an XML file. Everything is functioning well, but I now need to create a slider to display this content. My plan is to utilize jCarousel, as they claim to support dynamically loade ...

Encountered an error creating 'CustomElement' when the JavaScript file is located in the head section of the document

I've defined a custom element like this: class SquareLetter extends HTMLElement { constructor() { super(); this.className = getRandomColor(); } } customElements.define("square-letter", SquareLetter); After including the JavaS ...