Inverted logo based on background colour - javascript

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>

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>

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);
}
}

Related

Why my loading text not stand out tho it has bigger z-index than my background image?

I'm making a blurry loading effect. My background image has a z-index of -1 and my loading text has no z-index. Everything works except my loading text, I can't see it loading and stand out from my background image...
Does anybody know what's wrong? it'd be kind of you to help! Thank you so much!
This is my JS:
const loadText = document.querySelector('.loading-text')
const bg = document.querySelector('.bg')
let load = 0
let int = setInterval(blurring, 30)
const scale = (num, in_min, in_max, out_min, out_max) => {
return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
}
function blurring() {
load++
if (load > 99) {
clearInterval(int)
}
loadText.innerText = `${load}%`
loadText.style.opacity = scale(load, 0, 100, 1, 0)
bg.style.filter = `blur(${scale(load, 0, 100, 30, 0)}px)`
}
This is my html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blurry Loading</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section class="bg">
<div class="loading-text">
0%
</div>
</section>
<script src="script.js"></script>
</body>
</html>
This is my CSS:
* {
box-sizing: border-box;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.bg {
background: url('z.jpg') no-repeat center center/cover;
position: absolute;
top: -30px;
left: -30px;
width: calc(100vw + 60px);
height: calc(100vw + 60px);
z-index: -1;
filter: blur(0px)
}
.loading-text {
padding: 50% 50%;
font-size: 50px;
color: #fff;
It's actually visible, but very poorly because you're putting blur filter on bg element and everything inside (that includes your loading-text). Just put your loading-text outside.
This problem is occurring because loading-text is inside bg. So when the blur effect is applied to bg it automatically gets applied to loading-text as well. So the loading percentage is being rendered, but it's blurred into the background image and therefore not visible.
One solution is to have two elements within your bg element. These elements would not be nested and therefore any style applied to either element would not affect the other element. The first element would show the background image and the second element would show the loading text.
Here is a way to do that using your code, but I've removed anything that isn't necessary to achieve this effect:
const loadText = document.querySelector('.loading-text')
const bg = document.querySelector('.bg-image')
let load = 0
let int = setInterval(blurring, 30)
const scale = (num, in_min, in_max, out_min, out_max) => {
return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
}
function blurring() {
load++
if (load > 99) {
clearInterval(int)
}
loadText.innerText = `${load}%`
loadText.style.opacity = scale(load, 0, 100, 1, 0)
bg.style.filter = `blur(${scale(load, 0, 100, 30, 0)}px)`
}
.bg,
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 190px;
}
.bg-image {
background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/FullMoon2010.jpg/200px-FullMoon2010.jpg');
filter: blur(30px);
}
.loading-text {
color: #fff;
font: normal 32px serif;
text-align: center;
line-height: 190px;
}
<!DOCTYPE html>
<html lang="en">
<body>
<section class="bg">
<div class="bg-image">
</div>
<div class="loading-text">
0%
</div>
</section>
</body>
</html>

Fade in and fade out different text in a container at the same time in a loop

const firstTitle = document.querySelector(".first-title");
const secondTitle = document.querySelector(".second-title");
const firstSubtitle = document.querySelector(".first-subtitle");
const secondSubtitle = document.querySelector(".second-subtitle");
window.onload = function() {
setInterval(function() {
firstTitle.classList.add('fadeOut');
secondTitle.classList.add('fadeIn');
firstSubtitle.classList.add('fadeOut');
secondSubtitle.classList.add('fadeIn');
}, 4000);
}
h1 {
margin-bottom: 24px;
position: relative;
}
h1 span:nth-child(2) {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
p {
font-size: 20px;
line-height: 27px;
margin-bottom: 80px;
position: relative;
}
p span:nth-child(2) {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
.fadeIn {
animation: fadeIn 1s linear infinite;
}
.fadeOut {
animation: fadeOut 1s linear infinite;
}
/* Fade In and Fade Out Animation */
#keyframes fadeIn {
0% {
opacity: 0;
}
50% {
opacity: 0.5
}
100% {
opacity: 1;
}
}
#keyframes fadeOut {
0% {
opacity: 1;
}
50% {
opacity: 0.5
}
100% {
opacity: 0;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Text Fading</title>
</head>
<body>
<div class="container">
<header class="header">
<section>
<h1>
<span class="first-title">Title A</span>
<span class="second-title">Title B</span>
</h1>
<p>
<span class="first-subtitle">Text A</span>
<span class="second-subtitle">Text B</span>
</p>
</section>
</header>
</div>
</body>
</html>
From my code, I have styled it in such a way that the text in the spans inside the h1 and p tags are at the same level. This is because I want a span to fade in the exact same time the other span is fading out such that it creates a temporary overlap effect. However, I am unable to do that with my present knowledge of CSS and JavaScript.
How do I continuously fade in and fade out the two different spans in h1 and p tags simultaneously in an infinite loop such that they overlap at a point before completely fading in or fading out.
solution:
let title1 = document.getElementById('first-title');
let subTitle1 = document.getElementById('first-subtitle');
let title2 = document.getElementById('second-title');
let subTitle2 = document.getElementById('second-subtitle');
// Third, create variable so is can check if this element is first element or second element
let checkTimes = true;
function hapyFade() {
setTimeout(function(){
// Sixthly,Evry time checkTimes is reverse to aprouch toggle element
if (checkTimes == true) {
// Seventh, In the first case of variapple, hide the first element and show the second
title1.style.opacity = subTitle1.style.opacity = 0;
title2.style.opacity = subTitle2.style.opacity = 1;
// Sixthly too, here reverse variable
checkTimes = false;
} else {
// Seventh too, In the second case of variapple, hide the second element and show the first
title1.style.opacity = subTitle1.style.opacity = 1;
title2.style.opacity = subTitle2.style.opacity = 0;
// Sixthly too, here reverse variable
checkTimes = true;
}
// Fifth, same a function inside setTimeOut so reabeate this each 2 second
hapyFade();
}, 2000);
}
// Fourth, I created a fuction for hide show elemnt as toggle - after 2 second
hapyFade();
h1 {
margin-bottom: 24px;
position: relative;
}
h1 span:nth-child(2) {
position: absolute;
top: 0;
left: 0;
/* Secondly, Hide the second element so that only the first element is on the square at the start of the page */
opacity: 0;
}
p {
font-size: 20px;
line-height: 27px;
margin-bottom: 80px;
position: relative;
}
p span:nth-child(2) {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
h1 span,
p span {
transition: all .5s ease-in-out;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Text Fading</title>
</head>
<body>
<div class="container">
<header class="header">
<section>
<h1>
<!-- First, here I used id so I can call it in javascript -->
<span id="first-title">Title A</span>
<span id="second-title">Title B</span>
</h1>
<p>
<span id="first-subtitle">Text A</span>
<span id="second-subtitle">Text B</span>
</p>
</section>
</header>
</div>
</body>
</html>

How to set the window's Y middle to element's Y middle?

I have created a button which should shift the window's Y to "BOX - 5" div's Y middle through onclick. So in other words I want to set the "Box - 5" div in the middle of the window. I have tried many methods using window.scrollTo and using elements.innerHeight/2, but I still cannot center the element to the middle of the window/screen. Please Help.
I wish to only use Javascript, but if its not possible with it then I would accept jQuery script.
index.html:
window.onbeforeunload = function () {
this.scrollTo(0, 0);
}
var content = document.getElementById("content"),
current = 0;
for (var y=0;y<10;y++) {
var box = document.createElement("div");
box.id = "box";
box.innerHTML = "Box - " + (y+1);
content.appendChild(box);
}
document.querySelector("BUTTON").onclick = function() {
var box_5 = document.querySelectorAll("#box")[4];
/*
NEED HELP HERE
*/
}
body {
margin: 0;
}
#box {
position: relative;
height: 500px;
width: 100%;
margin: 5% auto 5% auto;
color: black;
background-color: skyblue;
border: black 1px solid;
font-size: 50px;
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button>CLICK TO SET THE WINDOW'S Y MIDDLE TO (BOX 5)'s Y MIDDLE</button>
<div id="content"></div>
</body>
</html>
Updated your snippet as below. You can use DOM element property offsetTop to check its Y position and use window.scroll to scroll the view to that element. Another sidenote, it's better to not assign the same id to multiple elements, so I change the id property to class and added identifier _{index} for the class name.
window.onbeforeunload = function () {
this.scrollTo(0, 0);
}
var content = document.getElementById("content"),
current = 0;
for (var y=0;y<10;y++) {
var box = document.createElement("div");
box.className += "box _" + (y+1);
box.innerHTML = "Box - " + (y+1);
content.appendChild(box);
}
document.querySelector("BUTTON").onclick = function() {
var box_5 = document.querySelectorAll(".box._5")[0];
if (box_5) {
// scroll the window view to the element
window.scroll({
top: box_5.offsetTop,
behavior: 'smooth',
})
}
}
body {
margin: 0;
}
.box {
height: 500px;
width: 100%;
margin: 5% auto 5% auto;
color: black;
background-color: skyblue;
border: black 1px solid;
font-size: 50px;
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button>CLICK TO SET THE WINDOW'S Y MIDDLE TO (BOX 5)'s Y MIDDLE</button>
<div id="content"></div>
</body>
</html>

Why can't I get my HTML element to stay at the bottom of the page?

I've tried multiple methods of getting this to work but nothing has.
Here is my HTML:
here's a jsfiddle for simplicity https://jsfiddle.net/w1z9bahv/23/
I cannot figure out why I can't get the footer to stay at the bottom. I've tried changing the dark mode features in JavaScript, I've tried multiple different methods of positioning the element on the bottom.
Once I activate dark mode, my footer will shoot up and be in the middle of the page. I just want it to stay at the bottom.
Here's my current code:
var darkModeOn = false;
function darkMode() {
var element = document.body;
var footer = document.getElementById("bottomText");
if (darkModeOn == false) {
document.getElementById("darkMode").innerHTML = "Light mode";
darkModeOn = true;
} else {
document.getElementById("darkMode").innerHTML = "Dark mode";
darkModeOn = false;
}
element.classList.toggle("darkMode");
footer.classList.toggle("darkMode");
}
body {
position: relative;
background-color: white;
margin: 100px;
filter: invert(0%);
}
body.darkMode {
position: relative;
margin: 100px;
background-color: #222;
filter: invert(100%);
}
footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
}
footer.darkMode {
position: fixed;
left: 0;
right: 0;
bottom: 0;
}
<html>
<body>
<p>
Here is some irrelevant text
</p>
<button>
Here is an irrelivant button
</button>
<footer id="bottomText">
<span>here is my footer</span>
<span>why is it not on the bottom</span>
<span><u id="darkMode" onclick="darkMode()">Dark mode</u></span>
</footer>
</body>
</html>
If there is a better way to add a dark mode feature that would be helpful too :)
Thanks
You can try the following:
var darkModeOn = false;
function darkMode() {
var element = document.body;
var footer = document.getElementById("bottomText");
var buttonToInvert = document.getElementById("buttonToInvert");
if (darkModeOn == false) {
footer.innerHTML = "Light mode";
darkModeOn = true;
} else {
footer.innerHTML = "Dark mode";
darkModeOn = false;
}
element.classList.toggle("darkMode");
buttonToInvert.classList.toggle("darkMode");
}
body {
background-color: white;
margin: 100px;
}
body.darkMode {
margin: 100px;
background-color: #222;
}
button.buttonToInvert{
filter: invert(0%);
}
button.darkMode{
filter: invert(100%);
}
footer {
/*Do the font (maybe)*/
position: fixed;
left: 0;
right: 0;
bottom: 0;
}
<html>
<head>
</head>
<body>
<p>
Here is some irrelevant text
</p>
<button id="buttonToInvert">
Here is an irrelivant button
</button>
<footer>
<span>here is my footer</span>
<span>why is it not on the bottom</span>
<span><u id="bottomText" onclick="darkMode()">Dark mode</u></span>
</footer>
</body>
</html>
Using padding instead of margin will allow more control over the footer. You can still achieve the "margin" affect with using box-sizing:border-box; on body with padding:100px;.
The filter you added to body is affecting the fixed positioning of the footer. The effect is documented here. To bypass the effect, create another div containing everything on the page except the footer. Anything for which you want fixed positioning cannot be within a container with a filter or transformation. Therefore, using a container for everything that isn't fixed and putting all fixed positioned things outside of the container will isolate the filter from affecting the footer. To still achieve the filter on the footer, I kept the code that altered its class so that the footer itself received the filter and not through inheritance. Hopefully this makes sense but let me know if you don't understand.
var darkModeOn = false;
function darkMode() {
var element = document.getElementById('filterContainer');
var footer = document.getElementById("bottomText");
if (darkModeOn == false) {
document.getElementById("darkMode").innerHTML = "Light mode";
darkModeOn = true;
} else {
document.getElementById("darkMode").innerHTML = "Dark mode";
darkModeOn = false;
}
element.classList.toggle("darkMode");
footer.classList.toggle("darkMode");
}
html,body {
margin:0;
padding:0;
}
#filterContainer{
background-color:white;
padding:100px;
box-sizing:border-box;
filter:invert(0%);
height:200vh;
}
.darkMode{
filter:invert(100%) !important;
}
footer {
/*Do the font (maybe)*/
position: fixed;
left: 0;
right: 0;
bottom: 0;
}
<html>
<head>
</head>
<body>
<div id="filterContainer">
<p>
Here is some irrelevant text
</p>
<button>
Here is an irrelivant button
</button>
</div>
<footer id="bottomText">
<span>here is my footer</span>
<span>why is it not on the bottom</span>
<span><u id="darkMode" onclick="darkMode()">Dark mode</u></span>
</footer>
</body>
</html>

javascript mouseout function flickering

I'm trying to create a mouse in and out effect that shows and disappears DIV's according to the mouse function. I've successfully done this, but the mouseout function flickers on and off when im inside the div instead of staying on.
Heres my sample code:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kow Your Face</title>
<style>
#face {
background-image: url(face.png);
width: 262px;
height: 262px;
}
#lefteye {
background-image: url(circle.png);
width: 28px;
height: 28px;
position: relative;
top: 69px;
left: 59px;
}
#righteye {
background-image: url(circle.png);
width: 28px;
height: 28px;
position: relative;
top: 41px;
left: 167px;
}
#mouth {
background-image: url(circle.png);
width: 28px;
height: 28px;
position: relative;
top: 84px;
left: 114px;
}
</style>
</head>
<body>
<div id="face">
<div id="lefteye" onMouseOver="getElementById('lefteye').style.visibility='hidden'; getElementById('lefteyedes').style.visibility='visible';" onMouseOut="getElementById('lefteye').style.visibility='visible'; getElementById('lefteyedes').style.visibility='hidden';">
</div>
<div id="righteye" onMouseOver="getElementById('righteye').style.visibility='hidden'; getElementById('righteyedes').style.visibility='visible';" onMouseOut="getElementById('righteye').style.visibility='visible'; getElementById('righteyedes').style.visibility='hidden';">
</div>
<div id="mouth" onMouseOver="getElementById('mouth').style.visibility='hidden'; getElementById('mouthdes').style.visibility='visible';" onMouseOut="getElementById('mouth').style.visibility='visible'; getElementById('mouthdes').style.visibility='hidden';">
</div>
</div>
<div id="lefteyedes" style="visibility: hidden;">
<p>Left Eye</p>
</div>
<div id="righteyedes" style="visibility: hidden;">
<p>Right Eye</p>
</div>
<div id="mouthdes" style="visibility: hidden;">
<p>Mouth</p>
</div>
</body>
</html>
Use document.getElementById instead of just getElementById and you can use this keyword to refer to the current element:
<div id="lefteye" onMouseOver="this.style.visibility='hidden'; document.getElementById('lefteyedes').style.visibility='visible';" onMouseOut="this.style.visibility='visible'; document.getElementById('lefteyedes').style.visibility='hidden';">
</div>
For some reason your onmouseout function is being repeatedly called "onmousemove"...this solution should help you suppress the onmouseout function being repeatedly called. I've rewritten your code a little to help make it easier to enforce changes later (illustrated with one of the onmouseover/onmouseout pairs)...give this a shot:
<script type="text/javascript">
function leftEyeVisibility(vis1, vis2) {
//this function should work for the left eye when the left eye is hidden (lefteyedes is visible) and the mouse is moving over (or not moving at all) the hidden left eye div but has not moused out of it
var dg = document.getElementById("lefteye");
var divStyle = window.getComputedStyle(dg, "");
var mousePosition = function (e) {
var xCoord = e.pageX;
var yCoord = e.pageY;
return xCoord + "," + yCoord;
}
var positionArray = mousePosition.split(","); //split the xy coordinates returned by previous function
if ((positionArray[0] > dg.offsetLeft) && (positionArray[0] < dg.offsetLeft + dg.offsetWidth) && (positionArray[1] > dg.offsetTop) && (positionArray[1] < dg.offsetTop + dg.offsetHeight)) {
var mouseOverlap = 'yes';
} else var mouseOverlap = 'no';
if ((divStyle.visibility === 'hidden') && (mouseOverlap === 'yes')) {
return false;
} else {
document.getElementById("lefteye").style.visibility = vis1;
document.getElementById("lefteyedes").style.visibility = vis2;
}
}
</script>
<div id="lefteye" onmouseover="leftEyeVisibility('hidden', 'visible')" onmouseout="leftEyeVisibility('visible', 'hidden')">
</div>
With jQuery it would be much easier to do this...let me know if it works.

Categories

Resources