Webkit border-radius and overflow bug when using any animation/transition - css

I am having getting a weird bug when I use a combination of overflow, border-radius, and transition. I have a div with an img inside of it:
<a href="#" class="block size1 annualreport nonprofit">
<div class="inner_block">
<img src="http://i.imgur.com/8uuZB.jpg" />
</div>
</a>
The div has a border-radius, and overflow is set to hidden:
body {background-color:#78735e;}
.block {
position: absolute;
left: 0px;
top: 0px;
border-radius: 10px;
margin: 6px;
box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.2);
overflow:hidden;
}
.size1 {
width: 226px;
height: 464px;
min-width: 160px;
max-width: 226px;
}
.inner_block {
overflow: hidden;
border-radius: 10px;
}
.block img {
width: 100%;
height: 100%;
transition: all 0.1s;
}
.block img:hover { width:115%; height:115%; }
When I hover over the img I have a transition that takes place which makes the image larger to create a zooming effect. The problem is that the overflow seems to break on the bottom left and bottom right of the image.
I have created a JSFiddle for you to see what I'm talking about. http://jsfiddle.net/dmcgrew/HuMrC/1/
It works fine in Firefox, but breaks in Chrome and Safari.
Anyone know what might be causing this or how to fix it?

I had the same exact issue. Adding this to the parent container solved it for me (this is a LESS mixin).
.transitionfix() {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0)
}

I added minus z-index value for image and higher value for parent
li {z-index:10; overflow: hidden;}
li img {z-index: -10;}

I have faced this issue on Safari(It's a known bug in safari); fixed it by applying -webkit-mask-image and it works for me perfectly. cheers
.block {
-webkit-mask-image: -webkit-radial-gradient(white, black);
}

-- Simple Solution --
On the same element that has the animation transition, simply add:
.animated-item {
will-change: transform; /* New line to add to your existing CSS */
}
The will-change CSS property hints to browsers how an element is expected to change. Browsers may set up optimizations before an element is actually changed. These kinds of optimizations can increase the responsiveness of a page by doing potentially expensive work before they are actually required.
~ https://developer.mozilla.org/en-US/docs/Web/CSS/will-change

I don't know if I'm understanding the problem correctly as the image isn't loading. If you add height: 100%; to .inner_block does it help your issue?
http://jsfiddle.net/HuMrC/2/

There's already an answer about a CSS property for creating a new stacking context:
isolation: isolate;

I've had an issue in the past like this while trying to zoom into a photo inside a div. I fixed it by adding rotation scale(1.05) rotate(0.02deg) to the scale transform
(It actually removed the glitchy lines)
My issue today is getting the glitch lines off a translateY div hover effect. Surprisingly enough, I got rid of them by removing overflow: hidden;
Hopefully this helps future debuggers.

It is a problem about stacking context.
We can use methods listed in MDN - stacking context to form a stacking context:
position: relative; z-index: 1;
-webkit-mask-image: -webkit-radial-gradient(white, black);
opacity: 0.999;
will-change: transform;
For me personally, the first method is the best.

Related

Offcanvas menu not working with direction rtl

I have a simple page with two offcanvas menus, one in which side, they both work normally when in english, but since I also need to support arabic, I use the dir="rtl" in the html tag, and with it the right offcanvas menu have some weird behaviour on Chrome, looks like a repaint issue, when I resize the window it goes to the right position (sometimes it goes randomly after a few seconds as well).
I'm using transform: translateX(); and transform: translate3d(); in the body to achieve this, and as far as I can see there's nothing wrong.
Here's a codepen example of the bug: http://codepen.io/Ghostavio/pen/WbgXXZ
Its a simple thing I did Hope This is your answer
What I did was made the body position Fixd
in body:
position: fixed
Your New CSS will look like this:
box-sizing: border-box
body
padding: 5%
position: fixed /*Changed Here*/
overflow-x: hidden
transition: .3s ease-in-out transform
&.left-offcanvas-active
transform: translateX(270px)
//transform: translate3d(270px, 0, 0)
&.right-offcanvas-active
transform: translateX(-270px)
//transform: translate3d(-270px, 0, 0)
header
text-align: center
position: relative
img, svg
vertical-align: middle
a
text-decoration: none
.logo img
width: 240px
max-width: 100%
.gc
fill: #8E8E8E
.content
text-align: justify
.hamburger-icon
position: absolute
top: 10px
left: 0
cursor: pointer
.second-icon
left: auto
right: 0
.left-offcanvas, .right-offcanvas
witdh: 270px
min-width: 270px
height: 100%
background-color: #BABACA
position: fixed
display: block
top: 5%
.left-offcanvas
left: -270px
.right-offcanvas
right: -270px
.offcanvas-links
display: block
padding: 20px
color: #117EBF
border-bottom: 1px solid #E1E1E1
font-weight: 800
text-decoration: none
span
background-color: #C80428
color: #FFF
padding: 0 5px
border-radius: 2px
font-weight: 400
float: right
Hope this helps you.
I had a similar issue creating a sticky header on a horizontal scrolling table for RTL. What I found is that in order to get position : sticky to work for RTL without JS, I had to assign z-index to both the sticky column (sticky header) and the scrollable columns.
At first I used JS to position everything and add offset padding to get the sticky header effect. But after a walking away in frustration and returning to it days later did I come up with a CSS only solution.
JSfiddle example

CSS3 blur filter on image expands beyond original width

I am applying CSS3 blur filter on an image, but unexpectedly the blur effect goes out of the image original size (at least on Webkit browsers ).
I used overflow: hidden; but it's not working.
Here is my code:
HTML:
<div class='container'>
<img src='img.jpg' class='blur' />
</div>
CSS:
body{
padding:0px;
margin: 0px;
background: #1f1f1f;
}
.blur{
-webkit-filter: blur(15px);
-moz-filter: blur(15px);
-o-filter: blur(15px);
-ms-filter: blur(15px);
filter: blur(15px);
}
.container {
border:1px solid #fff;
margin:40px;
float:left;
overflow: hidden;
}
And here is a fiddle
Any ideas?
By giving the img a negative margin such as
img {
margin: -5px;
}
... will hide the spillage. You can play around with the margin.
FIDDLE
EDIT: Why This Occurs
Applying blur... you are blending your element by whatever amount of px, em etc. you declare e.g. 5px. To create this blur, the element will be expanded/feathured by that amount outside of its current size.
So applying a negative margin essentially "clips" the size and prevents anything outside of it to work. "Clipping" it is one approach, another would be by wrapping the element with a div and declaring a height and width and applying overflow: hidden. This will mask the overflow.
As I was experiencing the exact same bug on Safari 8 I thought I'd post my solution.
In the above example, you'd just need to add
-webkit-filter:blur(0px);
to the container.
The blur effect always go beyond the width.
In your case you can fix the issue using one of the following techniques -
Try setting a width of your .container and reduce 15px + 15px from both height and width of the img using CSS calc() function.
Or you can just add a padding of 15px to the img
DEMO of 2nd solution
I don't know much about "blur" yet, but I'm guessing it spreads / blurs out the edges 15px (in this case) in every direction. When you add padding: 15px; to your .container class it looks fine:
.container {
border:1px solid #fff;
margin:40px;
float:left;
overflow: hidden;
padding: 15px;
}
here is the fiddle
Put height and width attributes that are smaller than the image on the container. A size of 1px less than the image seems to work well.
CSS:
.container {
/* ... */
width:399px;
height: 223px;
}
JSFiddle
If your background around the clipping box .outer can be solid, you can cheat with a drop shadow. http://jsfiddle.net/ffghjkbj/
.overflow{
width: 200px;
height: 200px;
overflow: visible;
background-color: transparent;
position: relative;
z-index: 4;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
margin: 30px;
}
.overflow:after {
content: "";
position: absolute;
display: block;
box-shadow: 0 0 0 40px #fff;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
}
.inner{
width: 100%;
height: 100%;
background: green;
filter: blur(10px);
-webkit-filter: blur(0px);
transition: all 0.5s ease-in-out;
-webkit-transform: scale(1.2 , 1.2);
-webkit-transform-origin: 50% 50%;
z-index: -1;
position: absolute;
-webkit-backface-visibility: hidden;
margin: 0px;
padding: 10%;
box-sizing: border-box;
}
.overflow:hover .inner{
filter: blur(10px);
-webkit-filter: blur(10px);
}
If you background is not solid, you could maybe use a border-image, with the same image than the background, to fake the effect, which would be almost the same than using a png mask with a hole in the middle, instead of a background, and moving the pseudo-object with the mask to the front with z-index.
The blurry border you see is generated by the .inner element being CLIPPED (by its parent) BEFORE the blur is applied. Definitely a way for the acceleration not to waste power in rendering hidden areas.
So the .inner element is ALREADY clipped at the parent's edges when the blur is applied to it, and the blurry frame is actualy the outside empty area bleeding inside the image when blurred. The blur is NOT applied to the whole inner element as we would imagine if the element was "inside" or "behind". Just to the visible part. (This is why an oversized .inner element as suggested above won't work).
It's not obvious because the idea of a children element "inside" or "behind" its parent is in our mind. Objects just happen to be clipped at the paren't coordinates, but are actually IN FRONT of the parent.

Off by one pixel issue in IE CSS transform

I am using transform: skew to create the effect of a down arrow on my banner image using both the :before and :after tags. The result should look like the following:
However, in IE 9-11 there seems to be a rounding issue. At some heights there is one pixel from the background image that shows below the skewed blocks resulting in the following:
In my case, the banner is a percentage of the total height of the window. Here is the some sample code which should be able to reproduce the problem:
HTML
<div id="main">
<div id="banner"></div>
<section>
<h1>...</h1>
<p>...</p>
</section>
</div>
CSS
#banner {
position: relative;
background-color: green;
width: 100%;
height: 75%;
overflow: hidden;
}
#banner:before,
#banner:after {
content: '';
display: block;
position: absolute;
bottom: 0;
width: 50%;
height: 1.5em;
background-color: #FFFFF9;
transform: skew(45deg);
transform-origin: right bottom;
}
#banner:after {
right: 0;
transform: skew(-45deg);
transform-origin: left bottom;
}
body {
background-color: #333;
position: absolute;
width: 100%;
height: 100%;
}
#main {
max-width: 40em;
margin: 0 auto;
background-color: #FFFFF9;
position: relative;
height: 100%;
}
section {
padding: 0 1em 5em;
background-color: #FFFFF9;
}
And here a working example.
Yes, seems to be a rounding issue – and I don’t know of anything that one could do to fix this. It’s in the nature of percentage values that they don’t always result in full pixel values – and how rounding is done in those cases is up to the browser vendor, I’m afraid.
I can only offer you a possible workaround (resp. “cover up”) that seems to work – if the layout really is as simple as this, and the main content area has a white background, and no transparency or background-image gets involved there.
Pull the section “up” over the banner by a negative margin of -1px (eliminated top margin of h1 here as well, otherwise it adjoins with the top margin of the section – countered by a padding-top), so that its background simply covers up that little glitch:
section {
padding: 1em 1em 5em;
background-color: #FFFFF9;
position:relative;
margin-top:-1px;
}
section h1:first-child { margin-top:0; }
Well, if you look closely, that makes the corner of triangle look slightly “cut off” (by one pixel) in those situations where the rounding glitch occurs – if you can live with that (and your desired layout allows for it), then take it :-) (And maybe serve it to IE only by some means). If not – then sorry, can’t help you there.

z-index is canceled by setting transform(rotate)

Using transform property, z-index is canceled and appeared in the front.
(When commenting out -webkit-transform, z-index is properly working in below code)
.test {
width: 150px;
height: 40px;
margin: 30px;
line-height: 40px;
position: relative;
background: white;
-webkit-transform: rotate(10deg);
}
.test:after {
width: 100px;
height: 35px;
content: "";
position: absolute;
top: 0;
right: 2px;
-webkit-box-shadow: 0 5px 5px #999;
/* Safari and Chrome */
-webkit-transform: rotate(3deg);
/* Safari and Chrome */
transform: rotate(3deg);
z-index: -1;
}
<html>
<head>
<title>transform</title>
<link rel="stylesheet" type="text/css" href="transformtest.css">
</head>
<body>
<div class="test">z-index is canceled.</div>
</body>
</html>
How do transform and z-index work together?
Let's walk through what is occurring. To start, note that z-index on positioned elements and transform by itself create new "stacking contexts" on elements. Here's what's going on:
Your .test element has transform set to something other than none, which gives it its own stacking context.
You then add a .test:after pseudo-element, which is a child of .test. This child has z-index: -1, setting the stack level of .test:after within the stacking context of .test Setting z-index: -1 on .test:after does not place it behind .test because z-index only has meaning within a given stacking context.
When you remove -webkit-transform from .test it removes its stacking context, causing .test and .test:after to share a stacking context (that of <html>) and making .test:after go behind .test. Note that after removing .test's -webkit-transform rule you can, once again, give it its own stacking context by setting a new z-index rule (any value) on .test (again, because it is positioned)!
So how do we solve your problem?
To get z-index working the way you expect, make sure that .test and .test:after share the same stacking context. The problem is that you want .test rotated with transform, but to do so means creating its own stacking context. Fortunately, placing .test in a wrapping container and rotating that will still allow its children to share a stacking context while also rotating both.
Here's what you started with: http://jsfiddle.net/fH64Q/
And here's a way you can get around the stacking-contexts and keep
the rotation (note that the shadow gets a bit cut off because of .test's white background):
.wrapper {
-webkit-transform: rotate(10deg);
}
.test {
width: 150px;
height: 40px;
margin: 30px;
line-height: 40px;
position: relative;
background: white;
}
.test:after {
width: 100px;
height: 35px;
content: "";
position: absolute;
top: 0;
right: 2px;
-webkit-box-shadow: 0 5px 5px #999; /* Safari and Chrome */
-webkit-transform: rotate(3deg); /* Safari and Chrome */
transform: rotate(3deg);
z-index: -1;
}
<div class="wrapper">
<div class="test">z-index is canceled.</div>
</div>
There are other ways to do this, better ways even. I would probably make the "post-it" background the containing element and then put the text inside, that would probably be the easiest method and would reduce the complexity of what you have.
Check out this article for more details about z-index and stacking order, or the working W3C CSS3 spec on stacking context
Set the div you want to stay on top to position:relative
Had a similar problem where siblings were being transform: translate()'d and z-index wouldn't work.
Most straightforward solution is to set position: relative on all siblings, then z-index would work again.
Quick fix: You could just rotate the other element by 0 degrees as well.
For those who still looking for the solution, I found this article how to solve issue with transform and z-index here
Simple usage of it is by doing this:
.parent { transform-style: preserve-3d; }
.parent:before { transform: translateZ(-1em); }
I was facing the similar problem.
What i did was, I added a wrapper div around the test and gave the transform property to the wrapper div.
.wrapper{
transform: rotate(10deg);
}
here is the fiddle http://jsfiddle.net/KmnF2/16/
Set the div you want to stay on top to position:absolute

overflow:hidden ignored with border-radius and CSS transforms (webkit only)

I want to have a square image inside a circle.
When the user hovers over the image, the image should scale (zoom in).
The circle should remain the same size.
Only during the CSS transition, the square image overlaps the circle (as if overflow:hidden weren't there at all).
Here's a demo with the weird behavior in Chrome and Safari:
http://codepen.io/jshawl/full/flbau
Working ok in firefox.
You need to add this code to the parent of your img :
position:relative;
z-index:1;
Example here : http://codepen.io/DavidN/pen/dIzJK
I removed some superfluous markup (the circle and square containers... only needs one) and styled the img itself:
#wrapper {
width: 500px;
height: 500px;
border-radius: 50%;
overflow: hidden;
-webkit-mask-image: -webkit-radial-gradient(circle, white, black);
}
#test {
width: 100%;
height: 100%;
transition: all 2s linear;
}
#test:hover {
transform: scale(1.2);
}
<div id="wrapper">
<img src="http://rack.3.mshcdn.com/media/ZgkyMDEzLzA1LzA4L2JlL2JhYmllc193aXRoLjA5NGNjLnBuZwpwCXRodW1iCTg1MHg1OTA-CmUJanBn/8f195417/e44/babies_with_swagg.jpg" id="test">
</div>
Add this code to your parent div and solve problem :
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
It appears as though you were styling one too many elements! I've created a fork here
I edited some of your SASS code to utilize the compass library and make better use of the transition and transform properties which can be seen here:
body { padding: 3em; }
.circle {
height: 500px;
width: 500px;
border: 1px solid black;
#include border-radius(500px);
overflow: hidden;
}
.circle img {
height: 500px;
width: 500px;
#include transition(all 0.3s ease);
&:hover { #include transform(scale(1.1)); }
}
Hopefully this helps! Just think of the circle element as the parent container which has general information about the space (e.g. 500px wide and 500px tall). The image itself has a rounded border of 500px. This is the element you want to edit! You can scale and transform this element here without interacting with the parent circle container. Reference compass for additional information about using the library! Good luck!

Resources