Custom div as cursor creates problems with the hover on links - javascript

I've a problem with a custom cursor created with an absolute div, with my test I realized that the custom div is directly positioned under the default cursor, then if I go hover a link I can't process my JS "mouseenter" because the default cursor is always hover only to the custom cursor... there is a way to fix it?
<div class="custom-cursor"></div>
Scss:
.custom-cursor {
width: 20px;
height: 20px;
border: 2px solid orange;
position: absolute;
z-index: 1080;
border-radius: 50%;
transition-duration: 100ms;
transition-timing-function: ease-out;
box-shadow: 0 0 0 2px black;
&.hover {
width: 40px;
height: 40px;
background: rgba(#FFCC00,.5);
}
}
Vanilla JS:
const cursor = document.querySelector('.custom-cursor');
// Custom cursor follow the default cursor
document.addEventListener('mousemove', e => {
cursor.setAttribute('style', 'top: '+(e.pageY - 10)+'px; left: ' +(e.pageX - 10)+'px;')
});
const links = document.querySelectorAll('a');
// Custom cursor change style on hover links
for(let x of links) {
x.addEventListener('mousenter', () => {
cursor.classList.add('hover');
});
x.addEventListener('mouseleave', () => {
cursor.classList.remove('hover');
});
});

You can enable clicking through elements by adding pointer-events: none; to your CSS
.custom-cursor {
pointer-events: none; /*don't interact with this div*/
width: 20px;
height: 20px;
border: 2px solid orange;
position: absolute;
z-index: 1080;
border-radius: 50%;
transition-duration: 100ms;
transition-timing-function: ease-out;
box-shadow: 0 0 0 2px black;
&.hover {
width: 40px;
height: 40px;
background: rgba(#FFCC00,.5);
}
}

You can use pointer-events: none; for the cursor-div - so that the hover event goes through. (you also forgot an e in "mouseenter"
Working example:
const cursor = document.querySelector('.custom-cursor');
// Custom cursor follow the default cursor
document.addEventListener('mousemove', e => {
cursor.setAttribute('style', 'top: '+(e.pageY - 10)+'px; left: ' +(e.pageX - 10)+'px;')
});
const links = document.querySelectorAll('a');
// Custom cursor change style on hover links
for(let x of links) {
x.addEventListener('mouseenter', () => {
cursor.classList.add('hover');
});
x.addEventListener('mouseleave', () => {
cursor.classList.remove('hover');
});
}
.custom-cursor {
width: 20px;
height: 20px;
border: 2px solid orange;
position: absolute;
border-radius: 50%;
transition-duration: 100ms;
transition-timing-function: ease-out;
box-shadow: 0 0 0 2px black;
pointer-events: none;
}
.custom-cursor.hover {
width: 40px;
height: 40px;
background: rgba(#FFCC00,.5);
}
<div class="custom-cursor"></div>
troet
quak
miau

Related

Dropdown menu instead of list ( mapplic plugin )

I am trying to change a menu from a list to a dropdown.
I am using the Mapplic - Custom Interactive Map WordPress Plugin
I found the code for it, but I don't seem to get it to
this.addLevelSwitcher = function() {
if (self.data.levels.length > 1) {
var control = $('<div></div>').addClass('mapplic-level-switcher');
self.data.levels.forEach(function(level, i) {
var button = $('<button></button>').attr('data-level', level.id).text(level.title).prependTo(control).click(function(e) {
e.preventDefault();
self.switchLevel(level.id);
});
if (level.show) button.addClass('mapplic-selected');
});
this.el.append(control);
self.el.on('levelswitched', function(e, target) {
$('button', control).removeClass('mapplic-selected');
$('button[data-level="' + target + '"]', control).addClass('mapplic-selected');
});
}
}
Also here is the css
/* new switcher */
.mapplic-level-switcher {
position: absolute;
right: 0;
top: 0px;
margin: 12px;
}
.mapplic-level-switcher button {
background-color: #f8f8f8;
border-radius: 0;
color: #888;
cursor: pointer;
display: block;
font-size: 11px;
font-weight: 600;
line-height: 20px;
padding: 4px 10px;
text-align: center;
user-select: none;
width: 100%;
border: none;
transition: transform 0.2s;
position: relative;
}
.mapplic-level-switcher button:hover { background-color: #f8f8f8; }
.mapplic-level-switcher button:focus { outline: none; }
.mapplic-level-switcher button.mapplic-selected {
box-shadow: 0 0 12px rgba(0, 0, 0, 0.06);
background-color: #fff;
color: #222;
transform: scale(1.15);
z-index: 100;
}
I am trying to make it more responsive on mobile...
Another thing I was thinking was to hide this menu on mobile and add indiviuals buttons in order to trigger the floor plan.
Any ideas on how could I do any of this?
Thanks

Scroll to top function stuck once activated(mobile)

Hello, I'm currently practicing coding my own site, but i've ran into a problem. I added an auto fade in scroll to top button which works fine on desktop, but on mobile once it's activated the scroll gets stuck at the top. Any idea whats causing it to get stuck, here is my coding.
Sorry in advanced, im very new to this.
The Script
<script>
const scrollTop = function () {
// create HTML button element
const scrollBtn = document.createElement("button");
scrollBtn.innerHTML = "↑";
scrollBtn.setAttribute("id", "scroll-btn");
document.body.appendChild(scrollBtn);
// hide/show button based on scroll distance
const scrollBtnDisplay = function () {
window.scrollY > window.innerHeight
? scrollBtn.classList.add("show")
: scrollBtn.classList.remove("show");
};
window.addEventListener("scroll", scrollBtnDisplay);
// scroll to top when button clicked
const scrollWindow = function () {
if (window.scrollY != 0) {
setTimeout(function () {
window.scrollTo(0, window.scrollY - 50);
scrollWindow();
}, 10);
}
};
scrollBtn.addEventListener("click", scrollWindow);
};
scrollTop(); scrollTop: scrolled;
</script>
</body>
</html>
</head>
</html>
CSS
section::after {
content: "";
display: table;
clear: both;
}
#scroll-btn {
opacity: 0;
width: 60px;
height: 60px;
color: #fff;
background-color: #c066c0;
position: fixed;
bottom: 10%;
right: 10%;
border: 2px solid #fff;
border-radius: 50%;
font: bold 40px monospace;
transition: opacity 0.5s, transform 0.5s;
overflow: hidden;
}
#scroll-btn.show {
opacity: 1;
transition: opacity 1s, transform 1s;
overflow: hidden;
}
Can anyone tell what the problem is?? Thanks so much!
A simple example of scroll to top
const scrollToTop = document.querySelector(".scroll-to-top");
window.addEventListener("scroll", () => {
if (window.scrollY > 200) {
scrollToTop.classList.add("visible");
} else {
scrollToTop.classList.remove("visible");
}
});
scrollToTop.addEventListener("click", () => {
window.scroll({
top: 0,
left: 0,
behavior: "smooth"
});
});
#import "https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css";
body {
height: 200vh;
}
.scroll-to-top {
--size: 48px;
position: fixed;
border: 0;
right: 32px;
bottom: 32px;
z-index: 9999;
display: grid;
border-radius: 50%;
width: var(--size);
place-items: center;
height: var(--size);
aspect-ratio: 1/1;
transform: scale(0);
will-change: transform;
background-color: white;
transition: transform 250ms ease;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.15);
}
.scroll-to-top svg {
width: 24px;
height: 24px;
pointer-events: none;
}
.scroll-to-top.visible {
transform: scale(1);
}
<button class="scroll-to-top">
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
<path d="M448 368L256 144 64 368h384z" />
</svg>
</button>

Toggle button animation

I have a toggle button to switch the website background color from black to white (and vice versa). It works ok, but I want the slider to move slowly (in 1 second, not instantly) when I click on it. The code:
var change = function() {
var backgr = document.body,
slider = document.getElementById('slider');
if (backgr.style.backgroundColor == 'white') {
backgr.style.backgroundColor = 'black';
slider.style.float = 'right';
} else {
backgr.style.backgroundColor = 'white';
slider.style.float = 'left';
}
}
body {
background-color: black;
}
#toggle {
width: 30px;
height: 16px;
background-color: orange;
padding: 0;
border: none;
border-radius: 16px;
}
#slider {
width: 14px;
height: 14px;
background-color: white;
margin: 1px;
border-radius: 50%;
float: right;
}
<button id='toggle' onclick="change()">
<span id='slider'></span>
</button>
Not sure if you have to animate the background-color or the button so I have animated both with a CSS transition, so keep just what you need.
For the button I've simply changed the margin-right (via calc()) keeping the float: right (which it can't be animated)
Also the JS part is simplified: toggling a class on the body element is enough and you can keep off your style from Javascript so as a result your code is more mantainable.
var body = document.body;
var change = function() {
body.classList.toggle('active');
}
body {
background-color: black;
transition: background-color 1s;
}
body.active {
background-color: white;
}
#toggle {
width: 30px;
height: 16px;
background-color: orange;
padding: 0;
border: none;
border-radius: 16px;
}
#slider {
width: 14px;
height: 14px;
background-color: white;
margin: 1px;
transition: margin 1s;
border-radius: 50%;
float: right;
}
.active #slider {
margin-right: calc(100% - 15px);
}
<button id='toggle' onclick="change()">
<span id='slider'></span>
</button>
Rather than using a button, I'd reskin a checkbox like this. This is handy as it keeps track of its own boolean value.
Then based on whether or not it's checked you can do whatever.
Below I've used transform and transition to animate the sliding you can see this in the CSS.
function toggleChange(e) {
let bodyStyle = document.querySelector('body').style;
if (e.target.checked) {
bodyStyle.background = "#000";
} else {
bodyStyle.background = "#FFF";
}
}
.switch[type=checkbox] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
width: 30px;
height: 16px;
background-color: orange;
border-radius: 16px;
}
.switch[type=checkbox]::after {
content: '';
position: absolute;
background: #FFF;
transition: all .2s ease-in-out;
border-radius: 7px;
width: 14px;
height: 14px;
margin: 1px;
}
.switch[type=checkbox]:checked::after {
transform: translateX(14px);
}
<input type="checkbox" onchange="toggleChange(event)" class="switch" />
I hope this is helpful.
Use transition: left 1000ms ease;
and position: relative;
Then change the left property in the script instead of changing float:
var change = function() {
var backgr = document.body,
slider = document.getElementById('slider');
if (backgr.style.backgroundColor == 'white') {
backgr.style.backgroundColor = 'black';
slider.style.left = 0; // NEW LINE
} else {
backgr.style.backgroundColor = 'white';
slider.style.left = "15px"; // NEW LINE
}
}
body {
background-color: black;
}
#toggle {
width: 30px;
height: 16px;
background-color: orange;
padding: 0;
border: none;
border-radius: 16px;
}
#slider {
width: 14px;
height: 14px;
background-color: white;
margin: 1px;
border-radius: 50%;
float: left; /* NEW LINE */
position: relative; /* NEW LINE */
transition: left 1000ms ease; /* NEW LINE */
left: 0; /* NEW LINE */
}
<button id='toggle' onclick="change()">
<span id='slider'></span>
</button>
Instead of float, I think you should use css that can by used with transition. if you place your sldier with a position for example, you can add a transition on the position with a 1sec duration and it will works as you want

Pure CSS Checkbox with JS toggle not working

Searched all over the internet, and I can't beat this issue.
I have a pricing section with a pricing plan switch. The logic itself is working fine, however, the CSS checkbox toggle itself isn't switching from left to right.
I assume it has to do with the CSS itself or the way I select the elements with JS. I've also read some topics on SO where they say that it's a checkbox issue with WordPress, didn't find my answer there, unfortunately.
The issue
On Chrome desktop, the CSS checkbox toggle isn't working.
On Safari, iPhone X the CSS checkbox switch checkbox does work but only if you click the label elements with text
Here's a link to the page
Link to Dropbox of me demonstrating the issue on iPhone
window.onload = function() {
var e = document.getElementById("firstPlan"),
d = document.getElementById("secondPlan"),
t = document.getElementById("switcher_iOS"),
m = document.getElementById("firstPlan_box"),
y = document.getElementById("secondPlan_box");
if (document.getElementById("switcher_iOS") == null) {
var node = document.createElement("input");
node.id = "switcher_iOS";
node.type = "checkbox";
node.className = "toggle_iOS--check";
var elm = document.getElementsByClassName('toggle_iOS')[0];
elm.insertBefore(node, elm.firstChild)
t = document.getElementById("switcher_iOS");
}
e.addEventListener("click", function() {
t.checked = false;
e.classList.add("togglePricing--is-active");
d.classList.remove("togglePricing--is-active");
m.classList.remove("hide");
y.classList.add("hide");
});
d.addEventListener("click", function() {
t.checked = true;
d.classList.add("togglePricing--is-active");
e.classList.remove("togglePricing--is-active");
m.classList.add("hide");
y.classList.remove("hide");
});
t.addEventListener("click", function() {
d.classList.toggle("togglePricing--is-active");
e.classList.toggle("togglePricing--is-active");
m.classList.toggle("hide");
y.classList.toggle("hide");
t.checked = !t.checked;
})
}
/* Toggle */
#switcher_iOS {
width: 100%;
}
.toggle_iOS,
.togglePricing {
display: inline-block;
vertical-align: middle;
margin: 10px;
}
.togglePricing {
color: #ccc9c9;
cursor: pointer;
transition: .1s;
font-weight: bold;
font-size: 17px;
}
.togglePricing--is-active {
color: #181818;
}
.toggle_iOS {
position: relative;
width: 58px;
height: 28px;
border-radius: 100px;
background-color: #1D8BF1;
overflow: hidden;
box-shadow: inset 0 0 2px 1px rgba(0, 0, 0, 0.05);
}
.toggle_iOS--check {
position: absolute;
display: block;
cursor: pointer;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 6;
}
.toggle_iOS--check:checked~.toggle_iOS--switch {
right: 2px;
left: 57.5%;
transition: 0.15s cubic-bezier(0.785, 0.135, 0.15, 0.86);
transition-property: left, right;
transition-delay: .01s, 0s;
}
.toggle_iOS--switch {
position: absolute;
left: 2px;
top: 2px;
cursor: pointer;
bottom: 2px;
right: 57.5%;
background-color: #fff;
border-radius: 36px;
z-index: 1;
transition: 0.15s cubic-bezier(0.785, 0.135, 0.15, 0.86);
transition-property: left, right;
transition-delay: 0s, .01s;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
<label class="togglePricing togglePricing--is-active" id="firstPlan">Payment Plan</label>
<div class="toggle_iOS">
<label for="switcher_iOS"><input type="checkbox" onclick="void(0);" id="switcher_iOS" class="toggle_iOS--check" checked></label><b onclick="void(0);" class="toggle_iOS--switch"></b>
</div>
<label class="togglePricing" id="secondPlan">One Payment</label>
I have simplified your css, and in order for this to work, you have to remove your JS that reset the state of the checkbox from the checkbox on click event such as
t.checked = !t.checked;
var t = document.getElementById("switcher_iOS");
t.addEventListener("click", function(){
console.log("i am", this.checked);
})
.toggle_iOS{
position: relative;
width: 58px;
height: 28px;
border-radius: 100px;
background-color: #1D8BF1;
overflow: hidden;
box-shadow: inset 0 0 2px 1px rgba(0,0,0,0.05);
}
.toggle_iOS--switch{
position: absolute;
left: 2px;
top: 2px;
cursor: pointer;
bottom: 2px;
right: 57.5%;
background-color: #fff;
border-radius: 36px;
z-index: 1;
transition: 0.15s cubic-bezier(0.785,0.135,0.15,0.86);
transition-property: left,right;
transition-delay: 0s,.01s;
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
[type=checkbox]:checked + .toggle_iOS--switch{
left: 57.5%;
right: 2px;
}
.toggle_iOS [type=checkbox]{
position: absolute;
display: block;
cursor: pointer;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 6;
}
<div class="toggle_iOS">
<input type="checkbox" id="switcher_iOS">
<div class="toggle_iOS--switch"></div>
</div>

Make arrow in button point down after menu slides out

I have a button that has an arrow appended to it when a user hovers over it. When clicked, a content div slides out in its wrapper using jQuery.slideToggle().
Once the div slides out, I want to make the arrow in the button rotate 180 degrees to signify that pressing it will make the content div go down if clicked again.
I made a JsFiddle to show what I have so far: https://jsfiddle.net/414mwv17/
What would be the best way to make the arrow point down after the button is clicked?
Create a new class for how you want the carat to appear :
#makeGroupButton span.rotate:after
{
transition: opacity 0.5s, top 0.5s, right 0.5s;
transform: rotate(135deg);
}
Note the class addition in the selector.
Then change the javascript/jQuery to just toggle that class:
$('#makeGroupButton').bind('click', function(){
$('#slideout').slideToggle(500);
$(this).children('span').toggleClass('rotate');
});
You can't directly select the :after and :before pseudo selectors with jQuery, so just changing the class, and adding CSS is customarily the easiest method.
Updated fiddle
Have started it for you to build on. Check this out and let me know your feedback. Thanks!
Added the following style:
#makeGroupButton span.open:after {
border: 3px solid #FFF;
border-top: none;
border-right: none;
margin-top: -15px;
}
and some js too:
$('#makeGroupButton').bind('click', function(event) {
event.preventDefault();
$('#slideout').slideToggle(500);
$(this).find('span').toggleClass('open');
});
#wrapper{
height: 500px;
width: 300px;
position:relative;
border: 2px solid blue;
}
#slideout {
height: 95%;
width: 95%;
border: 2px solid red;
position: absolute;
bottom: 0;
left: 2.5%;
}
#makeGroupButton
{
clear: both;
text-align: center;
color: white;
width: 220px;
background:black;
overflow: hidden;
transition: all 0.5s;
}
#makeGroupButton:hover, #makeGroupButton:active
{
text-decoration: none;
background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
}
#makeGroupButton span
{
display: inline-block;
position: relative;
padding-right: 0;
transition: padding-right 0.5s;
}
#makeGroupButton span:after
{
content: '';
position: absolute;
top: 0;
right: -20px;
opacity: 0;
width: 15px;
height: 15px;
margin-top: -5px;
background: rgba(0, 0, 0, 0);
border: 3px solid #FFF;
border-bottom: none;
border-left: none;
transition: opacity 0.5s, top 0.5s, right 0.5s;
transform: rotate(-45deg);
}
#makeGroupButton:hover span, #makeGroupButton:active span
{
padding-right: 30px;
}
#makeGroupButton:hover span:after, #makeGroupButton:active span:after
{
transition: opacity 0.5s, top 0.5s, right 0.5s;
opacity: 1;
border-color: white;
right: 0;
top: 50%;
}
#makeGroupButton span.open:after {
border: 3px solid #FFF;
border-top: none;
border-right: none;
margin-top: -15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="slideout" style="display: none;"></div>
</div>
<a href="#" id="makeGroupButton">
<span>New Group</span>
</a>
I would add a class rotate on click then apply the following css :
#makeGroupButton.rotate span:after {
top: 0px;
-webkit-transform: rotate(-228deg) !important;
}
I have update your js fiddle https://jsfiddle.net/414mwv17/2/.
A much cleaner way to do it would be use an arrow icon then just rotate that icon by 180 degrees.
Hope this helps

Categories

Resources