Elementor Header Change Color On Scroll Dynamically

Elementor Header Change Color On Scroll Dynamically

Element.How also offers premium tutorials! Check them here:

Table of Contents

In this premium tutorial you are going to learn how to change the styling of the header dynamically, based on the class names of the sections / containers encountered while scrolling down the page.

In other words, we are going to create a whole new CSS styling for the header, and it will be enabled just when we are over sections with a specific class name.

Here is a rough version of what we are creating.

Here is a production website where I implemented this same code snippet, with great results. (In collaboration with the amazing somethingfamiliar agency)

Features include:

  • Have a different logo image show for the alternate heading
  • Different color for the links and pointers from the Nav Menu element
  • Different color for the Nav Menu hamburger icon on mobile
  • Different background color and box shadow for the heading section
  • Different colors for the social icons element as well as the button element
  • Option to have a specific hover style always in place (as in the demos I shared above)
  • Works with either sections or containers

Let's get started!

To start with, let's add this code to our website

This is a premium tutorial. Purchase access to unlock the full tutorial.

Access tutorial

$39/one time Purchase access


  • Gain Access to This TutorialUnlock complete access to the current tutorial: Elementor Header Change Color On Scroll Dynamically
  • Future UpdatesYou will get access to all future updates to this tutorial.
  • Enjoy Unlimited UsageUse on as many of your own sites or your clients sites as you wish.

    Note that reselling or redistributing is not permitted.

Access everything

$299/one time Purchase All Access


  • Unlock every premium tutorial on Element.howGet access to the entire library of premium tutorials on Element.how
    Preview premium tutorials
  • Get access to the CSS course for Elementor usersAccess the complete 14 HTML chapters, 30 CSS chapters and 7 Elementor Projects.Learn more
  • Simple CSS Grid For ElementorAn Elementor Addon to Create Awesome Grid Layouts in a Single Click for Containers, Galleries and Loop Grid. Learn more
  • free extra: ShapeDividers.com Premium AccessLifetime Premium Access to ShapeDividers.comVisit ShapeDividers.com
  • 30 day money backNo questions asked money back. Not what you expected? Get a refund.
  • One-time payment of only $299No hidden fees or subscriptions.

    Sales taxes added where applicable.
  • Great supportGet help when you need it. Support includes getting things working as intended.

    Support excludes customization work.
  • Lifetime access to everything Element.howThe price reflects what is currently available on Element.how. All future updates are included, but none are promised. You pay for what is available now, and the rest is a sweet extra.

    I will say that it is definitely my intention to keep adding tutorials to Element.how.
* All prices are USD. Applicable taxes will be charged at checkout. Have a question? See the FAQ or email me.

Element.how also provides premium tutorials showing awesome advanced designs, check them out here.

Looking for something else? Search across 2737 Elements right here:

Checkout the Elementor Addon Finder directly

58 Responses

  1. Hi again Maxime!

    I've implemented this on a site and it works great. The only problem I'm having is when I tried creating a hamburger menu (which also works great) when I click on the hamburger it glitches and changes to the default header and doesn't turn back.

    I originally tried your tutorial: https://element.how/elementor-full-screen-split-navigation/

    It worked well but again, it glitched to the default header so changed colour on the wrong background.

    Then I tried using JetBlocks hamburger panel, same problem.


    Any ideas on how to make it not glitch like that?

    1. Hey Millie!

      Yes I see the problem indeed.

      Try this. Change this line:

      let observedElements = document.querySelectorAll('.elementor-section-wrap > *, .elementor > *:not(.elementor-section-wrap)');


      let observedElements = document.querySelectorAll('.elementor-section-wrap > *, .elementor > *:not(.elementor-section-wrap, #navsection)');

  2. Also, I am using menu anchors to click through to the next section using the arrows at the bottom of each section. However, the sticky header seems to be confusing it and adds the header above where the menu anchor is so it appears high. Any idea of how I could resolve this?

    So grateful for all your help.

    1. The anchors offset is caused by this CSS I found active on your site :

      html, body {
      scroll-padding-top: 75px;

      Not certain where exactly you added it though. Hopefully you will know!

      1. Hey Millie!

        I still see the CSS applied on the page... I'm not certain if it's really the cause of the problem or not, but first let's try to remove it.

      2. It's on that element:

        /* Start custom CSS for social-icons, class: .elementor-element-40595bd */

      3. Sorry! I forgot I put it in one more place when testing. I've removed it now. Has it gone?

      4. Yes now it has... the issue is still there. Could you please confirm that if you remove my custom code, the issue goes away? Just trying to confirm that it's related to my code, and not just an Elementor issue.

      5. Hi Maxime,

        The issue is still there, so I guess it is an issue with elementor?

        Out of interest, is adding 3 headings possible via the way in this tutorial?


      6. Hey Millie!

        Yes seems like an Elementor issue. You can still try to use the code from that tutorial here : https://element.how/elementor-scroll-offset-menu-anchors-table-content/

        Try this, in a code snippet :

        add_action( 'wp_footer', function() {
        if ( ! defined( 'ELEMENTOR_VERSION' ) ) {
        window.addEventListener('elementor/frontend/init', function() {
        elementorFrontend.hooks.addFilter( 'frontend/handlers/menu_anchor/scroll_top_distance', function( scrollTop ) {
        return scrollTop + 90;
        } );
        } );
        } );

        Yes, you can add as many headers as you want, it will work. Just keep this in mind: You should have only one container with the ID 'header-section'.

        So you would need to add all your different header containers IN that 'header-section' ID container. You will also need to rework the CSS to work as intended for each header container.

      7. Thank you. I've added the code snippet to a new snippet. I'm getting this error.

        The code snippet you are trying to save produced a fatal error on line 14:
        syntax error, unexpected end of file

        Thanks for all your help, sorry for being a pain!

      8. Oups really sorry about that. It didn't copy paste as expected.

        I updated my previous comment with the proper code, please try again.

      9. That has worked perfectly! You are a genius!

        Thank you so much for all your help!!

  3. Hi Maxime,

    I tried adding the HTML code to elementor >> custom code, but I got css errors in the root part of the code. Can you help me what am I doing wrong here?

    Thank you,

    1. Hey Paveen!

      Elementor is using an old CSS validator, and it's inaccurate. It will flag errors when there are none.

      The code works. If it's not working for you, maybe you added the PHP version in there? That one only works for with a php code snippet in the Code Snippet plugin. It won't work with Elementor custom code.

      Really, I suggest you use the first code snippet (php version), and add it in a code snippet from the Code Snippet plugin. That's ideal.

  4. Hi Maxime,
    is there any update for the code and flex containers, as this one seems not to be working with the new Elementor versions?
    Thank you in advance

    1. Hey Jovan!

      The code is tested working on the latest version of Elementor. Could you share your page with me so that I have a look why it might not be working as it should?


    1. Hey Caleb!

      It looks like it might be because your very first section on your page is set to 'sticky'. Try having it be normal, see if that fixes it.

  5. Is it possible to apply this CSS, but to another block/section/container that is not exclusive to HEADER?

    I subscribed thinking I could apply it to a container I have on the site that follows during the user's scroll (like a sticky index box), but I saw that the code contains HEADER specifications.

    1. Greetings!

      Yes it is certainly possible, as the class gets added to the <body> element.

      You will need some CSS knowledge though... I don't provide CSS directly for this scenario, as you could literally have any element sticky, and the CSS would be different in every case.

      Essentially, you write CSS for the alternate styling this way. Give you sticky container the ID "stickyContainer", then write like this:

      body.alternate-theme #stickyContainer .my-element-class-name {
      background-color: #333;

      that will change the background color of your element with the class 'my-element-class-name' to #333 when the alternate styling is active.

      Hope this helps


      1. thank you for the quick response.

        I will try it on a HEADER to understand the system, and then try to apply it to the container I want.

        as my CSS knowledge is limited, let's see if I can do it

      2. Hello again 🙂

        I managed to apply the tutorial to a sticky section, as was my initial idea.

        I don't know if it's working exactly like the header, but it does the trick.

        However, because it's a very vertical section the transition from black to white, and white to black seems too "rough".

        I tried applying the transition to the CSS, but it only worked on one transition.

        Is it possible to add to the CSS directly?
        Or would this transition have to be applied directly in the script (which is beyond my knowledge)?

      3. Yes you should be able to add the transition to the CSS directly. That's where it goes... the JavaScript here only changes class names on the body element. It does not directly change any styling.

        I don't know what you have used exactly here, but you need something like

        .element {
        transition: color 0.4s, border 0.4s;

        Or try just this, in the Advanced > Custom CSS field:

        selector * {
        transition: color 0.4s, border 0.4s;


  6. Hi Maxime.

    I have a problem that I've been trying to fix for days now, but I can't find a solution.

    I have a header that contains three seperat nav menus.

    All three of them are black as default.

    When I scroll down the page they change color from black to white when scrolling over the first container as they should, but when I scroll back to the top they keep being white. If I refresh the page they are black again. Any idea how to resolve this?

    Best regards

  7. Hi Maxime! When the "alternate theme" elements are set to hidden on mobile (through the responsive panel in the elementor advanced tab), they still show up - is this because of this part here:
    body.alternate-theme .alternate-theme-only {
    display: block;
    overrides the 'elementor-hidden-mobile' class? If so, can you please suggest some code to fix this?

    I tried asking chatGPT and it gave me this below, but that didn't work lol:

    const element = document.querySelector('#your-element-id');

    if (element && !element.classList.contains('elementor-hidden-mobile')) {
    element.style.display = 'block';

    Thanks for any help you can provide! 🙂

    1. Hey Charlene!

      Try this. Below this part of the CSS:

      body.alternate-theme .alternate-theme-only {
      display: block;

      Add this:

      @media (max-width:767px){
      body.alternate-theme .alternate-theme-only.elementor-hidden-mobile {
      display: none;

      Let me know if that works!


  8. Thanks so much that totally works!
    Unfortunately though, I just realized the styling on the drop down mega menu breaks once I add all this code in. 🙁 If I remove everything (like the whole thing - javascript, html, etc) the styling returns to normal. I've added it via my functions.php theme file, and also tried just adding it in an html widget through elementor, but the styling breaks either way.

  9. Hello, is there a way to modify the code to have 3 header options (on the same page) instead of 2? I though I saw a reference to tag in earlier comments, but didn't really see (or understand) how.


  10. Hi Maxime! This has been working amazing, up until today when I updated the elementor pro plugin to 3.15.1. The dropdown arrows/icons have reverted to the theme's default "red", but the text and logo and icons still color switch perfectly.

    Would you happen to know how i can fix this? I've tried a few things but haven't been successful. The website is live at https://www.justforyoudayspa.com

    Thanks so much!

    1. Hey Charlene!

      That's an Elementor bug... there is some CSS missing. There is no color styles applied at all to that icon, unless it's on hover.

      They will probably fix it, but for now you can add that CSS:

      .elementor-widget-n-menu .e-n-menu-item-title:not(.e-current) i {
      color: var(--n-menu-item-title-color-normal,var(--n-menu-item-title-hover-color-fallback));


      1. You are a fricking wizard lol! Thank you SO much for providing a quick fix in the interim! Worked perfect. Many thanks!!

    1. Greetings Christian!

      First, you will need to remove the class name default-theme-only so that your button is still displayed (now it gets display:none when the alternate theme is active).

      Then, add this variable with all the others:

      --alternate-button-icon-color: #333333;

      And below in the CSS, add this line where you see that same selector

      body.alternate-theme #header-section .elementor-button {
      fill: var(--alternate-button-icon-color); /* this is the line to add */

      I also made these changes in my code, so you could import the code again if you prefer.

      Then it should all work!


  11. Thanks Maxime
    Looking good. However I'm still getting a very brief #fff button background as colour changes from red to #F6F2EF on scroll. Which one is causing this?

    1. Hey Christian!

      I updated my CSS code to add three variables:

      --alternate-button-icon-color: #333333;
      --alternate-button-hover-text-color: #333333;
      --alternate-button-hover-bg-color: #ffffff;

      And this CSS:

      body.alternate-theme #header-section .elementor-button:hover {
      background-color: var(--alternate-button-hover-bg-color);
      color: var(--alternate-button-hover-text-color);
      body.alternate-theme #header-section .elementor-button:hover svg {
      fill: var(--alternate-button-hover-icon-color);

      That should allow you to control the hover color of the icon.


    1. Greetings Christian!

      Change this part:

      body.alternate-theme #header-section .elementor-button:hover svg {
      fill: var(--alternate-button-hover-icon-color);


      body.alternate-theme #header-section .elementor-button:hover svg,
      body.alternate-theme #header-section .elementor-button:focus svg {
      fill: var(--alternate-button-hover-icon-color);


  12. Hello Maxime! How do I approach this for sections where the main menu needs to be transparent? I basically need "three" menu on desktop:

    1. Black logo, black text, dark button style with a transparent background
    2. Same element as #1 (Black logo, black text, dark button style) but with a white background
    3. White logo, white text, light button style with a dark background

    For the buttons, I am also using the "Creative Button" widget from Essential Add-Ons.

    1. Hey Georgia!

      Sorry I don't have an option for three variations, only two is possible.

      Technically there could be three, however the tutorial is already complex enough with two variations, so I don't want to make it too complex by adding more variations.

      For the Creative Button, if you don't require it I suggest switching to the Elementor button. If you need it, then share with me your URL, and I will set you up.


    2. I should also mention that if you just want the header to be transparent at the top of the page, then this is possible. Share your page with me I will help you with this.

      1. Thank you for the quick reply! I've gone ahead and swapped in the Elementor button instead of the Creative Button then.

        And noted re: three menu not being possible. The header only needs to be transparent at the top of a few pages (not every page). It sounds like that is possible?

    3. Yes that should be possible, I will show you how, just send me your URL and the pages where you want it transparent.

  13. Thank you so much! My client actually just let me know that she'd prefer no background color at all (just the logo, text and button color changes for dark vs light). So I've got those sorted out now, woohoo!

    I do have one more follow up though - if I try to scroll back up, I can no longer see the hero section of the page. Here is the home page for reference where you can see it happening: https://divyam1.sg-host.com/

    This menu effect is only going to be for desktop, so please disregard tablet/mobile.

    1. Greetings Georgia!

      You gave the hero section the class name default-theme-only , which is intended to be used on elements in the header, that should show for the default theme and not the alternate theme.

      Remove that class from the hero section and it will fix this.


      1. Thank you so much Maxime! I'm almost done getting this set up. I just need to have the desktop menu background show transparent JUST for the hero section of this page: https://divyam1.sg-host.com/

        There are a few other pages that will need to have the menu background be transparent just on the hero sections as well. Is that possible?

    2. Greetings Georgia!

      Simply add this CSS, only on the specific page(s) where you want the header to be transparent at the top.

      #header-section:not(.elementor-sticky--effects) {
          background-color: transparent;

      Then, in your header template, set the effect offset value to what you need... It's the scroll point (in PX) at which the default background color will come back.


Leave a Reply