Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I try to make this effect using css.
This is the effect:
I try to make div that:
div {
height: 300px;
width: 10px;
position: absolute;
border-radius: 0px 500px 500px 0;
-moz-border-radius: 0px 500px 500px 0;
-webkit-border-radius: 0px 500px 500px 0;
background-color: grey;
opacity:0.1;
}
and then by css change the width of this effect.But it look very ugly it more square then circle and also I the change in the width dont make it become like the effect. it looks like the shape become bigger in width but not become more circle...
How can I make this effect by css/js ? everything that I tried with the div look very bad.
Thanks.
The effect is a little tricky because of its shape. The key is that the circle that you are creating with the div has to be moved mostly off screen to get a curve that aligns more with the example you gave.
.container .effect{
position:absolute;
width:200px;
height:80%;
top:10%;
right:-140px;
background-color:#fff;
border-radius:100% 100% 100% 100%;
transition:width 500ms ease-in-out, right 500ms ease-in-out, opacity 500ms ease-in-out;
opacity:.7;
}
Here is a fiddle with more details. Try turning the overflow:hidden off on the .container element to see more details of whats going on. The JavaScript is just to show the effect happening.
**Side note: the background image is not my own and was used for education purposes. Credit belongs with the original owner.
Just give it a try (Don't forget to emulate touch events in chrome):
var _div = document.getElementById('wrapper');
var _elem = document.getElementById('div');
_div.addEventListener('touchmove', function () {
_elem.style.width = '60px';
});
_div.addEventListener('touchend', function () {
_elem.style.width = '0';
});
*, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#div {
height: 95%;
width: 0;
top: 2.5%;
position: absolute;
border-radius: 0 500px 500px 0;
-moz-border-radius: 0 500px 500px 0;
-webkit-border-radius: 0 500px 500px 0;
background-color: gray;
opacity: 0.1;
-webkit-transition: width .2s; /* Safari */
transition: width .2s;
}
#wrapper {
width: 100%;
height: 100%;
background: darkgreen;
}
<div id="wrapper">
<div id='div'></div>
</div>
Here is another take using pseudo-elements and transforms. When scroll reaches end on both sides, the faux-rubber-banding effect will show up.
Works with mouse scroll to test on non-touch screen desktops. For Chrome, can emulate mouse events to test.
Demo Fiddle: http://jsfiddle.net/abhitalks/v4mLkttL/
Demo Snippet:
var $wrap = $('#wrap'), startX, isDrag = false;
$wrap.on('touchstart', function(e) {
startX = e.originalEvent.touches[0].clientX; isDrag = true;
});
$wrap.on('touchmove', function(e) {
var delta = e.originalEvent.changedTouches[0].clientX - startX,
pos = $(this).scrollLeft(), w = $(this).width(),
iw = $(this).innerWidth(), sh = this.scrollWidth
;
if (isDrag) {
if ((delta > 0) && (pos <= 0)) {
$wrap.addClass('rubberLeft');
isDrag = false; e.preventDefault();
}
if ((delta < 0) && (pos + iw >= sh)) {
$wrap.addClass('rubberRight');
isDrag = false; e.preventDefault();
}
}
});
$wrap.on('touchend', function(e) {
isDrag = false; clearRubber();
});
$wrap.on('mousewheel DOMMouseScroll', function(e) {
var start = e.originalEvent,
delta = start.wheelDelta || -start.detail,
pos = $(this).scrollLeft(), w = $(this).width(),
iw = $(this).innerWidth(), sh = this.scrollWidth
;
this.scrollLeft += delta * -1;
if (pos <= 0) { $wrap.addClass('rubberLeft'); setTimeout(clearRubber, 600); }
else if (pos + iw >= sh) { $wrap.addClass('rubberRight'); setTimeout(clearRubber, 600); }
else { clearRubber(); }
e.preventDefault();
});
function clearRubber() { $wrap.removeClass('rubberLeft').removeClass('rubberRight'); }
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body { height: 100vh; width: 100vw; overflow: hidden; }
#wrap {
min-width: 100vw; height: 100vh;
overflow-y: hidden; overflow-x: scroll;
background-color: #000; white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
#wrap img { display: inline-block; vertical-align: top; }
#wrap::before, #wrap::after {
content: ''; display: block;
position: absolute; top: 4%;
width: 100px; height: 90%;
background-color: rgba(255,255,255,0.6);
box-shadow: 0 0 10px 4px rgba(0,0,0,0.5);
border-radius: 50%; transform: translateX(0px);
transition: transform 0.5s;
}
#wrap::before { left: -105px; }
#wrap::after { right: -105px; }
#wrap.rubberLeft::before { transform: translateX(45px); }
#wrap.rubberRight::after { transform: translateX(-45px); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrap">
<img class="page" src='//lorempixel.com/240/320' />
<img class="page" src='//lorempixel.com/241/320' />
<img class="page" src='//lorempixel.com/239/320' />
<img class="page" src='//lorempixel.com/240/320' />
<img class="page" src='//lorempixel.com/241/320' />
<img class="page" src='//lorempixel.com/239/320' />
</div>
Related
I have a small scroll effect which simulate that a logo will disappear if a lower div will scroll over it.
Currently I'm checking if two divs are intersecting. If this is true, then the height of the div of the logo will decrease with the scroll position of the div beneath.
Unfortunately, my demo is not foolproof and some fragments of the logo are still visible.
Is there a way to do this jank-free? Maybe with requestAnimationFrame?
function elementsOverlap(el1, el2) {
const domRect1 = el1.getBoundingClientRect();
const domRect2 = el2.getBoundingClientRect();
return !(
domRect1.top > domRect2.bottom ||
domRect1.right < domRect2.left ||
domRect1.bottom < domRect2.top ||
domRect1.left > domRect2.right
);
}
const el1 = document.querySelector(".logo");
const el2 = document.querySelector(".clickblocks");
let scrollPositionEl2;
let heightDifference;
const logoHeight = el1.offsetHeight;
document.addEventListener("DOMContentLoaded", () => {
var scrollDirectionDown;
scrollDirectionDown = true;
window.addEventListener("scroll", () => {
if (this.oldScroll > this.scrollY) {
scrollDirectionDown = false;
} else {
scrollDirectionDown = true;
}
this.oldScroll = this.scrollY;
// test
if (scrollDirectionDown) {
if (elementsOverlap(el1, el2) === true) {
scrollPositionEl2 = el2.getBoundingClientRect().top;
heightDifference = logoHeight - scrollPositionEl2 + 100;
//console.log(logoHeight - heightDifference);
el1.style.height = `${logoHeight - heightDifference}px`;
}
} else {
//scrolling up
scrollPositionEl2 = el2.getBoundingClientRect().top - 100;
el1.style.height = `${scrollPositionEl2}px`;
//console.log(logoHeight);
}
});
});
#import url("https://fonts.googleapis.com/css2?family=Inter:wght#900&display=swap");
.wrapper {
max-width: 100vw;
margin: 0 auto;
background-image: url("https://picsum.photos/1920/1080");
background-size: cover;
background-attachment: fixed;
height: 1200px;
position: relative;
&::after {
content: "";
position: absolute;
background: rgba(0, 0, 0, 0.3);
width: 100%;
height: 100%;
inset: 0;
}
}
body {
margin: 0;
}
main {
width: 100%;
height: 100vh;
position: relative;
z-index: 1;
}
.clickblocks {
width: 100%;
height: 200px;
display: grid;
grid-template-columns: repeat(12, (minmax(0, 1fr)));
}
.clickblock {
transition: all ease-in-out 0.2s;
backdrop-filter: blur(0px);
border: 1px solid #fff;
height: 100%;
grid-column: span 6 / span 6;
font-size: 54px;
font-weight: 700;
padding: 24px;
font-family: "Inter", sans-serif;
color: white;
text-transform: uppercase;
&:hover {
backdrop-filter: blur(10px);
}
}
.logo {
background: url("https://svgshare.com/i/ivR.svg");
width: 100%;
background-repeat: no-repeat;
background-position: top;
position: fixed;
top: 100px;
}
.logo-wrapper {
position: relative;
}
<div class="wrapper">
<main>
<div class="logo-wrapper" style="height: 390px">
<div class="logo" style="height: 300px">
</div>
</div>
<div class="clickblocks">
<div class="clickblock">
Some Content
</div>
</div>
</main>
</div>
Few things here to optimize your performance.
getBoundingClientRect() is a rather expensive calculation. If there are NO other options it's fine.
The Intersection Observer API is a lot more performant, and you can set the root element on the API. Then observe the element that is moving. This should be able to telly you if their are colliding.
Whenever you do scroll based logic, you should really try and throttle the logic so that the scroll any fires ever 16.6ms. That will reduce the number of times the calculations are made, and speed things up on the FE.
Learn how to use Google Chrome's performance tab. It can be overwhelming at first, but it gives you the ability to drill into the exact piece of code that's slowing your site down.
Learn about JS's event loop, and what's really going on under the hood. This video by Jake Archibald really help me understand it.
Hope this helped, sorry that I didn't give you an actual solution.
Hey I have an inline javascript code that adds a class to an element and makes it slide up in the screen. But it suddenly stopped working and I don't know why. Here's the HTMl and JS:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 400) {
$(".converter").addClass("atcbottomactive");
} else {
$(".converter").removeClass("atcbottomactive");
}
});
.converter {
position: fixed;
height: 60px;
width: 100%;
bottom: -200;
background: #eeeeee;
transition: 1s;
z-index: 10000;
}
.ccontent {
display: inline-flex;
width: 100%;
padding: 10px 5%;
}
.atcbottomactive{
bottom:0;
transition: 1s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="background: green; height: 1500px; width: 100%;"></div>
<div class="converter"><div class="ccontent">...</div></div>
Here's the link
Thanks in advance :)
In fact, trying to use it without including JQuery gives you the error. You can solve this easily with "JavaScript" without using jQuery.
var element = document.querySelector(".converter");
window.addEventListener('scroll', function() {
var scroll = window.pageYOffset || document.documentElement.scrollTop;
if (scroll >= 400) {
element.classList.add("atcbottomactive");
} else {
element.classList.remove("atcbottomactive");
}
});
.converter {
padding: 20px 20px 200%;
background: blue;
color: white;
}
.converter.atcbottomactive {
background: green;
}
<div class="converter">
<div class="ccontent">Scroll me: 400px</div>
</div>
I'm using 'mouseenter' and 'mouseleave' to change the visibility of an image when I enter and leave an element. My issue is these events keep firing even when I'm within the element. Using 'pointer-events = none' works but it turns off another animation I have on the image. Is there a solution to this that either doesn't use pointer-events nor mousenter/leave and allows me to have animations on my image? DEMO
HTML:
<img id="image" src=""/>
<div id='box' class="box"></div>
CSS:
.box {
border: 2px solid red;
height: 400px;
width: 60%;
margin: 10px auto;
}
#image {
position:absolute;
width: 60px;
height: 60px;
display: none;
}
JS:
$(document).mousemove(function(e){
const height = $('#image').height() / 2;
const width = $('#image').width() / 2;
$("#image").css({
left:e.pageX-width,
top:e.pageY-height
});
});
$('.box').mouseenter(_=> {
$('#image').show();
});
$('.box').mouseleave(_=> {
$('#image').hide();
});
I'm not sure if this accomplishes what you're looking for - but you could change the z-index of the image and the background of the parent container, like:
$(document).mousemove(function(e){
const height = $('#image').height() / 2;
const width = $('#image').width() / 2;
$("#image").css({
left:e.pageX-width,
top:e.pageY-height
});
});
let entries = 0;
let exits = 0
$('.box').mouseenter(_=> {
$('#image').show();
entries += 1;
document.getElementById("entries").textContent=entries;
});
$('.box').mouseleave(_=> {
$('#image').hide();
exits += 1;
document.getElementById("exits").textContent=exits;
});
.box {
border: 2px solid red;
height: 400px;
width: 60%;
margin: 10px auto;
background: transparent;
}
#image {
position:absolute;
width: 60px;
height: 60px;
display: none;
z-index: -1;
}
#display {
position: absolute;
top:0;
left: 0;
border: 1px solid black;
width: 100px;
height: 100px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="image" src="https://i5.walmartimages.ca/images/Large/580/6_r/875806_R.jpg"/>
<div id='box' class="box"></div>
<div id= 'display'>
<div id= 'entries'>00</div>
<div id= 'exits'>00</div>
</div>
Which will cause the .box to always be on top, even though the image is under your cursor.
Have you tried maybe setting a value to indicate the current state of the image?
Something like this:
var showImage = false;
$(document).mousemove(function(e){
const height = $('#image').height() / 2;
const width = $('#image').width() / 2;
$("#image").css({
left:e.pageX-width,
top:e.pageY-height
});
});
$('.box').mouseenter(_=> {
if (showImage)
return;
showImage = true;
$('#image').show();
});
$('.box').mouseleave(_=> {
showImage = false;
$('#image').hide();
});
I have created a small demo of two boxes animating in and out based on scroll position. But this isn't exactly what I want to achieve. What I want is for the boxes to animate based on scroll position not just transition in and out when a certain point is reached.
For example the scrolling should control the animation so if you scroll down the boxes will animate in, if you scroll up they will animate out. If you stop scrolling mid animation the animation will stop. If you reverse the scroll position the animation will reverse. So the animation only happens as you scroll.
I hope that is clear enough for you to understand. I will try provide a link to what I am trying to achieve. But for now here's my demo just using a transition to animate the boxes.
jQuery(document).ready(function($){
var scroll_pos = $(window).scrollTop();
var box = $('#container').offset().top - 200;
$(window).on('scroll', function(){
scroll_pos = $(window).scrollTop();
$('p').html(scroll_pos);
if(scroll_pos >= box){
$('#left').addClass('animate');
$('#right').addClass('animate');
}else{
$('#left').removeClass('animate');
$('#right').removeClass('animate');
}
});
});
#container{
width: 600px;
height: 300px;
margin: 1000px auto;
overflow: hidden;
font-size: 0;
}
#left{
width: 55%;
height: 300px;
background-color: blue;
display: inline-block;
transform: translateX(-100%);
transition: all 0.5s;
}
#right{
width: 45%;
height: 300px;
background-color: yellow;
display: inline-block;
transform: translateX(100%);
transition: all 0.5s;
}
#left.animate{
transform: translateX(0%);
}
#right.animate{
transform: translateX(0%);
}
p{
position: fixed;
top: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<p></p>
<div id="container">
<div id="left"></div>
<div id="right"></div>
</div>
Here's an example of what I want to achieve. As you can see the scroll controls the animation of the fidget spinner https://ampbyexample.com/visual_effects/basics_of_scrollbound_effects/
Based on this answer you could do someting like:
/**
* inViewport jQuery plugin by Roko C.B.
* http://stackoverflow.com/a/26831113/383904
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
*/
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el) {
function visPx(){
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
// Now our stuff:
var $container = $("#container");
var $left = $("#left");
var $right = $("#right");
$container.inViewport(function( px ) {
var v = 1 - px / $container.height(); // Value from 1.0 to 0.0 and v.versa
$("p").text(v);
$left.css({transform: `translateX(${ -v * 100 }%)`});
$right.css({transform: `translateX(${ v * 100 }%)`});
});
body {
height: 500vh;
}
#container {
position: relative;
margin: 0 auto;
top: 200vh;
overflow: hidden;
width: 60vw;
height: 60vh;
}
#left,
#right {
width: 50%;
height: 100%;
float: left;
}
#left {
background-color: blue;
transform: translateX(-100%);
}
#right {
background-color: yellow;
transform: translateX(100%);
}
p {position: fixed; top:0; left: 0;}
<div id="container">
<div id="left"></div>
<div id="right"></div>
</div>
<p></p>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
I'm trying to develop following functionality for a sidebar. In a nutshell, Sidebar will have 100% height and will be absolutely positioned. Inside it there is content, which should scroll with the page, while sidebar is fixed. And as addition there is a shadow effect / response to show user if he can scroll down or up. So for example if there is something that can be scrolled down / up show shadow there, if not don't show shadow. I made a quick mockup, hopefully it will help you understand what happens if page is scrolled:
I made a quick jsfidle with content and sidebar, this is as far as I can get at the moment. http://jsfiddle.net/cJGVJ/3/
I assume this can't be achieved only with css and html and work cross browser, so jQuery solutions are welcome.
HTML
<div id="main"> <!-- Demo Content (Scroll down for sidebar) -->
<!-- Demo content here -->
</div>
<aside id="sidebar">
<div id="side-content-1"></div>
<div id="side-content-2"></div>
</aside>
CSS
body {
background: #f3f3f3;
margin: 0;
padding: 0;
}
#page-wrapper {
width: 90%;
margin: 0 auto;
overflow: hidden;
}
#sidebar {
width: 30%;
float: left;
background: #ffffff;
padding: 10px;
height: 100%;
position: fixed;
}
#main {
width: 60%;
float: right;
}
#side-content-1, #side-content-2 {
height: 400px;
}
#side-content-1 {
background: red;
opacity: 0.4;
}
#side-content-2 {
background: green;
opacity: 0.4;
margin-top: 10px;
}
EDIT
Bare in mind content in sidebar sums up to less than one of the page content, so once it reaches the bottom (so when bottom shadow disappears) it should stay there, while main content can be still scrolled down.
This is still a little rough, but its a start:
I went through and polished it a little more and took care of some window resizing issues.
I think this will work for you:
Updated Working Example
JS
$(window).scroll(function () {
var y = $(window).scrollTop();
var x = $(window).scrollTop() + $(window).height();
var s = $('#sidebar').height();
var o = $('#side-content-1').offset().top;
var q = $('#side-content-1').offset().top + $('#side-content-1').height();
var u = $('#side-content-2').offset().top;
if (x > s) {
$('#sidebar').css({
'position': 'fixed',
'bottom': '0',
'width': '27%'
});
$('#bottomShadow').hide();
}
if (x < s) {
$('#sidebar').css({
'position': 'static',
'width': '30%'
});
$('#bottomShadow').show();
}
if (y > o) {
$('#topShadow').show().css({
'position': 'fixed',
'top': '-2px'
});
}
if (y < o) {
$('#topShadow').hide();
}
if (y > q - 4 && y < q + 10) {
$('#topShadow').hide();
}
if (x > u - 10 && x < u + 4) {
$('#bottomShadow').hide();
}
});
var shadow = (function () {
$('#topShadow, #bottomShadow').width($('#sidebar').width());
});
$(window).resize(shadow);
$(document).ready(shadow);
CSS
body {
background: #f3f3f3;
margin: 0;
padding: 0;
}
#page-wrapper {
width: 90%;
margin: 0 auto;
overflow: hidden;
}
#sidebar {
width: 30%;
float:left;
background: #ffffff;
padding: 10px;
}
#main {
width: 60%;
float: right;
}
#side-content-1, #side-content-2 {
height: 400px;
}
#side-content-1 {
background: red;
opacity: 0.4;
}
#side-content-2 {
background: green;
opacity: 0.4;
margin-top: 10px;
}
#topShadow {
display:none;
height:2px;
box-shadow:0px 5px 4px #000;
}
#bottomShadow {
position:fixed;
bottom:-3px;
height:2px;
width:99%;
box-shadow:0px -5px 4px #000;
}
CSS Tricks website have an article on Persistent Headers where they accomplish something similar with a bit of JQuery