Setting overflow on container breaks translateZ - css

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

Related

Border radius not applied if backface-visibility hidden on child element

I have a couple of divs, one inside the other, I'm using border-radius and overflow: hidden on the outer div which creates a circular mask over the inner div.
It works, however, when using backface-visibility: hidden; on the child div the border-radius is no longer applied.
Here's an example of the issue, can be seen in chrome and safari
Looks like this is a bug in webkit it's being tracked on the chromium issue track. Looks like no sign of a fix being merged any time soon.
Ok, i've tried a few things with your example. The W3schools states that "backface-visibility:hidden;" is not yet well supported. This property has to do with 3d transformations, right? Specially rotation.
I found a workaround. Apply the "backface-visibility" on the mask div, not the inner one. If you do that, you'll see that it breaks the round as well. But if you apply a rotation transform on the mask div, the rounded border appears back to normal.
So, if you really want to hide the backface without losing the radius, apply this style only after you started rotating the element. Check this out:
<p>Backface hidden:</p>
<div class="ex">
<div class="mask bfh">
<div class="bg"></div>
</div>
</div>
And the css:
.bfh {
-webkit-backface-visibility:hidden;
-webkit-transform: rotateY(30deg);
}
In #Rob linked track on chrome issue there is also a workaround that was added by user viktorli.
Simply add a transform rule on the parent element of the rogue child not respecting the overflow:hidden rule and it will be fixed! something like:
-webkit-transform: scale(1);

Is Chrome regressing regarding z-indexes (or what am i doing wrong)?

The nav of a website i have in production works as 3 tabs, each of the 3 corresponding content coming forward on click.
I just realized it doesn't work on Chrome 22 (although i'm 90% sure i tested it on Chrome a year ago when the site was brought online), but is perfectly fine on IE9 and FF16.
Here is a summary of my problem : http://jsfiddle.net/be7mQ/3/
As you can see, only the last tab of the 3 can be hovered (and therefore clicked) on Chrome 22.
It's like Chrome created a new z-index stack for each .tab-container instead of just showing all elements with z-index:21 above the rest of the content.
All the elements are either position:fixed or position:absolute and i can't see what's wrong there, anyone?
It's like Chrome created a new z-index stack for each .tab-container instead of just showing all elements with z-index:21 above the rest of the content.
This behavior was deliberately introduced in Chrome 22. Boxes with position: fixed will create new stacking contexts in WebKit-based browsers regardless of their z-index, causing the behavior you're currently seeing.
More on that here. It is said that it is being proposed as a revision to the CSS2.1 spec to aid mobile implementations (the same behavior already occurs on mobile WebKit browsers); it was addressed to some extent in this set of minutes but there hasn't been any actual change to the spec yet as I've seen — indeed; the working group hasn't reached a consensus yet.
I for one agree with Microsoft's compatibility concerns; I can see this breaking a sizable portion of modern sites. The problem is exacerbated by workarounds basically being situational and totally dependent on the nature of the affected layout, as demonstrated by the other answers here.
BoltClock's answer was the one, and as previously written, each case will need a specific fix to this, but this is how i solved my own broken site :
http://jsfiddle.net/be7mQ/13/
i.e. put all my previous position:fixed divs in one only position:fixed parent #tabs that has z-index:1 to force a new stack on browsers other than Chrome22.
This way, within the new #tabs element i'm free to play with z-indexes again as before.
Remove height: 100% from .tab-container. The height of the third tab is covering up the previous two. When I did this in your fiddle they were all clickable.
Since you're using position fixed, the top: 0 property will make your last element hover all others. Instead of positioning your tab element, change the top of your tab-container, as follows.
Change your HTML to
<div class="tab-container info">
<div id="info" class="tab">I<br/>N<br/>F<br/>O</div>
</div>
<div class="tab-container news">
<div id="news" class="tab">N<br/>E<br/>W<br/>S</div>
</div>
<div class="tab-container shop">
<div id="shop" class="tab">S<br/>H<br/>O<br/>P</div>
</div>​
and your CSS to
.info{
top:0px;
}
.news{
top:100px;
}
.shop{
top:200px;
}​
Fiddle
Because you are using
height: 100%
on the .tab-container{, the last one is overlapping everything else hence only the third(last) one works for hovering. Try removing the height: 100% from your css for tab-container. It works!

Kill Horizontal Scroll On Absolute Image with Body as Parent

I haven't asked too many CSS questions on here, so here it goes.
Let's say I have a page:
<body>
<div id="wrap">//page containment, etc.. goes here..</div>
<img class="custom-bg" src="example.jpg" />
</body>
Then I write some CSS for the image in particular:
#wrap {
z-index: 100;
}
img.custom-bg {
position: absolute;
top: 1000px;
left: 50%;
margin-left: -960px //the image is 1290px wide
z-index: 0;
}
If you can't tell by now, yes, I'm trying to create a background image using absolute positioning. Yes, I know, I can just set the image as a background to the body tag and use positioning to place it, but for the sake of this question, let's say that's not an option to me.
The issue at hand is the appearance of horizontal scroll bars. Google is full of examples with people turning off overflow and other things, but I'm curious if anyone has been able to find/create a definite approach to removing horizontal scroll bars when performing something like the above. An absolute image, that lives happily on it's own. Centered. And not "attached" to the window... Thus eliminating the need for the browser to let users know there's an image that's really big, and that they just have to see it by scrolling horizontally a little bit.
Any insight would be awesome. I included as little code as possible so that people who may search for this example and are new to web dev, may have an easy time understanding how to work through their problem regarding absolute positioning and horizontal scrolling.
I may have missed the point here, but why don't you just use position:fixed instead?
http://jsfiddle.net/shanethehat/7MetS/

Fluid images in Chrome: how to avoid repaint?

I'm working on a photography site with a lot of images and they have no fixed height and width as I want this site to be 100% fluid: how do you work around the ugly Chrome repaint of the images? (i.e. Images are first displayed at zero height and then rescaled to their final size moving around the entire layout)
I've tried pretty much everything and my last option is to hide the image repaint with a black div and then set its opacity to 0 when images are finished loading (BTW, I've tried this with a (document).ready call but it seems too soon: how would you do it?)
Specify your image's height and width attribute / its dimensions.
<img src="img.jpg" width="125" height="60" alt="My First Photograph ever">
This helps the browser avoid a second pass to layout your page and it optimizes page load as well! :)
Chrome (or any browser really) cannot avoid this 'repainting', since they don't know on forehand what size your images will be.
Thus, you will need to explicitly specify the sizes of your images, either in the image width and height properties itself, or via CSS.
I know I am more than two years late, but how about the practice suggested here?
<div class="embed-container ratio-16-9">
<img src="imgage.jpg"/>
</div>
.embed-container {
position: relative;
height: 0;
overflow: hidden;
background-color:black;
}
.ratio-16-9{
padding-bottom:56.25%; /* 9/16*100 */
}
.ratio-4-3{
padding-bottom:75%; /* 3/4*100 */
}
.ratio-1-1{
padding-bottom:100%; /* ... */
Also, an important remark from the comments section to pay attention to, and improve upon the original technique:
Nice trick. However, if I was you, I would replace the "img" tag with
a background image on your div (and background-size: cover or
contain). That would avoid you the position trick, the overflow trick,
and a lot of work for the browser.
I hope someone will find this useful.
It’s hard to test, but you could try setting width/height in CSS
img {display: block; width: 100%; height: auto;}
if you want the images to be full-width. This might prevent a full-page repaint, but of course there’ll be some repaint regardless as images load. You can also investigate what’s happening with Chrome’s --show-paint-rects
Hope that helps

CSS3 property webkit-overflow-scrolling:touch ERROR

iOS 5 released web designers a new property -webkit-overflow-scrolling:touch that uses the iOS devices hardware accelerator to provide native scrolling for a scrollable div.
When implemented on our site in development it does work but not well. I believe there may be a CSS issue hence I ask here.
The following fiddle will show you it working perfectly
If you pop over to our site in development you will find the same panel under facilities tab but on iOS although the scrolling is perfect the overflowed section is not shown with pictures literarily chopped in two.
http://www.golfbrowser.com/courses/mill-ride/
I have no idea how to fix this
http://www.golfbrowser.com/photo.PNG
As #relluf pointed out, applying 3D transitions on the relative element fixes the bug. However, I investigated it a bit further and it seems that applying -webkit-transform: translateZ(0px) works too (this is what Google does on gmaps map container) and it does not need to be on the relatively positioned element, just the direct descendant of the scrollable element.
So if you don't want to manually keep a list of all the places where the fix is needed, you just might do:
element {
-webkit-overflow-scrolling: touch;
}
element > * {
-webkit-transform: translateZ(0px);
}
What a bugger they let loose here. Tried all manner of workarounds until I finally found the only property needed by for elements to be properly rendered in a -webkit-overflow-scrolling:touch div: position: static
Relative and absolute positioned elements are always cut off on the boundary, and completely missing (except for empty space) outside of it. If you change the position property dynamically, from static to absolute, only the visible portion of the scrollable div viewport stays rendered, wherever the offset happens to be.
I have run into this bug as well. I fixed it by applying the following css to parent elements:
-webkit-transform: translate3d(0, 0, 0);
However, I have noticed that that slows down rendering and might select other input elements than wanted when a touched input element is scrolled into the center of the view (by Safari/iOS).
In iOS, when an element inside an element with -webkit-overflow-scrolling: touch set is positioned absolutely (or fixed) relative to an element outside of the scrolling container, the element is rendered only once and the rendering is not updated as the element is scrolled. Sample HTML:
<div class="relative-to-me">
<div class="scrollable">
<div class="absolutely-positioned">
</div>
</div>
</div>
If you force a re-render by changing a CSS property (in the inspector for example), you can see that the element's positioning is re-rendered into the correct location. I suspect this is a result of some performance features to optimize scrolling performance.
The solution to this problem is to set will-change: transform on the absolutely (or fixed) positioned element.
.absolutely-positioned {
will-change: transform;
}
I deeply investigated this bug, I also created a jsfiddle and submitted it to Apple in a bug report. Please see: iOS5 Images disappear when scrolling with webkit-overflow-scrolling: touch
As soon as Apple replies to me, I'll report it on that topic so you can stay up-to-date about this very annoying bug
I also experienced the problem where overflow scroll with -webkit-overlfow-scrolling set to touch resulted in redraw problems with positioned elements. In my case I had a list where the individual items had relative positioning so that I could use positioning on their child elements. With the above CSS on iOS 5, when the user scrolled hidden content into view, there was a momentary delay before it redrew the screen to review the elements. It was really annoying. Fortunately I discover that if I gave the parent node position relative as well, this was resolved.
The bug still lives in iOS 6. If your issue is related to position: relative, you might solve the issue be setting z-index: 1 temporarily via JS. -webkit-transform: translate(...) did not work with position: relative in my case.
I tried some different solutions, seemed not work perfectly in my case.
Finally I've found a way works fine with jQuery:
Apply -webkit-overflow-scrolling property every time when you touch up.
*At first I Applied Also -webkit-overflow-scrolling:auto when TouchDown, to disable iOS rendering. But it made Page blink. So I dropped it away, then works fine surprisingly!
Check lines below, hope it helps:
<!-- 🍉 JQuery Functions-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
//🍋 Apply -webkit-overflow-scrolling in Every TouchEnd
$(document).on('click touchend', function(event) {
$("#TestDIV").css({"-webkit-overflow-scrolling":"touch"});
});
</script>
<!-- 🍉 html Elements & Style -->
<div id="TestDIV">
<div class="Element"></div>
<div class="Element"></div>
<div class="Element"></div>
<div class="Element"></div>
<div class="Element"></div>
</div>
<style>
#TestDIV{
white-space: nowrap;
overflow-x: scroll;
-webkit-overflow-scrolling:touch;
}
#TestDIV .Element{
width:300px;
height:300px;
margin: 2px;
background-color: gray;
display: inline-block;
}
#TestDIV .Element:nth-child(odd){
background-color: whitesmoke;
}
</style>

Resources