Safari position:sticky not working in an overflow:auto element - css

According to CanIUse, there is a known issue with Safari and position:sticky inside an overflow:auto element:
A parent with overflow set to auto will prevent position: sticky from working in Safari
However, this is the exact use case that I need. I have a scrollable div, which is subdivided into two columns. The right column should be sticky and never move, even when the entire div is scrolled. The reason I'm using position:sticky on the right column is that I want the user to be able to still scroll the left column with the cursor on the right column. And this was the only solution that I found to have worked.
A working example for Firefox / Chrome is here:
http://cssdeck.com/labs/zfiuz4pc
The orange area remains fixed while scrolling, but in Safari it doesn't.
The example above has some unnecessary wrappers to my issue, but I wanted to replicate as closely as possible the environment where I want to have this code working in. The basic gist of it is I have this:
<div class="modal-content">
<div class="left-content">
</div>
<div class="sticky-element">
</div>
</div>
And the CSS:
.modal-content {
display: flex;
overflow: auto;
flex-flow: row nowrap;
}
.left-content {
flex: 0 0 300px;
}
.sticky-element {
position: sticky;
top: 0;
right: 0;
width: 200px;
}
Again, this works in FF/Chrome but not in Safari. Is there a workaround to get it to work in all browsers? Or is there a different approach I can use to maintain scrollability even with the mouse cursor over the sticky element?

simply add position: -webkit-sticky;

Adding display: block to the .sticky-element worked for me without having to add position: -webkit-sticky. Found this solution at this Codepen.

I got this solution from someone else:
http://cssdeck.com/labs/bu0nx69w
Basically, instead of position:sticky, use position:fixed for the right panel. The key is to also you will-change:transform in a parent div (in the above example, in .modal-content) so position:fixed becomes fixed relative to that parent, and not the viewport. It's a neat little trick

I had a similar case:
<div scroll>
<div sticky />
<list />
</div>
Just wrap the scroll content with a div worked like a charm:
<div scroll>
<div>
<div sticky />
<list />
</div>
</div>

I had to use below to make it work in both Chrome and Safari:
position: sticky;
position: -webkit-sticky;
display: block;

position: sticky will not work, if your parent element has overflow: hidden. having this sticky setting, it will have automatically transform your element from relative to actual fixed to the top border of the document.

Another solution for this specific case, so long as you don't need the scroll bar on the far right of the modal.
Since your sticky element is the same height as your .modal-content, you could remove sticky altogether from .sticky-element. First, remove overflow:auto from .modal-content, then add that style to .left-content since that's the part you want to scroll anyway.

i cant really test this for safari right now but this has always been an alternative for me when creating a sticky footer for example:
<!DOCTYPE html>
<html>
<head>
<title>sticky side div</title>
<style type="text/css">
.maindiv{
position: relative;
display: inline-block;
background-color: forestgreen;
width: calc(100vw - 150px);
height: 100%;
overflow: auto;
}
.sidediv{
position: fixed;
display: inline-block;
background-color: lightyellow;
float: right;
width: 100px;
height: 100%;
}
</style>
</head>
<body>
<div class="maindiv">
Lorem 45
</div>
<div class="sidediv">
Lorem 30
</div>
<div class="maindiv">
Lorem 100
</div>
<div class="maindiv">
Lorem 900
</div>
</body>
</html>
once you know the width of your right content add a little more px to it then use the css calc function to make sure the other div's don't flow in to it
also there is a known bug with vh and vw in Safari 7. You can fix it by setting height: inherit on the #child elements whose parents have vh heights or vw widths
but my best recommendation if you were not going for cross browser support will be to use CSS Grids

Related

HTML/CSS Footer not sticking to bottom moving on screen resize

I have the following attempt, trying to make a simple sticky footer.
My problem is the footer is not sicking to the bottom, I suspect it might be a css problem.
Would greatly appreciate it if someone can give the following code a scan and provide some advise.
#footer { /* position must be absolute and bottom must be 0 */
height: 100px;
width: 100%;
background: red;
position: absolute;
bottom: 0;
}
<footer class="footer" id="footer">
<div class="footLeft" style="width:75%; float:left;">
</div>
<div class="footerRight" style="width:25%; float:right; padding:25px;">
<button class="btn btn-danger" style="font-size:20px;">Sign Up</button>
</div>
</footer>
The Problem Im having / Output
Add the following rules to body
body {
min-height:100%;/*or 100vh */
position:relative;
}
Explanation:
The min-height property will make sure that the body at least takes 100% of your viewport height. This way even if you have less content your footer will always stick to the bottom of viewport.
Position: relative rule is set so that the footer is positioned absolute relative to the body and not any other wrapper
You can just use this native class to achieve sticky footer in bootstrap--
<div class="footer navbar-fixed-bottom">
Another possibility is using position:fixed, without influencing the body css.
In that case the footer would be always at the bottom of the page event if a scrollbar is present
Example
#footer { /* position must be absolute and bottom must be 0 */
height: 100px;
width: 100%;
background: red;
position: fixed;
bottom: 0;
}
See fiddle

Background of a div inside another one with "white-space: nowrap;" does not cover all the width

Ok, I've got a problem out there. To be short, here's a fiddle. I'll repeat myself here:
HTML:
<div class="container">
<div class="selected">
<span>Why don't you cover all the width!?</span>
</div>
<div>
<span>Little content</span>
</div>
</div>
CSS:
.container {
width: 100px;
white-space: nowrap;
background-color: #0f0;
overflow-x: auto;
height: 200px;
}
.selected {
background-color: #f00;
white-space: nowrap;
}
The first question is: why does not the inner div's background cover the entire span?
The second one: I'd like to have a fix, of course.
And one more thing: the html elements are generated by a third-party tool, to which I have no access, which makes "wrapping it all in another div" thing impossible. Only CSS, only hardcore!
UPDATE:
By the way, the container is itself resizable (a frame inside a frameset to be precise).
EDIT:
I've updated the fiddle in order to provide more info. The problem is, that when the second div will be selected, I'd like the red background to stretch to the width of the longest line.
UPDATE 2:
The above described problem can be solved with display: table-row; (see here). The tricky thing is to make this work even if content is less wide than the container itself (a fiddle).
Divs have width:auto by default. So the inner div is 100px wide, like the outer one. The span overflows out of the div.
In this particular case, the easiest solution is to give the inner div display:inline-block
div div {display:inline-block}
so that it no longer fits itself in its parent, but it moulds itself to the width of its contents.
Updated fiddle.
Edit: to answer your second question: yes, the display:inline-block stops the selected div from being as wide as the container.
Fortunately, that can be corrected by adding
min-width:100%;
in addition to the display:inline-block. See more updated fiddle.
Another edit:
And the question keeps changing. Now it's about frames in a frameset. Oh well.
Here is the latest fiddle that solves the problem as formulated now. But let's see what changes the future has in store...
I think you just need to apply the background color to the span instead of the div.
http://jsfiddle.net/M294p/8/
HTML:
<div class="container">
<div class="selected">
<span>Why don't you cover all the width!?</span>
</div>
<div>
<span>Little content</span>
</div>
</div>
CSS:
.container {
width: 100px;
white-space: nowrap;
background-color: #0f0;
overflow-x: auto;
height: 200px;
}
.selected {
background-color: #f00;
white-space: nowrap;
display:inline-block;
}
The answer to your first question is because you have explicit width to the parent div. You can apply display: inline-block to inner div and remove the width: 100px from the parent.
HTML
<div>
<div class="test">
<span>Why don't you cover all the width!?</span>
</div>
</div>
CSS
.test {
background: red;
display: inline-block;
}
An example : http://jsfiddle.net/M294p/6/

`absolute` child does not relate to `relative` parent when parent is `table-cell` - only firefox

Situation
html:
<div class="container">
<div class="parent">
<div class="child">x</div>
</div>
</div>
css:
.container {
display: table;
}
.parent {
display: table-cell;
position: relative;
}
.child {
position: absolute;
right: 0;
}
What I expect:
the .child should be positioned to the right edge of .parent. Works in Chrome.
What I get in Firefox:
the .child is positioned to the right edge of the closest "non static" parent which is has not display: table-cell.
Fiddle
http://jsfiddle.net/SYG5k/2
Question
Why does display: table-cell influence the positioning of child elements, or, why is position: relative ignored on table-cell elements? Can I work around this if I rely on table-cell?
You need to put position: relative; in your parent.
So in the code in your question add position: relative; to .container
Or in your jsfiddle add position: relative; to .parent
.parent {
height: 150px;
width: 450px;
display: table;
margin-top: 400px;
background: #bbb;
position:relative;
}
Related : Firefox ignores absolute positioning in table cells and Positioning context on table-cell element in Firefox
About your questioning 'why' : It's no more a 'block' level element. It's a table-cell so positioning will behave in a different way (in this case, with firefox).
See this to understand deeper about 'tables' behaviors
http://jsfiddle.net/SYG5k/12
Add a wrapper to your absolute element and make it relative, so you will have something like table-cell > relative wrapper > absolute element
http://jsfiddle.net/SYG5k/13/
<div class="rel">
a
<div class="absolute">x</div>
</div>
.foo, .rel {
position: relative;
}
This is a work around I can't explain why it doesn't work normally. Perhaps someone else will answer that for you
Edit : my mistake the wrapper is supposed to wrap everything in the cell, it's what I originally wanted to code, more of a typo. I updated the fiddle above
A work around may be to use an inner div with a width and height of 100%, and set that to position:relative;
HTML:
<div class="parent">
<div class="cell foo">
<div class="cellInner">
a
<div class="absolute">x</div>
</div>
</div>
CSS:
.cellInner{
position:relative;
width:100%;
height:100%;
}
Updated JS Fiddle: http://jsfiddle.net/SYG5k/11/
I was adding a popup menu that appears on each row of the table as the user mouses over it when I ran into this FF problem. Based on the very useful info above, I ended up putting a div wrapper inside the table cell in each row where I wanted my absolutely positioned popover menu to located, and set its display property to relative. My JS then adds the absolutely position menu inside the div as each row is rolled - it has to be a child of the the relatively positioned div, of course. Note that the div will shrink-wrap the td's content rather than filling the td as I expected, but no matter, you then have a relative context, and you can use top and left on the absolutely positioned child element to locate it exactly where you want it with respect to the table cell.

Chrome: overflow:auto + margin:auto fails to layout correctly sometimes

I'm trying to layout a page which has anchor elements that I would like on a new line and centered. However these blocks are inside of <p> elements which are beside floating images.
Right:
http://test.sunnysidemarket.ca/right.jpg
Wrong:
http://test.sunnysidemarket.ca/wrong.jpg
So basically I have:
HTML:
<div class="content">
<div>
<img src="..." width="276" height="207" />
</div>
<div class="body">
<p>
...
<a class="mediaset" href="...">Link</a>
</p>
</div>
</div>
CSS:
.content img {
float: right;
}
a.mediaset {
margin: 0 auto;
width: 220px;
display: block;
overflow: auto;
}
Or what you can see in the jsfiddle: http://jsfiddle.net/CVkFw/
The issue is intermittent, sometimes it happens, sometimes it doesn't. What it appears to me to be is a bug in chrome where the overflow and margin properties are calculated but when the floating content loads, sometimes the browser doesn't layout the elements again.
There are ways of solving this using jQuery and modifying my HTML but I would really love to solve this with CSS if at all possible.
My best guess is that this erratic behavior is caused by overflow: visible applied in global.styles.css. The problem:
.node-article .field-name-body,
.node-synced-facebook-content .field-name-body {
overflow: visible;
}
I'm offering this suggestion because when I add this CSS override for overflow: hidden, that component appears to load "more solidly". The fix:
.node-article .field-name-body,
.node-synced-facebook-content .field-name-body {
overflow: hidden;
}
The selector itself might need to be adjusted depending on what it is intended to affect. (I'm obviously not that familiar your page's css code.) Hopefully this points you in the right direction though!

How to auto adjust the <div> height according to content in it?

I have a <div> which needs to be auto adjusted according to the content in it. How can I do this? Right now my content is coming out of the <div>
The class I have used for the div is as follows
box-centerside {
background:url("../images/greybox-center-bg1.jpg") repeat-x scroll center top transparent;
float:left;
height:100px;
width:260px;
}
Just write "min-height: XXX;" And "overflow: hidden;" & you will be out of this problem
Like this
min-height: 100px;
overflow: hidden;
Try with the following mark-up instead of directly specifying height:
.box-centerside {
background: url("../images/greybox-center-bg1.jpg") repeat-x scroll center top transparent;
float: left;
min-height: 100px;
width: 260px;
}
<div class="box-centerside">
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
This is sample content<br>
</div>
Just write:
min-height: xxx;
overflow: hidden;
then div will automatically take the height of the content.
I've used the following in the DIV that needs to be resized:
overflow: hidden;
height: 1%;
You could try, div tag will auto fit height with content inside:
height: fit-content;
just use following
height:auto;
I have made some reach to do auto adjust of height for my project and I think I found a solution
[CSS]
overflow: auto;
overflow-x: hidden;
overflow-y: hidden;
This can be attached to prime div (e.g. warpper, but not to body or html cause the page will not scroll down) in your css file and inherited by other child classes and write into them overflow: inherit; attribute.
Notice: Odd thing is that my netbeans 7.2.1 IDE highlight overflow: inherit; as Unexpected value token inherit but all modern browser read this attribute fine.
This solution work very well into
firefox 18+
chorme 24+
ie 9+
opera 12+
I do not test it on previous versions of those browsers. If someone will check it, it will be nice.
If you haven't gotten the answer yet, your "float:left;" is messing up what you want. In your HTML create a container below your closing tags that have floating applied. For this container, include this as your style:
#container {
clear:both;
}
Done.
Don't set height. Use min-height and max-height instead.
Simple answer is to use overflow: hidden and min-height: x(any) px which will auto-adjust the size of div.
The height: auto won't work.
simply set the height to auto, that should fix the problem, because div are block elements so they stretch out to full width and height of any element contained in it. if height set to auto not working then simple don't add the height, it should adjust and make sure that the div is not inheriting any height from it's parent element as well...
Set a height to the last placeholder div.
<div class="row" style="height:30px;">
<!--placeholder to make the whole block has valid auto height-->
Min- Height : (some Value) units
---- Use only this incase of elements where you cannot use overflow, like tooltip
Else you can use overflow property or min-height according to your need.
I just used
overflow: hidden;
And it was worked for me properly. This div had some of float lefted divs.
<div> should expand automatically. I guess that the problem is that you're using fixed height:100px;, try replacing it with min-height:100px;
use min-height instead of height
I have fixed my issue by setting the position of the element inside a div to relative;
height:59.55%;//First specify your height then make overflow auto
overflow:auto;
For me after trying everything the below css worked:
float: left; width: 800px;
Try in chrome by inspecting element before putting it in css file.
Most of these are great answers, but I feel that they are leaving out one inevitable aspect of web-development which is the on-going page update. What if you want to come and add content to this div? Should you always come to adjust the div min-height? Well, whilst trying to answer these two questions, I tried out the following code instead:
.box-centerside {
background: url("../images/greybox-center-bg1.jpg") repeat-x scroll center top transparent;
float: left;
height: auto; /* adjusts height container element according to content */
width: 260px;
}
furthermore, just for a sort of bonus , if you have elements around this div with properties like position: relative; , they would consequently stack on top of this div, because it has property float: left; To avoid such stacking, I tried the following code:
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr); /* number depends on how many columns you want for a particular screen width. */
height: auto; /* adjusts height container element according to content */
}
.box-centerside {
background: url("../images/greybox-center-bg1.jpg") repeat-x scroll center top transparent;
height: auto; /* adjusts height container element according to content */
width: 100%;
}
.sibling 1 {
/* Code here */
}
.sibling 2 {
/* Code here */
}
My opinion is that, I find this grid method of displaying more fitting for a responsive website. Otherwise, there are many ways of achieving the same goals; But some of the important goals of programming are to make coding simpler and more readable as well as easier to understand.
There is no need to set such as min-height any more, only set work well:
overflow: hidden
You Can Try Using fit-content This Works In Every Browser
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fit According To Div</title>
<style>
.test {
/* Use This Code */
width: fit-content;
block-size: fit-content;
/* You Can Also Try height: fit-content */
height: auto;
border-radius: 13px;
border-style: solid;
overflow: auto;
border-color: rgb(174, 174, 235);
}
</style>
</head>
<body>
<div class="test" autofocus>
<form>
<script src="https://checkout.razorpay.com/v1/payment-button.js" data- payment_button_id="pl_JfhYZeSvyVFaIf" async></script>
</form>
</div>
</body>
</html>

Resources