CSS shake/jitter bug in chrome? transition of width on centered div - css

I have a centered div layer using margin: 0 auto, with a fixed width of width: 1000px, which will go width: 100% when starting to scroll down, along with a transition to make it look nice.
The problem is, that some of the content starts to shake and jitter during the transition. I say some of the content, because for example images shake, while H1 texts does not
This only happens in Chrome and Edge. (tested on windows 10).
Doing some research, I found Chrome had known issues in the past with transitions when not using hardware acceleration, resulting in flickering. From what I understand, this has been solved by Google over 2 years ago.
I tried implementing all sorts of workarounds, trying to trigger a hardware acceleration, but nothing worked.
From what I learned so far, this jittering / shaking issue only happens when a div layer is centered using margin: 0 auto with a fixed width and that element is then transitioned into width: 100%.
A strange issue, when re-creating the demo code inside of JSFiddle, I can’t seem to always reproduce it on my system.
Here is the JSFiddle: https://jsfiddle.net/aobrien/vc4n8ecy/
Just scroll down and notice how the chrome logo shakes. You might have to scroll up and down to noticed it, depending on your screen size.
Note: This only seems to be visible when you have a screen width of around 1700px or higher, so make sure your browser is in full width. Scaling the browser window to 80% also triggers the issue.
//jQuery to add sticky class when scrolling
$(window).scroll(function() {
if ($(this).scrollTop() > 1) {
$('.header').addClass("sticky");
} else {
$('.header').removeClass("sticky");
}
});
body {
height: 2000px;
}
.header {
background: #335C7D;
margin: 0 auto;
width: 1000px;
transition: width .6s ease;
height: 200px;
}
.sticky {
position: fixed;
width: 100%;
left: 0;
right: 0;
will-change: width;
}
.wrap {
width: 1000px;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="header">
<div class="wrap">
<img src="https://i.stack.imgur.com/iaYsc.png" />
<h1> Hello World.</h1>
</div>
</div>
</div>
This seems to be very easy and straight forward way of achieving a full width sticky menu with transition.
Could it be that using margin: 0 auto along with a width change, results in problems to recalculate the centered div layer?
So far, all my attempts to solve this or find a workaround, have failed.

It seems I found one solution.
Adding display: table; to the element that uses the transition property, seems to remove the shaking.
//jQuery to add sticky class when scrolling
$(window).scroll(function() {
if ($(this).scrollTop() > 1) {
$('.header').addClass("sticky");
} else {
$('.header').removeClass("sticky");
}
});
body {
height: 2000px;
}
.header {
background: #335C7D;
margin: 0 auto;
width: 1000px;
transition: width .6s ease;
height: 200px;
display: table; /* this seems to fix it */
}
.sticky {
position: fixed;
width: 100%;
left: 0;
right: 0;
will-change: width;
}
.wrap {
width: 1000px;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="header">
<div class="wrap">
<img src="https://i.stack.imgur.com/iaYsc.png" />
<h1> Hello World.</h1>
</div>
</div>
</div>

Related

How to stretch a canvas to page full height with header & footer?

Is there a simple CSS-only solution to make a HTML5 canvas to fill the entire space between a header and a footer?
The height of header and footer is known and fixed, all elements should have 100% width. Key point here is the simplicity of markup and style, and to avoid wrapper divs.
This is my markup:
<div class="header"><p>header</p></div>
<canvas id="content" class="content"></canvas>
<div class="footer"><p>footer</p></div>
While the problem of a full-height div between header and footer seems to be a lot easier to solve, and there are on SO already some very fine answers, i cannot figure a way to get the same with a canvas.
Fiddle: http://jsfiddle.net/h7smdykf/
Do you mean like this?
Edit: Jep, they are right, streching the canvas skrews up your elements. I got a little further with "object-fit" https://www.w3.org/TR/css3-images/#the-object-fit
Using "object-fit" is suggested from https://html.spec.whatwg.org/multipage/scripting.html#the-canvas-element
Edit2: There is still a problem with the vertical alignment. The Circle should be in the middle of the page.
z-Index solves the problem.
var c=document.getElementById("content");
var ctx=c.getContext("2d");
var x = c.width / 2;
var y = c.height / 2
ctx.beginPath();
ctx.arc(x,y,50,0,2*Math.PI);
ctx.stroke();
html, body {
margin: 0;
padding: 0;
}
.header, .footer {
position: fixed;
width: 100%;
height: 48px;
left: 0;
background: lightgreen;
z-index: 1;
}
.footer {
bottom: 0px;
}
.content {
position: fixed;
width: 100%;
height: 100%;
object-fit: scale-down;
background: lightblue;
z-index: 0;
margin: 48 0 48 0;
}
<div class="header"><p>header</p></div>
<canvas id="content" class="content"></canvas>
<div class="footer">footer</div>

CSS resize of image in fluid lightbox container

Short version: Make the image fit nicely the visible area for small windows, starting from this fiddle
Update: There doesn't seem to be a solution for this issue. I thought there might be one because Chrome actually makes it possible (see my answer) but behavior is different in other browsers.
Longer version:
I'm working on a lightweight fluid lightbox and have an apparently simple CSS issue I can't resolve.
I want the content (a single image) to be downsized if needed to fit, while keeping the aspect ratio the same.
Here's a demo fiddle: http://jsfiddle.net/3a9y9/2/ . Resize the window so the image doesn't fit height wise.
It almost works, but the height given to the image is slightly more than what's actually visible so a bit of the bottom gets clipped. I've tried tweaking things to no avail; I wish I understood how come the available height is too high.
Maybe it's related, but IE 9 doesn't even maintain the aspect ratio with this attempt of a solution. Also, Chrome behaves strangely when resizing the window and clicking on run in the fiddle will sometimes redraw differently.
What's the solution?
It's no problem to wrap the <img> in a <div> or two if it's necessary, but the top-level structure should ideally remain the same (i.e. a .featherlight-content inside a .featherlight and that's it).
In featherlight.min.css, change .featherlight-image{width: 100%} to .featherlight-image{max-width: 100%}
and at the end, write the following css:
#media only screen and (min-height:1000px) {
.featherlight-image { height: 900px; }
}
#media only screen and (min-height:700px) {
.featherlight-image { height: 600px; }
}
#media only screen and (max-height:700px) {
.featherlight-image { height: 400px; }
}
What it's doing is changing the width of the lightbox from fixed 100% into a maximum of 100% (so that it's adjusted as per height). And then with #media, the height of the image is restricted. #media will allow for responsiveness based on browser height.
Higher resolution browsers will show the image at 900px height; those with a minimum of 700px height will show it at 600px, and smaller ones will show it at 400px.
You can of course adjust the numbers as per your preference; but this solution worked and solves the problem of long images.
Here's a jsfiddle. Note that using data-featherlight="image" is important for this to work properly.
Hope it helps.
In my opinion, the easiest way to both fit an image in the container and to center it is absolute positioning with margin: auto:
.featherlight img {
max-width:90%;
max-height:90%;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
margin: auto;
}
(Fiddle)
Alternatively, you can try to set the size of the image in viewport relative units (vw/vh), they have quite good browser support now: http://caniuse.com/#search=vw
Note: The following appears to be true only for Chrome, but it doesn't work in Firefox or IE...
After much twiddling around, my conclusion is that there's a fundamental difference in the way that height and width are treated in general and that it affects calculations here.
It's bound to be related to the flow of things, like how reducing the width of a <div> will have the content flow down, expanding the height, but how reducing the height of a <div> won't make it wider.
The clipping here is due to the fact that the border-bottom and padding-top are not taken into account in the available height. The solution is thus to remove those altogether.
If one still wants a border, then it can be faked by adding an absolutely positioned <div>. Here's the corresponding fiddle.
It gets cut off because the padding is throwing it off.
It doesn't work in IE or Firefox because they don't assume that the height of content div should stretch to fit its container's height. You would have to use height: 100% or some other percentage. This causes more problems when trying to achieve a max-height.
It doesn't enlarge the image when the size gets larger in height because that is the way most browsers handle re-rendering the page (or not re-rendering in this case) when the size of the viewport changes in height. You will have to force a re-rendering of the page. The only CSS way I know how to do that is with a CSS3 animation.
Here is a solution that does not work in Firefox or IE (so... not that great of a solution), but it fixes the cutting-off and resizing issues.
http://jsfiddle.net/SombreErmine/ENrnu/5/
It utilizes calc() and CSS3 animations; so it's definitely limited in practical use. I'm not posting this as the solution. I'm mostly posting it to share some information on what I've learned. Hopefully, this will help lead to a real solution.
HTML Code:
<div class="featherlight" style="display: block;">
<div class="featherlight-content">
<img src="http://placekitten.com/640/480" alt="" class="featherlight-image featherlight-inner"/>
</div>
</div>
CSS Code:
.featherlight {
position:fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
text-align: center;
background: rgba(0, 0, 0, 0.8);
}
.featherlight:before {
/* position: trick to center content vertically */
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em;
}
.featherlight .featherlight-content {
padding: 25px;
position: relative;
text-align: center;
vertical-align: middle;
display: inline-block;
min-width: 30%;
margin-left: 5%;
margin-right: 5%;
max-height: 95%;
background: #fff;
}
.featherlight .featherlight-image {
max-width:100%;
max-height:calc(100% - 50px);
vertical-align: bottom;
-webkit-animation: render_update 1s linear 0s infinite;
-moz-animation: render_update 1s linear 0s infinite;
-o-animation: render_update 1s linear 0s infinite;
animation: render_update 1s linear 0s infinite;
}
#-webkit-keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
#-moz-keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
#-o-keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
#keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
You can try the following approach. Elements that have a set width become wider when they have padding and/or border-width. To avoid these problems, make use of the now common box-sizing: border-box; reset.
*,
*:before,
*:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
An element can be centered by setting height: 100%; to a "ghost" element (it can be a pseudo element) inside the parent and vertical-align: middle; to both.
.featherlight {
background-color: rgba(0, 0, 0, 0.8);
bottom: 0;
font-size: 0;
left: 0;
overflow: auto;
padding: 0 5%;
position: absolute;
right: 0;
text-align: center;
top: 0;
}
.featherlight:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.featherlight-content {
display: inline-block;
margin: 5% 0;
max-width: 100%;
vertical-align: middle;
}
Images can be made responsive-friendly by applying max-width: 100%; and height: auto; to the image so that it scales nicely to the parent element.
.featherlight-content img {
border: 25px solid #fff;
display: block;
height: auto;
max-width: 100%;
}
See live example here: http://jsfiddle.net/cdog/AXzz8/.

Scaling div width depending on height

I want to have a site that is 100% of the height of the browser at all times, with the width scaling with an aspect ratio when the height is changed.
I can achieve this using the new vh unit: http://jsbin.com/AmAZaDA/3 (resize browser height)
<body>
<div></div>
</body>
html, body {
height: 100%;
width: 100%;
margin: 0;
}
div {
height: 100%;
width: 130vh;
margin: 0 auto;
background: #f0f;
}
However, I worry about fallback for IE8 and Safari, as it this unit is not supported there.
Are there any other CSS only methods of achieving this effect?
I have a solution that works also with IE8 (using Pure CSS 2.1), but not perfectly.
because I need the browser to recalculate things when he get resized, and apparently it doesn't do that unless he has to (and I cant find a way to make him think he has to), so you will have to refresh the page after resizing.
as far as I know, the only element that can scale reserving his ratio is an <img>, so we will use the <img> to our advantage.
SO, we are going to use an image with the ratio that we want (using the services of placehold.it), lets say we want a 13X10 ratio (like in your example), so we'll use <img src="http://placehold.it/13x10" />.
that image will have a fixed height of 100% the body, and now the width of the image scales with respect to the ratio. so the width of the image is 130% height of the body.
that image is enclosed within a div, and that div has inline-block display, so he takes exactly the size of his content. witch is the size you want.
we remove the image from the display by using visibility: hidden; (not display:none; because we need the image to take the space), and we create another absolute div, that will hold the actual content, that will be right above the image (100% width and 100% height of the common container).
That works perfectly when you first initiate the page, but when you resize the page, the browser doesn't always measure the right width and height again, so you'll need to refresh to make that happened.
Here is the complete HTML:
<div class="Scalable">
<img class="Scaler" src="http://placehold.it/13x10" />
<div class="Content"></div>
</div>
and this simple CSS:
html, body, .Content
{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body
{
text-align: center;
}
.Scalable
{
position: relative;
display: inline-block;
height: 100%;
}
.Scaler
{
width: auto;
height: 100%;
margin-bottom: -5px;
visibility: hidden;
}
.Content
{
position: absolute;
top: 0;
background-color: black;
}
Here's a Fiddle (don't forget to refresh after resizing)
I recommend you to copy this code to your local machine and try it there rather then within the fiddle.
In this similar SO question a CSS technique was found and explained on this blog entry that allows an element to adjust its height depending on its width. Here is a repost of the code:
HTML:
<div id="container">
<div id="dummy"></div>
<div id="element">
some text
</div>
</div>
CSS:
#container {
display: inline-block;
position: relative;
width: 50%;
}
#dummy {
margin-top: 75%; /* 4:3 aspect ratio */
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver /* show me! */
}
Demo Here
If this is sufficient for you, I'd recommend this technique. However, I'm unaware if the technique can be adapted to handle scenarios where you must have an element adjust its width depending on its height.
You can do it with the help of padding on a parent item, because relative padding (even height-wise) is based on the width of the element.
CSS:
.imageContainer {
position: relative;
width: 25%;
padding-bottom: 25%;
float: left;
height: 0;
}
img {
width: 100%;
height: 100%;
position: absolute;
left: 0;
}

CSS Sticky Footer - With Margin

I'm trying to apply this method of the Sticky Footer: http://code.google.com/p/cleanstickyfooter/
It works great, however, I have one problem. The design for my particular site has a 34px margin at the top of the page. So I've tried a few ways of implementing it, either by doing body {margin-top:34px} or doing container {margin-top:34px}.
However, in both cases, the Sticky Footer gets messed up. When I try to compensate for the 34px, it doesn't ever seem to work out.
Any ideas?
Here's a Fiddle example: http://jsfiddle.net/jrZKb/
Using the Modern Clean CSS Sticky Footer, it's working (on FireFox and IE9):
http://jsfiddle.net/jrZKb/1/
<body>
<header> Header</header>
<article>Lorem ipsum...</article>
<footer></footer>
</body>
html {
position: relative;
min-height: 100%;
}
body {
margin: 0 0 100px; /* bottom = footer height */
}
header
{
background-color: green;
}
footer {
position: absolute;
left: 0;
bottom: 0;
height: 100px;
width: 100%;
background-color: blue;
}

z-index layering in IE9, with example, stacking contexts checked (I think)

I am working on a portfolio project. I have a relatively positioned image in a relatively positioned div. Using z-index I have a fixed position div on top of this, inside of which there are three floated divs, each of which has a cursor url specified in css. All of this is in another div. The aim is to have a previous, play and next cursor displayed on top of an image to control the display of images.
It works well in Safari, Firefox, Chrome. It does not work in IE (9,8 or 7). The cursor does not show when over the image. Somehow, the fixed position div is dropping behind the image, even though it's z-index says it should be above.
I have read a lot on this. I have considered the stacking contexts, and I believe they are OK in my code. I have investigated making all the objects have relative positioning in case fixed and relative positioning is creating different stacking contexts. This did not solve it. I have investigated quirks and standard mode. Nothing seems to work.
I have uploaded stripped back example pages of my problem here:
http://bigflannel.com/portfolio/ie-test
Any help very very gratefully appreciated. I'm 8 hours into debugging and stuck.
The HTML
<div id ="website">
<div id="media-panel">
<img id="image0" class="image" src="http://bigflannel.com/portfolio/admin/albums/album-5/lg/fk01117.jpg">
</div><!-- #media-panel -->
<div id="navigation-panel">
<div id="left-area"></div>
<div id="play-pause-area"></div>
<div id="right-area"></div>
</div><!-- #navigation-panel -->
</div><!-- #website -->
The CSS
#website {
position: relative;
z-index: 0;
}
#media-panel {
position: relative;
height: 600px;
z-index: 1;
}
.image {
position: relative;
max-height: 600px;
max-width: 600px;
z-index: 0;
}
#navigation-panel {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 1500px;
height: 900px;
}
#left-area {
position: relative;
float: left;
cursor: url(http://bigflannel.com/development/mobileApp/bigflannel-portfolio/images/prevL.cur), auto;
width: 500px;
height: 900px;
}
#play-pause-area {
position: relative;
float: left;
cursor: url(http://bigflannel.com/development/mobileApp/bigflannel-portfolio/images/playL.cur), auto;
width: 500px;
height: 900px;
}
#right-area {
position: relative;
float: left;
cursor: url(http://bigflannel.com/development/mobileApp/bigflannel-portfolio/images/nextL.cur), auto;
width: 500px;
height: 900px;
}
Unfortunately IE is very buggy when it comes to cursors. This is actually not a z-index issue. The layering is working as expected. You can test this by putting a background color on the #navigation-panel as it goes over the image. It has to do with IE and the behaviour of cursor.
Solution: (for IE9)
/* Background with no opacity */
#navigation-panel {
background: rgba(0, 0, 0, 0);
}
You can probably fix with earlier versions of IE by using the filter.

Resources