I don't get why this is happening:
I have:
https://jsfiddle.net/d5jehq02/1
<div class="para_group">
<div class="para_layer para_layer_back">
<h2>background</h2>
</div>
<div class="para_layer para_layer_front">
<h2>forefront</h2>
</div>
</div>
I am trying to create a parallax scrolling effect and although the 2 parent layers (class='para_group') have position='relative', still onr of the child divs - specifically seems to overlap its parent layer...
If you see the example link above, you will realize that the background layer from the 2nd group - seems to overlap the first group all together - when it shouldn't - the group's position is set to relative - therefore block objects (the parent divs) should appear one below the other...
I cannot get my mind around this one :(
The relativity of the conventional html positioning in here is seriously disturbed by the fact that the layer_back elements AND layer_front elements are actually moved into 3d context and scaled.
To achieve the parallax effect, what is done in here is:
Setting 1px perspective (camera set 1px away from the rendering plane).
.parallax {
perspective: 1px;
}
Moving the background layers 1px deeper into the field of view while at the same time scaling them to be twice as large.
.para_layer_back {
transform: translateZ(-1px) scale(2);
}
^ This is the heart of the parallax effect, as moving the elements 1px deeper when we have perspective set at 1px, positions the elements twice as far from the camera as the front layers which are translateZ'd by 0. This produces the parallax effect while scrolling, but also makes the elements appear smaller, because they're further away (the perspective effect).
That's why they are scale(2)'d so they appear in their original size.
Thing is, they're moved away from the camera without changing their relative positions (they're right next to each other then), and then they're scaled in-place, the scale operation having transform-origin set at their centers, makes them get larger and overlap each other.
What you could do to solve the problem is to work on first moving them away from each other before scaling them.
Take a look at the forked and updated fiddle where I've removed the "scale(2)" part on the back layers, they are in the back, and they are positioned properly (without overlapping).
http://jsfiddle.net/3x150vsx/1/
.para_layer_back {
transform: translateZ(-1px) scale(1);
}
The solution to your problem lies in moving them away from each other before you try to scale them up.
Good luck :>
Related
I want a cool scrolling effect on my website like this:
There are two background images that scroll much slower than the rest of the page, divided by another element with a higher z-index value and unmodified scroll speed.
I have managed to do so in Firefox using 3d transform and overflow: hidden (as you can see, the two background images do not overlap). Here's the significant part of the code:
HTML:
<div class="container-container">
<div class="container">
<div class="slow-scroll">
<img src="...">
</div>
</div>
</div>
CSS:
.container-container {
perspective: 100px;
}
.container {
transform-style: preserve-3d;
overflow: hidden;
}
.slow-scroll {
transform: translateZ(-900px) scale(10.5);
}
My intention was to do the same as in the GIF - have a container with regular scroll speed that would contain the slower scrolling background, so that the overflow could be hidden, thus making it impossible for the two background images to overlap.
However, this doesn't work for Chrome or Microsoft Edge - the background images act as if the translateZ() value was absent (the scale still works normally though). This happens if I set overflow: hidden to any value except initial, revert, or unset.
Can this be fixed? Is there a workaround?
Note: I have looked around and saw this question, but it's outdated and the accepted answer does not work for me.
Based on your description, and the sample images provided, I think what you're looking for is a parallax scrolling effect. Simply refer to this tutorial below, which contains a simple example. I think it will help you.
How TO - Parallax Scrolling
Edit:
And according to your description, you mentioned that translateZ() not work in Edge, I created a simple demo and tested it, and I found it works normally in Edge(version 97.0.1072.55). I think maybe there is some problem with the code, such as this line:
transform: transform: translateZ(-900px) scale(10.5);
And if you want to implement this requirement, you could try to create multiple layers and set different translateZ() values for them. Simply refer to this example: Pure CSS Parallax Websites - Demo3
Basically, I'd like to understand how the effect with the vertically scrolling, but overlapping images on the amazing Beolit 15 works.
What I found out so far is that they use a container div which again contains four divs that are positioned absolutely to the upper left corner of the container. So far, so good. Apart from that, the four divs all have the same size, feature a background-image that is sized as cover, and have different z-index values to make sure that they are in the correct order on top of each other.
Then, what they added is a clip style that always starts in the upper left corner of each of the four divs, always has the same width, but they differ in their vertical length. The top-most is the shortest one, the second-top-most is the second-shortest one, and so on…
So far, I already have two questions:
How do they get the 673px width? Isn't this depending on screen resolution? Why is it exactly this value?
How did they get the height of teach of the clipping rectangles? Why exactly those values? (Of course, because otherwise it wouldn't work, but how did they get those values? I'm sure not by trial and error…)
Now, apart from that, you can see that when you scroll, basically all they do is update the lower border of the clipping rectangle. This way it looks as if they were sliding up, and move above the images, while they stay fixed.
What I do not get here is how they do this. Obviously they have somehow attached to the window.scroll event, but how exactly?
They add a .fixed class to div.images via e.startEngine() once it reaches the top edge of the viewport and remove it via e.stopEngine() when you scrolled through all images. This triggers the following styles:
.focus .images.fixed {
position: fixed;
width: calc(50% - 30px);
}
calc(50% - 30px) is probably the 673px you are searching for.
The style every image gets looks like:
height: 928px;
clip: rect(0px 597px 1856px 0px);
which can be expanded to:
height: [window.innerHeight];
clip: rect(
0px
[window.innerWidth / 2 - 30]
[
this.parentNode.parentNode.offsetTop +
document.querySelector('.inpagenav').offsetHeight +
(window.innerHeight * IMAGENUMBER) -
window.scrollY
]
0px
);
The scroll event is attached via e.Tools.bindEvent(window, "scroll", w) and the function w calls e.Tools.clipY() which sets the clip styles for each image.
I have this:
div {
transform:rotateX(120deg);
}
But when I make the transformation it leaves me a white space over the div. How can I make the div to stay at the top.
Pretty sure you are looking for transform-origin.
Something like transform-origin: 0% 33%; works in your case.
jsFiddle here - play around with it.
By default, the origin is set to 50% 50%.
See MDN documentation.
To change the rotation point of an element, you can use transform-origin.
Browser support is limited, and prefixed, so check in here for some more information:
(it will only work in chrome and safari for 3D transformations like this, I believe)
http://www.w3schools.com/cssref/css3_pr_transform-origin.asp
Here is an example:
http://jsfiddle.net/zAZuY/1/
notice how the second div sticks to the top. Also, take note that a 120 degree rotation will begin to flip your element upside down if the origin point is at the top (you are actually seeing the backside of the element at this point)
Something like:
div {
transform:rotateX(120deg);
transform-origin:top left;
}
Best way to grasp this is to pretend the DIV is a piece of paper and you're sticking a nail onto the top left hand side of the paper. Now since you're flipping the paper on the X axis, it uses the top of the paper as the folding point and turns itself around that area.
Remember to declare both the "webkit" and "ms" versions of "transform" and "transform-origin" in your CSS since the vanilla statements haven't been universally adopted yet.
Can some please explain to me the difference in transitioning the positional left or right properties or the -transform: translateX(n), as the both seem to achieve the same thing yet can be applied independently. I understand about the possibility of hardware acceleration but that's dependent on implementation.
// psuedo code;
#box {
-transition-property: all;
-transition-duration: 1s;
}
// javascript
box.style.transform = "translateX(200px)";
vs
box.style.left = "200px";
What's the advantage of one over the other?
Thanks,
p
The drawing order of rendering layers is:
layout layer
paint layer
compositor layer
A redraw in a layer will trigger redraw in subsequent layers.
Changing left or margin will trigger a redraw in layout layer (which, in turn, will trigger redraws in the other two layers) for the animated element and for subsequent elements in DOM.
Changing transform will trigger a redraw in compositor layer only for the animated element (subsequent elements in DOM will not be redrawn).
The difference in performance (hence in frames per second or, in simple terms, in animation smoothness) is tremendous. Using the first technique will often result in jittery animations even on good machines (when the processor is busy), while the second will likely run smoothly even on systems with limited resources.
Another advantage of using transforms is compositor redraws are heavily optimized (animations to multiple elements result in one redraw for all), while changing layout layer will trigger a redraw after each change of each element.
For a more detailed explanation on rendering techniques and rendering performance I recommend Google's Web Fundamentals.
Position is dependant on what the position is set to, transform works from the element itself. So you could see transform as being identical to position:relative;.
However, you can still use transform on an absolutely positioned element (to position it relatively without needing an additional element or resorting to margins), as well as transform being CSS3 so if you can use position instead you should.
top and left CSS properties work only on elements positioned relative, absolute or fixed. Also, top and left properties rely on the parent's position (relative it, absolute or static). Translations are not affected by that settings.
Translation transformations are "identical" to applying top and left when element has position: relative. In any other case they aren't the same operations.
As mention above:
position:relative and translate can achieve the same effect in a different way
position:relative happen in the layout phase which means it can interact with other elements in terms of layout
while translate happens when all the layout process complete, further it even already painted, what is remaining is a matter where to put the element, so it has no interaction with the existing layout
consider the following example which will present an obvious visual difference by using the two methods
.container {
width: 300px;
height: 300px;
overflow: scroll;
background: red;
}
.child {
width: 280px;
height: 280px;
background: green;
}
<div class="container">
<div class="child"></div>
</div>
By setting position:relative;top:100px to the child element, the container has no enough space to hold the child, and because of the fact that overflow is set as scroll, the scroll bar will present
On the other hand, By setting transform:translateY(100px), it has nothing to do with the layout, so the scrollbar will not present
Like the spec said:
However, if relative positioning causes an 'overflow:auto' or
'overflow:scroll' box to have overflow, the UA must allow the user to
access this content (at its offset position), which, through the
creation of scrollbars, may affect layout
To conclude, position is involved in layout, while transform not, which means transform can have better performance.
prefer transform to position when the layout is not your concern
I've used the div:hover CSS rule to achieve the desired affect - an image "swap" when the mouse hovers over a navigation image: www.scottmccarthydesign.com/dev.index.html
My setup here, however, is not actually a "swap." The main navigation image is a flattened jpeg of the entire desk (for faster loading), and there are empty divs over each item on the desk to map the image with links. When these empty divs are moused over, the div:hover rule fills the div with a .png that is meant to be placed precisely over the main desk image to give the effect of an image swap.
It works nicely in Firefox, but I do not understand why Safari is positioning the :hover image over the desk differently than Firefox is - each :hover image is about 1 pixel off, making it look like the seperate images on the desk are actually shifting a bit when moused over. Any suggestions??
I've had trouble using the :hover pseudo-class on elements other than <a></a>. You could use (jquery/javascript) to alter the class of the said <div> using onmouseover and onmouseout events.
With onmouseover, add a class that defines a certain background image. With onmouseout remove that class.
Even easier, use jquery .hover()
reposition your links after adding this to your css:
a div {
line-height: 0;
}
I've come across this issue before and found that it had to do with the size of the image. When the image is an odd-number pixel size on one of its dimensions, the calculations done by Firefox and Chrome/Safari (particularly when using center) are slightly different. Essentially, it has to do with sub-pixel rounding.
Simply add or subtract a pixel to your images on the axis that has an odd number length, to make them an even number (ie - instead of 100x123, make it 100x124) and you should be golden.
No need to use Javascript, this can certainly be achieved using just CSS. In my opinion, your best bet is to use the technique discussed in this article on CSS Sprites: http://www.alistapart.com/articles/sprites.
Essentially, for each item on your desk, place the hovered and non-hovered image in same image, one on top of each other, so that the top area has the non-hover state, and the bottom area has the hover state. Your code will probably look like this modified:
div#keyboard2 {
position: absolute;
left: 89px;
top: 256px;
width: 67px;
height: 160px;
background: url(../images/keyboard.png) 0 0 no-repeat;
}
#keyboard2:hover { background-position: 0 100%; }
Your desk image will then be empty, and of your items will just be on top of it.