CSS mix-blend-mode + JS - javascript

So I have a custom js cursor ( which follows the mouse cursor with a delay ) which has a background color of #000 and mix-blend-mode set to difference. My body background color and text is set to #fff. Now, I have a p tag with the text "HELLO" which I want to be visible just the words "H" and "O", so I created a span which color's is set to #000. When I hover over the P tag, because of the mix-blend-mode, I can see the "ELL" words as I wanted, but the words "H" and "O" get " invisible ". How can I make them be visible when the cursor gets over it? ( just the part of each word which is being hovered by the cursor, not the entire word, IF the cursor doesn't cover the entire word )
Is there any solution? I tryed to change the color of the "H" and "O" on mouseenter/mouseleave but it doesn't work as expected.
const cursor = document.querySelector('.cursor')
const wuc = document.querySelectorAll('.wuc')
document.addEventListener('mousemove', e => {
cursor.setAttribute('style', 'top: ' + e.clientY+'px; left: '+e.clientX+'px;')
})
wuc.forEach((wuc) => {
wuc.addEventListener('mouseenter', () => {
wuc.style.color = '#fff'
})
wuc.addEventListener('mouseleave', () => {
wuc.style.color = '#000'
})
})
body {
background-color: #fff;
color: #fff;
}
.cursor {
width: 5vw;
height: 5vw;
transform: translate(-2.5vw, -2.5vw);
position: fixed;
transition-duration: 200ms;
transition-timing-function: ease-out;
background-color: #000;
border-radius: 50%;
mix-blend-mode: difference;
}
p {
margin-left: 30vw;
margin-top: 40vh;
}
.wuc {
color: #000;
}
<div class="cursor"></div>
<p class="container">
<span class="wuc">H</span>ELL<span class="wuc">O</span>
</p>

I would color the text using a radial-gradient that follow the same position of your custom cursor
const cursor = document.querySelector('.cursor')
document.addEventListener('mousemove', e => {
cursor.setAttribute('style', 'top: ' + e.clientY + 'px; left: ' + e.clientX + 'px;');
document.body.setAttribute('style', '--x: ' + e.clientX + 'px;--y:' + e.clientY + 'px;');
})
body {
background-color: #fff;
color: #fff;
}
.cursor {
width: 5vw;
height: 5vw;
transform: translate(-2.5vw, -2.5vw);
position: fixed;
transition-duration: 200ms;
transition-timing-function: ease-out;
background-color: #000;
border-radius: 50%;
mix-blend-mode: difference;
}
p {
margin-left: 30vw;
margin-top: 40vh;
}
.wuc {
background:
radial-gradient(farthest-side, #fff 99.5%, #000 100%) calc(var(--x,0px) - 2.5vw) calc(var(--y,0px) - 2.5vw)/5vw 5vw fixed no-repeat,
#000;
-webkit-background-clip:text;
background-clip:text;
-webkit-text-fill-color: transparent;
color:transparent;
}
<div class="cursor"></div>
<p class="container">
<span class="wuc">H</span>ELL<span class="wuc">O</span>
</p>

Related

Custom cursor doesn't move with page when scroll

I have built a custom cursor, but im having an issue with its position when you scroll the page. Rather than following the mouse cursor, it stays where it was on the page until you move the mouse again and then it catches up.
let mouseCursor = document.querySelector(".cursor");
window.addEventListener('DOMContentLoaded', cursor);
window.addEventListener('mousemove', cursor);
document.addEventListener('mouseenter', () => mouseCursor.style.display = 'block');
document.addEventListener('mouseleave', () => mouseCursor.style.display = 'none');
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)) {
jQuery('.cursor').remove();
} else {
mouseCursor.style.display = 'block';
}
function cursor(e){
mouseCursor.style.top = "calc(" +e.pageY + "px - 1rem)";
mouseCursor.style.left = "calc(" +e.pageX + "px - 1rem)";
}
.section{
height:200vh;
}
.cursor{
display:none;
width: 20px;
height: 20px;
border: 2px solid #f2f2f2;
outline: 2px solid #000;
border-radius: 50%;
position: absolute;
transition: all 0.3s ease;
transition-property: background, transform;
transform-origin: center center;
z-index: 20000;
pointer-events: none;
}
<div class="cursor"></div>
<div class="section"></div>
You need to work with clientX/Y property not pageX/Y.
Because clientX/Y coordinates are relative to the top left corner of the visible part of the page, while pageX/Y is relative to the top left corner of the whole page.
Also, Instead of making your circle position:absolute , you have to change it to position:fixed;
Elements with fixed positioning are fixed with respect to the viewport
CSS absolute and fixed positioning
let mouseCursor = document.querySelector(".cursor");
window.addEventListener('DOMContentLoaded', cursor);
window.addEventListener('mousemove', cursor);
document.addEventListener('mouseenter', () => mouseCursor.style.display = 'block');
document.addEventListener('mouseleave', () => mouseCursor.style.display = 'none');
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)) {
jQuery('.cursor').remove();
} else {
mouseCursor.style.display = 'block';
}
function cursor(e){
mouseCursor.style.top = "calc(" +e.clientY + "px - 1rem)";
mouseCursor.style.left = "calc(" +e.clientX + "px - 1rem)";
}
.section{
height:200vh;
}
.cursor{
display:none;
width: 20px;
height: 20px;
border: 2px solid #f2f2f2;
outline: 2px solid #000;
border-radius: 50%;
position: fixed;
transition: all 0.3s ease;
transition-property: background, transform;
transform-origin: center center;
z-index: 20000;
pointer-events: none;
}
<div class="cursor"></div>
<div class="section"></div>

Hiding/Showing CSS elements does not work?

THE WHOLE CODE IN JSFIDDLE
I have been struggling to effectively remove the code and css created in the function Seifenblasen_blasen()
function Seifenblasen_blasen(){
btn1.style.display = 'none';
document.getElementById("text").innerHTML="Bubble"
const section = document.querySelector('section')
const createElement = document.createElement('spawn')
var size = Math.random() * 60;
createElement.style.width = 30 + size + 'px';
createElement.style.height = 30 + size + 'px';
createElement.style.left = Math.random() * innerWidth + "px";
section.appendChild(createElement);
setTimeout(() => {
createElement.remove()
},8000)
}
const Blaseninterval = setInterval(Seifenblasen_blasen, 100)
created CSS:
section {
width: 100%;
height: 100vh;
overflow: hidden;
background: #1F69FA;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
section.text{
font-size: 10em;
color: #333;
margin: 0 auto;
text-align: center;
font-family: consolas;
background-color:#1F69FA;
pointer-events: none;
border: none;
}
section spawn {
position: absolute;
bottom: -80px;
background: transparent;
border-radius: 50%;
pointer-events: none;
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.5);
animation: animate 4s linear infinite;
}
section spawn:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
transform: scale(0.25) translate(-70%, -70%);
background: radial-gradient(#fff, transparent);
opacity: 0.6;
border-radius: 50%;
}
#keyframes animate {
0% {
transform: translateY(0%);
opacity: 1;
}
99% {
opacity: 1;
}
100% {
transform: translateY(-2000%);
opacity: 0;
}
section span {
margin-top: 700px;
font-size: 1em;
color: #333;
margin: 0 auto;
font-family: consolas;
background-color: #1F69FA;
border: none;
position: absolute;
}
HTML:
<section id="section">
<div class="content">
<button id="btn"></button>
<button id="btn1"></button>
</div>
</section>
to then execute the next function function next(). This removal is needed because when I don't remove the elements from the first function the second wont work. I could just do document.head.innerHTML = "" but that would then also remove the css needed for the button appearing in the next function. So then I tried to make variables with const
const btn = document.getElementById('text');
const btn1 = document.getElementById('text1');
const section = document.querySelector('section')
// in function Seifenblasen_blasen()
btn1.style.display = 'none';
// in function next()
section.style.display = 'none';
btn.style.display = 'none';
btn1.style.display = 'block';
to hide and show only parts of the css without removing the css entirely to keep the styling intact, but now nothing works anymore.(the button on the next Screen doesn't show up at all and the first button does not contain any styling) My endgoal is that I can essentially switch between two screens one showing the bubbles and one the bouncy balls and when I click on the button it goes on. (for example start is bubbles. I click -> Bounce, click again -> back to Bubbles and so on)

Cursor changer effect

I am having trouble changing my custom cursor width and height when I hover on the img element.
I tried using both css and javascript for the effect to work but it won't. When I change my function from "onmouseover" to "onclick" it works perfectly fine.
const cursor = document.querySelector('#cursor');
document.addEventListener('mousemove', e => {
cursor.setAttribute("style", "top: " + (e.clientY - 10) + "px; left: " + (e.clientX - 10) + "px;")
})
/*
/////Second way with javascript/////
var cursor = document.getElementById('cursor');
document.addEventListener('mousemove', function(e){
var x = e.clientX;
var y = e.clientY;
cursor.style.left= x + "px";
cursor.style.top= y + "px";
});
*/
function myFunction() {
document.getElementById("cursor").style.width = "100px";
document.getElementById("cursor").style.height = "100px";
}
body {
margin: 0;
height: 100vh;
background: rgb(27, 27, 27);
}
#cursor {
width: 30px;
height: 30px;
border: 2px solid gray;
border-radius: 50%;
position: fixed;
transition-duration: 100ms;
transition-timing-function: ease-out;
}
img {
position: absolute;
top: 50%;
left: 50%;
}
img:hover #cursor {
width: 100px;
height: 100px;
}
<div id="cursor"></div>
<img onmouseover="myFunction()" src="navbar.svg" alt="navbar">
How about this class toggle. Works.
Always preferable to use addEventListener everywhere
const cursor = document.querySelector('#cursor');
document.addEventListener('mousemove', e => {
cursor.setAttribute("style", "top: " + (e.clientY - 10) + "px; left: " + (e.clientX - 10) + "px;")
})
const hoverIt = e => cursor.classList.toggle("hover");
document.getElementById("navbarimg").addEventListener("mouseover",hoverIt);
document.getElementById("navbarimg").addEventListener("mouseover",hoverIt);
#cursor {
width: 30px;
height: 30px;
border: 2px solid gray;
border-radius: 50%;
position: fixed;
transition-duration: 100ms;
transition-timing-function: ease-out;
}
#cursor.hover {
width: 100px;
height: 100px;
}
img {
position: absolute;
top: 50%;
left: 50%;
}
img:hover #cursor {
width: 100px;
height: 100px;
}
<div id="cursor"></div>
<img id="navbarimg" src="navbar.svg" alt="navbar">
So the css solution here will not work as the #cursor is not a child of the img. You could have it a child of the anchor but that is probably the wrong approach anyway as it is not extendable.
You should probably change the logic to use an eventListener for simplicity...
document.getElementById("testImg").addEventListener("mouseover", function( event ) {
alert("over"); // Do your resizing here and ensure the image has the matching id
})

Attempting to trigger modals with h2 elements to overlay an animating background. Doesn't work, can someone help see where I went wrong?

As it says in my title, I am trying to trigger modals with javascript by clicking on h2 elements.
When I use inspector to change the modal display mode from none to visible I can see the modal on top of everything else. But clicking on the h2 elements doesn't seem to trigger this action so I assume its a problem with my javascript.
Can anyone help me out here? Can't seem to get it and I'm sure its something dumb.
Here is my code.
Html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jacob Truax Portfolio</title>
<script src="main.js"></script>
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="fonts.css">
<script src="jquery.js"></script>
</head>
<body>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>We are a magazine. This is a test.</p>
</div>
</div>
<!-- Button triggering color change -->
<div id="myBtn" class="Btn">
<button></button>
</div>
<!-- main content -->
<div class="main">
<ul>
<li class="fnup">fn-up</li>
<li class="about">about</li>
<li class="issue">issue 0</li>
<li class="contact">contact</li>
</ul>
</div>
<!-- main-2 content overlaid on "main" -->
<div class="main-2">
<h2 id="myButton" class="fnup2">fn-up</h2><br>
<h2 class="about2">about</h2><br>
<h2 class="issue2">issue 0</h2><br>
<h2 class="contact2">contact</h2>
</div>
<!-- section with rotating 3d object -->
<section>
<div class="face face-cover"></div>
<div class="face face-spine"></div>
<div class="face face-back"></div>
<div class="face face-top"></div>
<div class="face face-side"></div>
<div class="face face-bottom"></div>
</section>
</body>
<script src="rotate.js"></script>
<script src="gradient.js"></script>
<script src="rotate-type.js"></script>
<script src="transition.js"></script>
css
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 5; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
font-size: 2vw;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
/* End modal ============ */
body {
background-color: #d22c1f;
font-family:"Brrr", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 700;
font-size: 12vw;
overflow: hidden;
perspective: 1500px;
height: 100vh;
width: 100vw;
}
#media only screen and (min-width: 1600px) {
body {
font-size: 210px
}
}
/* a {
opacity: 0;
color: rgba(102, 102, 102, 0);
text-decoration: none;
display: inline-block;
} */
/* the main contet is in 3d space and rotates slightly with the cursor */
.main {
position: relative;
height: 100vh;
width: 100vw;
transform-style: preserve-3d;
backface-visibility: hidden;
transform: rotateX(0deg) rotateY(0deg);
}
li {
text-shadow: 4px 4px 40px #000;
color: rgba(102, 102, 102, .3);
padding-left: 60px;
top: -10px;
display: inline-block;
}
/* main-2 is h2 texts overlaid on top of "main" in order to trigger modals */
.main-2 {
position: fixed;
left: 0;
top: 0;
}
h2 {
opacity: 1;
color: rgba(102, 102, 102);
text-decoration: none;
display: inline-block;
padding-left: 60px;
top: -10px;
cursor: pointer;
}
/* This button triggers the background color change */
div.Btn {
position: fixed;
line-height:0;
font-size: 0px;
right: 3vw;
bottom: 3vh;
width: 36px;
height: 36px;
background-image: url(lib/frown.svg);
opacity: 0.3;
mix-blend-mode: overlay;
z-index: 2;
}
div.Btn:hover {
background-image: url(lib/smile.svg);
opacity: 0.3;
mix-blend-mode: overlay;
}
button {
width: 36px;
height: 36px;
border: none;
outline:none;
background: transparent;
border: none !important;
cursor: pointer;
font-size:0;
}
/* section for rotating object following cursor */
section {
position: absolute;
top: 50%;
left: 75vw;
transform-style: preserve-3d;
backface-visibility: hidden;
transform: rotateX(0deg) rotateY(0deg);
z-index: 1;
}
div.face {
position: absolute;
top: 0;
left: 0;
background-size: cover;
}
div.face-cover {
width: 440px;
height: 620px;
background-image: url(lib/fn-up_Magazine_Cover.jpg);
transform: translateX(-50%) translateY(-50%) translateZ(15px);
}
div.face-side {
width: 30px;
height: 620px;
background-image: url(lib/fn-up_Magazine_Side.jpg);
transform: translateX(-50%) translateY(-50%) rotateY(90deg) translateZ(220px);
}
div.face-spine {
width: 30px;
height: 620px;
background-image: url(lib/fn-up_Magazine_Spine.jpg);
transform: translateX(-50%) translateY(-50%) rotateY(-90deg) translateZ(220px);
}
div.face-top {
width: 440px;
height: 30px;
background-image: url(lib/fn-up_Magazine_Top.jpg);
transform: translateX(-50%) translateY(-50%) rotateX(90deg) translateZ(310px);
}
div.face-bottom {
width: 440px;
height: 30px;
background-image: url(lib/fn-up_Magazine_Bottom.jpg);
transform: translateX(-50%) translateY(-50%) rotateX(-90deg) translateZ(310px);
}
div.face-back {
width: 440px;
height: 620px;
background-image: url(lib/fn-up_Magazine_Back.jpg);
transform: translateX(-50%) translateY(-50%) rotateY(180deg) translateZ(15px);
}
Javascript
rotate.js
document.addEventListener("mousemove", function (event) {
const x = event.pageX
const y = event.pageY
const midX = x - window.innerWidth / 3.9
const midY = y - window.innerHeight / 2
const box = document.querySelector('section')
//box.style.left = x + "px"
//box.style.top = y + "px"
box.style.transform = "rotateX(" + (midY * 0.35) + "deg) rotateY(" + (midX * 0.35) + "deg)"
//box.style.transform = "rotateY(" + (midX * 0.4) + "deg)"
})
gradient.js
var angle = -20, color = "#2b2b2b", colors = "#000", font = "rgba(102, 102, 102, .3)", shadow = "4px 4px 40px #000";
var changeBackground = function() {
angle = angle + .3
document.body.style.backgroundImage = "linear-gradient(" + angle + "deg, " + colors + ", " + color + ", " + colors + ", " + color + ", " + colors + ", " + color + ", " + colors + ", " + color + ", " + colors + ", " + color + ", " + colors + ", " + color;
requestAnimationFrame(changeBackground)
}
var changeFont = function() {
document.querySelectorAll('li').forEach(li => li.style.color = font);
}
var changeShadow = function() {
document.querySelectorAll('li').forEach(li => li.style.textShadow = shadow);
}
changeBackground()
changeFont()
changeShadow();
document.querySelector('#myBtn').addEventListener('click', function () {
color = (color != "#2b2b2b") ? "#2b2b2b" : "#f1f9d4";
colors = (colors != "#000") ? "#000" : "#759ef3";
font = (font != "rgba(102, 102, 102, .3)") ? "rgba(102, 102, 102, .3)" : "rgba(178, 117, 164, .3)";
shadow = (shadow != "4px 4px 40px #000") ? "4px 4px 40px #000" : "4px 4px 40px #fff";
changeFont()
changeShadow();
})
rotate-type.js
document.addEventListener("mousemove", function (event) {
const x = event.pageX
const y = event.pageY
const midX = x - window.innerWidth / 2
const midY = y - window.innerHeight / 2
const type = document.querySelector('.main')
//box.style.left = x + "px"
//box.style.top = y + "px"
type.style.transform = "rotateX(" + (midX * 0.009) + "deg) rotateY(" + (midY * 0.009) + "deg)"
//box.style.transform = "rotateY(" + (midX * 0.4) + "deg)"
})
transition.js (the modal)
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var button = document.getElementById("myButton");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
button.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}

How to properly animate a bar gliding?

I have two buttons, when a user clicks on them it gets underlined. However, I'd like the .underline to be animated/glide horizontally to the button that is being clicked on.
Demo: https://jsfiddle.net/ds1wr736/11/
As of right now, the .underline just appears and disapears when a button is clicked. How can I animate this to smoothly glide (x values changing) to the selected button without hacks and JQuery?
function switchTab(tab) {
if (tab === 1) {
document.getElementById("tab2").classList.add("underline");
document.getElementById("tab1").classList.remove("underline");
}
else if (tab === 2) {
document.getElementById("tab1").classList.add("underline");
document.getElementById("tab2").classList.remove("underline");
}
}
.bar {
background-color: gray;
padding: 20px;
}
.underline {
border-bottom: 5px solid red;
}
button {
width: 100px;
height: 50px;
background-color: white;
}
button:focus {
outline: none;
}
<div class="bar">
<button id='tab1' class="underline" onclick='switchTab(2)'>Tab 1</button>
<button id='tab2' onclick='switchTab(1)'>Tab 2</button>
</div>
Rather than animating a border I've created an additional element that reacts to the the click events. This allows us to track the position of the "underline" and scale and animate it between buttons when clicked.
This can be modified to accept hover events instead using mouseover instead of click.
let buttons = document.querySelectorAll('button');
buttons.forEach(button => {
button.addEventListener('mouseover', hoverboard); // Hover event
//button.addEventListener('click', hoverboard);
});
function hoverboard(e) {
const board = document.querySelector('.hoverboard');
// - 1 due to the border of the button
let width = this.offsetWidth - 1;
const firstChild = document.querySelector('.bar button:first-child');
const lastChild = document.querySelector('.bar button:last-child');
// - 19 due to padding being 20px on the left and removing 1 for the button's border
let left = this.offsetLeft - 19;
board.style.cssText = 'transform: translateX(' + left + 'px); width: ' + width + 'px;';
}
.bar {
position: relative;
background-color: gray;
padding: 20px;
}
.underline {
border-bottom: 5px solid red;
}
button {
width: 100px;
height: 50px;
background-color: white;
}
button:focus {
outline: none;
}
.hoverboard {
position: absolute;
width: 100px;
height: 3px;
background: red;
transition: transform .25s ease, width .25s ease;
}
<div class="bar">
<button id='tab1'>Tab 1</button>
<button id='tab2' style="width: 65px;">Tab 2</button>
<button>Tab 3</button>
<div class="hoverboard"></div>
</div>
Here ya go. Only the edited classes are here:
.underline:after {
border-bottom: 5px solid red;
animation-name: slideIn;
animation-duration: 1s;
width: 100%;
content: '';
position: absolute;
bottom: 0;
left: 0;
}
#keyframes slideIn {
from {width: 0;}
to {width: 100%;}
}
button{
position: relative;
width: 100px;
height: 50px;
background-color: white;
}
What I did is that I used the abstract after element on the buttons and positioned it absolute to it's relative button. And used css animation.

Categories

Resources