Robolisk
Robolisk

Reputation: 1792

Inverted logo based on background colour

I'm wondering if anyone has discovered a beautiful way to rotate out logo's based on 'sections' of the page.

In more detail I have a logo on a transparent navbar, let's say a white logo.

My page is broken into sections, some gray/light background some darker/black backgrounds. As I scroll, I hope that the sticky logo will be swapped out to an opposing color. I attempted to do this by naming each section with an id such as id='white and id=black.

Then once I scrolled down and hit that I'd trigger the function and swap out the picture, although, I realized that it only detects the first id of white or the second of black.

Not sure how to approach this other then make a unique id for each section, which, seems barbaric.

window.onscroll = function() {
  myFunction()
};


function myFunction() {
  if ($(this).scrollTop() >= $('#white').position().top) {
    logoSwap(0);
  } else if (($(this).scrollTop() >= $('#black').position().top)) {
    logoSwap(1);

  }

}

function logoSwap(which) {
  if (which) {
    $('#logo').css("background-color", "black");
  } else {
    $('#logo').css("background-color", "white");
  }
}
#logo {
  position: fixed;
  top: 0;
  left: 0;
  height: 50px;
  width: 50px;
  background-color: black;
}

.h500 {
  height: 500px;
}

.white {
  background-color: white;
}

.black {
  background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="logo">
</div>

<section id="white" class='h500 white'>
</section>
<section id="black" class='h500 black'>
</section>
<section id="white" class='h500 white'>
</section>
<section id="black" class='h500 black'>
</section>

Upvotes: 1

Views: 963

Answers (2)

Lahcen YAMOUN
Lahcen YAMOUN

Reputation: 691

You have to use classes and not id's because there must be only one item in the document having a same id, contrary to class.

About the script: the idea is to iterate over all the sections .white or .black and get the top and bottom for each one, which will allow you while handling scrolling event to verify if your logo is inside a given section (between the section's top and bottom positions)

Edit: I add this code (with pure javascript) to my comment.

const whites = [...document.querySelectorAll('.white')].map(e => ({
    top: e.getBoundingClientRect().top,
    bottom: e.getBoundingClientRect().bottom
}));

//If you have a logic of only white and black sections, you can omit blacks, else you can use them

// const blacks = [...document.querySelectorAll('.black')].map(e => ({top: e.top, bottom: e.bottom}));

const logo = document.querySelector('#logo');

document.addEventListener('scroll', () => {
    let position = (logo.getBoundingClientRect().bottom + logo.getBoundingClientRect().top) / 2 + window.scrollY;
    for (let i = 0; i < whites.length; i++) {
        if (position >= whites[i].top && position <= whites[i].bottom) {
            logo.classList.remove('whiteLogo');
            logo.classList.add('blackLogo');
            return;
        }
    }

    logo.classList.remove('blackLogo');
    logo.classList.add('whiteLogo');
});
*,
html,
body {
    margin: 0;
    padding: 0;
}

section {
    height: 200px;
}

.black,
.blackLogo {
    background: black;
}

.white,
.whiteLogo {
    background: white;
}

#logo {
    position: fixed;
    top: 0;
    left: 0;
    height: 50px;
    width: 50px;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="logo" class="whiteLogo"></div>
    <section class="black"></section>
    <section class="white"></section>
    <section class="black"></section>
    <section class="black"></section>
    <section class="white"></section>
    <section class="black"></section>
</body>

</html>

Upvotes: 1

Jeff
Jeff

Reputation: 382

DOM id's need to be unique, so your code will only recognize the first instance of each. You should find the last section you scrolled over, and find what class that has:

function myFunction() {
    var position = $(this).scrollTop()

    var class_pos = $('.white, .black').filter(function(){ return position >= $(this).position().top})
  // console.log(class_pos)
  if ($(class_pos[class_pos.length - 1]).hasClass('white')){
    logoSwap(0);
  } else {
    logoSwap(1);
  }

}

Upvotes: 1

Related Questions