Nested position:fixed clipped with overflow:auto, but only in Webkit on Mac - css

I have two DIVs, main and header. Both are position: fixed. The top of the header places it above (in the negative top margin of) the main DIV, which has overflow: auto to allow for scrolling. The header is visible on all modern desktop browsers I've tested, except Chrome and Safari on Mac, where it's clipped (hidden).
This seems like a bug, but I don't understand why it would only affect Webkit-based browsers on OS X.
Here's the code...
HTML:
<div id="main">
<div id="header">Partially clipped in Chrome and Safari on Mac.</div>
Main content goes here.<br/>
Main content goes here.<br/>
...
</div>
CSS:
#main {
position: fixed;
top: 50px;
height: 100px;
overflow: auto;
}
#header {
position: fixed;
top: 42px;
}
Live example here.
I found a few similar reports and suggestions about using -webkit-transform: translateZ(0). Interestingly, that doesn't fix it, but it does make the bug occur on Windows. Example here.
Any ideas?

Related

Nested "position: sticky" element not sticking in Safari, but works in iframe

I'm using CSS position: sticky to stick some elements to my page. I'm using <div>s to produce a grid-like structure (<table>s aren't appropriate to my use case). Please note that this is specifically a position: sticky question - I'm not looking for a Javascript solution, and I believe that position: sticky should work as desired based on the spec and the behaviour in other browsers.
I need to stick a row for vertical scrolling, and the first cell in that row for horizontal scrolling. If I use position: sticky; left: 0; on the first cell without sticking the row, the cell sticks to the left just fine. However, in Safari if I use eg.
.row {
position: sticky;
top: 10px;
width: ...
}
.cell {
position: sticky;
left: 0;
width: ...
}
the row sticks when vertically scrolling as desired but the cell does not stick when horizontally scrolling.
The code behaves as desired in Chrome and Firefox, and in an iframe in Safari.
Here's some code for a minimal example:
CSS:
.row {
position: -webkit-sticky;
position: sticky;
top: 10px;
white-space: nowrap;
width: 2000px;
z-index: 30;
}
.cell {
display: inline-block;
width: 100px;
}
.sticky {
position: -webkit-sticky;
position: sticky;
left: 0;
font-weight: bold;
}
HTML:
<div class="row">
<div class="cell sticky">Sticky</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
...
</div>
Uploaded files here (can't use codepen/jsfiddle as they load into an iframe):
https://qcn.github.io/minimal_sticky.html Minimal example: doesn't work in Safari, works in Chrome/Firefox
https://qcn.github.io/minimal_sticky_iframe.html The same minimal example loaded into an iframe: does work in Safari!
Another interesting thing I noticed was that if I scroll the page horizontally and then refresh, the sticky cell renders at the left of the viewport, and then scrolls normally in that position (ie. it still doesn't stick, but it knows where it should have been on page load!). This and the fact that the behaviour works inside an iframe and in other browsers makes me suspect it's a browser bug, but I'm unable to find other references to it.
Try adding a unit. It worked when I wanted to sticky a nested header to the top. I haven't tried your horizontal situation. Hope it helped.
left: 0px; instead of left: 0;
This appears to be an instance of this bug: https://bugs.webkit.org/show_bug.cgi?id=106062
I worked around my issue by wrapping the page in a scrolling div to contain it, rather than using viewport scroll. Not ideal but it appears to be a browser bug.
I finally found a solution to this!!!
using display: contents;
https://css-tricks.com/get-ready-for-display-contents/

How to stop mobile safari from setting fixed positions to absolute on input focus?

Disclaimer - I understand there exists questions around fixed elements in safari, and fixed elements weren't supported, but now are and so forth. However I can't find a question that addresses this exact question.
Given the simplest of fixed sidebars, something like:
.sidebar {
position: fixed;
top: 10px;
right: 10px;
}
And a relatively long page, with input elements.
When an input element is focused, any fixed element becomes absolute - I understand the why, safari is trying to declutter the viewport - thats fine, but not always appropriate. I ask that I get to choose the best experience for the user (i know best naturally).
So the Question..
Is there any way to leave fixed elements as fixed even when input elements are focused?
I have attempted to do a bit of $(window).on('scroll', magic and position elements manually on scroll, but its quite jittery on the ipad.
Safari has supported position: fixed since at least version 9.2, but if you're seeing difficult issues, you can fully create the fixed position effect by making the document element and body full screen and then using absolute positioning. Scrolling then occurs in some main container element rather than the body. Your "fixed" elements can exist anywhere in the markup using this method.
jsfiddle here
html,
body,
.mainContainer {
height: 100%;
width: 100%;
overflow: hidden;
margin: 0;
}
.mainContainer {
overflow: auto;
}
.fixed {
position: absolute;
bottom: 20px;
left: 20px;
}
In order to achieve the effect you desire you need to change your approach to the layout. Instead of positioning the sidebar with position:fixed you need to use position:absolute within a position:relative container that is set to the height of the viewport within that position:relative container you need another div that uses overflow-y: scroll and -webkit-overflow-scrolling : touch
Caveat: I generally avoid using position fixed on tablet & mobile if possible although the browser support is there, in my experience it'll be janky and javascript solutions leave a lot to be desired, my first response would be to challenge the pattern with the designer. If I'm given designs that include a position fixed element when there are input elements, I'm more likely to seek a design solution than a development one as the focus issues you're describing are difficult to circumvent and maintain a quality user experience.
THE MARKUP:
<div class="outer">
<div class="sidebar">
<ul>
<li>Dummy list nav or something</li>
</ul>
</div>
<div class="container">
<input type="text" />
<!-- I added 10000 inputs here as a demo -->
</div>
</div>
THE CSS:
html,body{
-webkit-overflow-scrolling : touch !important;
overflow: auto !important;
height: 100% !important;
}
.outer {
position: relative;
overflow: hidden;
/* I'm using Viewport Units here for ease, but I would more likely check the height of the viewport with javascript as it has better support*/
height: 100vh;
}
.sidebar {
position: absolute;
top: 10px;
right: 10px;
/*added bg colour for demo */
background: blue;
}
.container {
height: 100vh;
overflow-y: scroll;
-webkit-overflow-scrolling: touch
}
input {
display: block;
}
Here's a CodePen for you to open in your simulator (presentation view):
https://codepen.io/NeilWkz/full/WxqqXj/
Here's the editor view for the code:
https://codepen.io/NeilWkz/pen/WxqqXj

overflow:hidden not working on Chrome

I am working on testing a site on all browsers before starting device adapting with media queries.
I have found an issue: when any element is dynamically affected, the overflow:hidden property does not work anymore for that element on Chrome.
You can see it here: http://germanalvarez.net/5/
After loading the site, click on the MENU button on the bottom right of the panel, and click on any section:
If you are in Chrome, the top part of the panel (classified as .titlePanel) will no longer remain overflow:hidden, so the overflowed part of the icon will go out of the titlePanel (see image). This only happens when changing section.
If you are in Firefox, even after changing section it will remain hidden, so here, it works OK.
I found a supposed solution on the web: style elements on its tag. If you check my code you'll see .titlePanel has this opening tag, but it doesn't work either:
<div class="panel titlePanel expanded" style="overflow: hidden;">
This is caused by the use of position: fixed :
.titlePanel [class^="icon-"]:before,
.titlePanel[class*=" icon-"]:before {
font-size: 16em;
left: 79%;
line-height: 100%;
margin: 0 0 0 50px;
position: fixed;
}
As you're using fixed, your pseudo-element is totally out of the flow. It's no longer affected by any overflow: hidden on its parents.
To fix it, remove this fixed position and use absolute instead :
[class^="title-"] {
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}
[class^="title-"] i {
position: absolute;
right: 0;
top: 0;
}

IE 10 & 11 make fixed backgrounds jump when scrolling with mouse wheel

When you scroll with the mouse wheel in Windows 8 the fixed background image bounces around like crazy. This only affects IE 10 and IE 11. This affects elements with position:fixed as well.
Here is an example with a fixed background-image:
http://www.catcubed.com/test/bg-img-fixed.html
Here is example code:
#section{
position: fixed;
top:0;
left:0;
background-color:#eee;
background-position: top left;
background-image: url("images/7.png");
background-size: auto;
background-repeat: no-repeat;
z-index: 10;
}
Is there a solution to keep the background still in IE 10 and 11?
I know it is a bit late for an answer but I've had the same problem and was able to fix it by adding these attributes to my css file
html{
overflow: hidden;
height: 100%;
}
body{
overflow: auto;
height: 100%;
}
From the comments:
This solution stops scroll events from firing on the window, so do be careful if you're using anything that relies on such events firing. codepen.io/anon/pen/VawZEV?editors=1111 ( overflow: hidden, scroll events don't work) codepen.io/anon/pen/PNoYXY?editors=1111 ( overflow: auto, scroll events fire) - Dan Abrey
So this might cause some problems in your projects. But I don't see another way to workaround this bug in IE.
This looks like a z-index bug, try adding z-index: 1.
Looking into this, I've found the best way to debug is to:
Create a simple element at the top of the page, e.g.
<style>#test {position: fixed; background: red; top: 0; left: 0; width: 4em}</style>
<div id="test">Test</div>
In all the above cases, this works correctly, and the scroll is smooth. So this proves it can be done! Now slowly add your properties back in, until you are able to get the element with position fixed to work in the context of your site.
I then found that adding a z-index to the fixed items resolved the issue. (e.g. z-index: 1)
I also discovered that once a position is set on a child element, the bug presents it's self from that point down/onwards.
So you need to ensure none of the child elements have a position set,
or if they do, you explicitly set a position on each child.
E.g.
<!-- Works -->
<div style="position: fixed;">
<div>Nice</div>
<div>Wicked</div>
<div>Cool</div>
</div>
<!-- Element with position: relative, experiences the bug -->
<div style="position: fixed;">
<div style="position: relative;">sad</div>
<div>sad</div>
<div style="position: fixed;">happy</div>
</div>
It's fixable, but will require some tweaking!
Here is a workaround (tested on Windows 8.1):
Move the "background" CSS property to the BODY element. Currently it is on the DIV element with id="filler". Here is the resulting CSS:
body {
font-family: Helvetica, Arial, sans-serif;
background: #fff url(blue-kitty.jpg) no-repeat fixed center 100px;
}
#filler {
text-align: center;
}
.big-margin {
margin-top: 500px;
}
try to turn off smooth scrolling option.
Internet Options - Advenced Tab - Use Smooth Scrolling
it's like rendering bug.... MS IE team is investigating....
just simply define body container to relative.
<style>
body
{
position: relative;
}
</style>
The fix in my case was to simply remove the z-index property from the element that has position:fixed, IE then stopped the strange flickering.
(disabling smooth scrolling on IE options worked while having he z-index property but that's not a solution since users would most likely have it on by default).

z-index chrome bug

I'm experiencing a really annoying bug that seems to only happen on Windows and OS X: the z-index of an element whose parent has fixed position doesn't work on Chrome! I converted my odd situation to a simple code:
html:
<div id="mask">
</div>
<div id="box">
<div class="below-mask circle">
should be below the mask
</div>
<div class="above-mask circle">
should be above the mask
</div>
</div>​
css:
body {
font-family: Verdana;
font-size: 9px;
margin: 0px;
}
#box {
position: fixed;
}
#mask {
position: absolute;
left: 0px;
top: 0px;
background-color: rgba(0, 0, 0, 0.5);
width: 100%;
height: 100%;
z-index: 9998;
}
.circle {
position: relative;
background-color: rgba(255, 204, 0, 0.75);
border-radius: 75px;
line-height: 150px;
margin: 50px;
text-align: center;
width: 150px;
height: 150px;
}
.above-mask {
z-index: 9999;
}
.below-mask {
z-index: 9997;
}​
sandbox: http://jsfiddle.net/gibatronic/umbgp/
I tested on Internet Explorer 9, Firefox 15, Opera 12.02 and Safari 5.1.7 on OS X and Windows and all of them displayed as expected.
I also tested on Ubuntu 12.10 and it worked just fine for every browser including Chrome!
I even tested on Kindle 4 browser and it worked!
I wonder if anyone knows any kind of fix to workaround this issue!
one800higgins's answer is along the right lines. The real answer is that on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is auto. So the stacking context hierarchy looks like this:
document root (z-index 0)
#mask (z-index 9998)
#box (z-index 0)
.above-mask (z-index 9999)
.below-mask (z-index 9997)
That means that 9998 is never compared with 9999 or 9997 to determine stacking order. Instead, 9999 is compared with 9997 to determine which of .above-mask and .below-mask is further in front, and then once everything inside #box is stacked in that context, it's treated as a single layer at z-index 0 which gets stacked behind #mask at z-index 9998.
This also explains why #TheNextBillGates's answer of moving #mask inside #box works - because then #mask is in the same stacking context as .above-mask and .below-mask. I highly recommend the above link for more comprehensive details, and you should also see the announcement for the stacking change for fixed elements in Chrome.
I just came across this bug, and its still happening in Google Chrome v26. I could set the z-index as high as I wanted to from code or Chrome's CSS editor and it made no difference (and the element's position was set to absolute). The same z-index setting was working as expected in Firefox and even IE8-IE10. When I switched the parent element from position:fixed to position:absolute then the child element's z-index worked fine in Chrome.
If you move the #mask inside of the #box it works just fine.
<div id="box">
<div id="mask"> </div>
<div class="below-mask circle">should be below the mask</div>
<div class="above-mask circle">should be above the mask</div>
</div>
Here's a fiddle http://jsfiddle.net/TheNextBillGates/jKm4b/
Not sure why this is just yet.
Assign a z-index to your fixed div. That should cause chrome to respect the z-index values for all it's children as well.
The multiple z-index stacks is unfortunate and confusing in my opinion, however you may be able to solve this without changing your html structure if you raise the z-index of any of the target element's parents. Try to find a parent element that is a sibling of the troublesome element overlapping your content. Apply this styling:
position: relative; z-index: [# higher than overlapping element's z-index];
Your milage may vary depending on your project, however this solution worked for my project.
I think its because its not at the bottom of the page like modal windows are suppose to be. Easy fix is to just grab all of the modal windows and throw them into a div before the ending body tag. Example below fixes every chrome issue i have.
$('body').append('<div id="modelContainer" />');
$('.modal').each(function() {
$(this).appendTo('#modelContainer');
})
Change or remove the position: fixed on #box, and you're set.
jsFiddle

Resources