CSS transform and fixed positioning in Safari - css

I'm having troubles with fixed positioning, css transformed container and Safari. I'm trying to display a dropdown list when I click an item, inside a modal. The modal bears a css transform. To make sure the dropdown list is always displayed over the modal, I position it as fixed (I calculate the left and top values using JS).
It works as expected in Chrome, Firefox and Opera, but Safari shows a strange behaviour. According to the W3C:
Any computed value other than none for the transform results in the
creation of both a stacking context and a containing block. The object
acts as a containing block for fixed positioned descendants.
So a fixed element inside a CSS transformed container should be positioned relatively to this container, instead of the viewport. But it seems that Safari does not behave like this. See this example :
$(document).ready(function() {
$(".show-liste").click(function() {
$(".liste").show();
});
});
.modale {
height: 50px;
overflow-y: scroll;
transform: translate(100px);
}
ul {
position: fixed;
left: 0px;
top: 0px;
}
/* --- Purely style related stuff ---- */
body {
font-size: 80%;
}
.modale {
position: absolute;
top: 50px;
padding: 60px;
background-color: white;
border: 1px solid #ccc;
box-shadow: 2px 2px 2px #ddd;
}
button {
width: 200px;
}
ul {
list-style-type: none;
margin-top: 0;
padding-left: 0;
width: 200px;
display: none;
box-shadow: 2px 2px 2px #ddd;
}
li {
background: white;
padding: 10px 20px;
border: 1px solid #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="modale">
<div class="row">
<div>
<button class="show-liste">Open dropdown</button>
<ul class="liste">
<li>Choice 1</li>
<li>Choice 2</li>
<li>Choice 3</li>
<li>Choice 4</li>
<li>Choice 5</li>
</ul>
</div>
</div>
</div>
Do you have any idea how to fix this ? Any polyfill, any way to get round this issue ? USing absolute positionning is the solution I'd like to avoid, as it would imply moving the list at the document's body level, and then handling it's creation / destruction, attached model (I'm using AngularJS), events, etc. That's really my last resort.

I believe you can get the desired cross-browser behavior by using position:absolute instead of position:fixed.

Related

Perfectly overlapping round divs

I have a list which has round elements in it. They have a image in the background and on hover the other div is supposed to become visible as an overlay. It works so far, however there is still a visible border, indicating that the hovered div is not perfectly overlaying the other rounded element.
HTML:
<ul>
<li>
<div class="hover"></div>
</li>
<li>
<div class="hover"></div>
</li>
<li>
<div class="hover"></div>
</li>
</ul>
CSS:
ul {
margin: 0;
padding: 0;
list-style: none;
font-size: 0;
height: 140px;
}
li {
width: 140px;
height: 140px;
margin: 0;
padding: 0;
display: inline-block;
border-radius: 70px;
background: url(http://www.nationalflaggen.de/media/flags/flagge-thailand.gif);
}
.hover {
border-radius: 70px;
width: 140px;
height: 140px;
}
.hover:hover {
background-color: rgba(255,255,255,.9);
}
I added a fiddle since I really don't know how to make them perfectly overlapping.
Thanks for your help.
UPDATED THE FIDDLE:
http://jsfiddle.net/pL9Aa/1
Looks like a sub-pixel problem -- the browser does a bunch of math to determine the smoothness of a curve using square pixels. And sometimes it doesn't render how you might expect.
You can simply remove the border-radius rule from the :hover pseudo class if you are keeping it transparent.
.hover {
width: 140px;
height: 140px;
}
Fiddle
If it needs to be round, I would override your image using the same element, instead of a nested element, like so:
li:hover {
background: white;
}
Fiddle2
You could add:
li:hover {
background:none;
}
to ensure that the background on the li is gone.
It's weird though - does look like a rendering bug.
Assuming that you are going to have text or other content in the overlay, it's worth noting that setting the background to be slightly transparent (e.g. rgba(255,255,255,0.8)) makes the rendering error less noticeable.
Just change #hovers border-radius: 62px;
If your hover is only meant to cover the element, you do not need to put a border-radius on the hover element. Simply removing that line will resolve your issue:
.hover {
width: 140px;
height: 140px;
}
http://jsfiddle.net/pL9Aa/3/
If in the production envirionment you can actually use a background color, you could also use a box-shadow
demo: http://jsfiddle.net/j4NFB/
.hover:hover {
background-color: #FFF;
box-shadow: 0 0 0 1px #fff;
}

How do I correct fixed positioning for a sidebar in Firefox?

I have following HTML in my webpage where I want to keep the sidebar fixed on the left side.It works fine in the Chrome but Firfox isn't displaying the sidebar as fixed :
<div id="sidebar">
<!-- Logo -->
<div >
<h1>Heading</h1>
</div>
<!-- Nav -->
<nav id="nav">
<ul>
<li><a href="#target1" >About</a></li>
<li><a href="#target2" >Works</a></li>
<li><a href="#target3" >Our Team</a></li>
<li><a href="#target4" >Contact</a></li>
</ul>
</nav>
</div>
the CSS for above code is :
#sidebar
{
position: fixed;
top: 0;
padding: 3em 1.35em 1em 1.15em;
height: 100%;
width: 12em;
background: #364050 ;
box-shadow: inset -0.1em 0em 0.35em 0em rgba(0,0,0,0.15);
}
please suggest me some solution so that the sidebar will remain fixed in Firefox.
Check your body css tags, the metas, and anything that could affect to that div. Maybe there is another css rule overwriting that 'position'
Also, if you have css3 tags or errors in the body css, for example, transform: translate3d(0px, 0px, 0px); that could make fixed position break in Firefox.
filter on the current element or any parent will cause position fixed break on Firefox. Remove it or find another way to not to use filter directly
i think you should try to make some changes in you css
try this css
#sidebar
{
position: fixed;
top: 0;
padding: 10px;
bottom:0;
left:0;
width:200px;
background: #364050 ;
box-shadow: inset -0.1em 0em 0.35em 0em rgba(0,0,0,0.15);
}
i do not prefer to use em for element dimensions it should be in px you can use em foe font size etc.
#sidebar
{
position: fixed;
top: 0;
left:0;
padding: 3em 1.35em 1em 1.15em;
height: 100%;
width: 12em;
background: #364050 ;
box-shadow: inset -0.1em 0em 0.35em 0em rgba(0,0,0,0.15);
}
it works fine on google chrome but on firefox, You need to Add The properties (Top ,Bottom ,Left,Right ) for the fixed div
like this
top : 0;

Parts of content remain visible despite overflow:hidden

I have an issue regarding a div with overflow: hidden. It is positioned relative and it's child div is positioned absolute. On hover, the parent div changes from overflow:hidden to overflow:visible. This enables the child div to display properly.
The issue: although everything else works just great, when the mouse is no longer over the parent div (thus overflow is now hidden again), bits of the child div are still shown in their place. They are not actually displayed, because if I select some text or objects near them the dissapear completely. It's as if the page needs a "refresh" of some kind.
Has anyone else come accross this? I'm kind of stuck on this...
UPDATE: I made a jsfiddle with the issue and realised it's only occuring on webkit based browsers (Chrome and Safari). I still have no idea why, though...
<div class="list-name">
<ul>
<li class="truncated">
<a href="">
Hover me to see all the magic thext I'm hidding
</a>
</li>
</ul>
</div>
It would seem that an extra overflow:hidden added to the hyperlink solves the issue. Check it out in this fiddle.
That looks like a bug in rendering, not why it works like that. Developer tools show it like mouse is still hovered above the element. Possibly there some element became to wide/high and mouse out event can't happen. But if you remove position:relative;, position:absolute; and replace top/left with margin-top/margin-left - everything works nice to me:
http://jsfiddle.net/Nt5bN/13/
CSS:
.list-name ul {
margin: 50px;
padding: 0;
list-style: none;
}
.list-name li {
display: block;
float: left;
width: 60px;
height: 29px;
overflow: hidden;
background: #eee;
}
.list-name a {
width: 300px;
display: block;
float: left;
}
.list-name li.truncated:hover {
overflow: visible;
}
.list-name li.truncated:hover a {
margin-top: -3px;
margin-left: -8px;
background: #fff;
z-index: 9999;
padding: 2px 0 2px 7px;
border-radius: 3px;
border: 1px solid #ddd;
}

CSS navigation with cut-out notch as marker

I know I have seen this somewhere before, but I am trying to create a black fixed navbar with a marker that is transparent cut-out triangle. I need help getting the triangle cut-out to be transparent to the background, so when you scroll the page, you can see through to the content beneath:
I have a standard list/anchor navigation with a javascript to move the .current class depending upon the page section:
<div class="navbar">
<ul>
<li class="current"><a>home</a></li>
<li><a>products</a></li>
<li><a>services</a></li>
<li><a>contact us</a></li>
</ul>
</div>
styled with the following CSS:
.navbar {
width: 100%;
position: fixed;
background: black;
float: left;
}
ul, li {
list-style: none;
margin: 0;
padding: 0;
float: left;
}
a {
padding: 10px 20px 20px;
}
.current a {
background: transparent url('../img/wedge-red.png') center bottom no-repeat;
}
The only way I can think to do it is to add extra divs on either side of the ul and assign the background to them, and then use a transparent png with a cutout as the background of the li a's.
Is there a way to do this without getting really ugly like that, and adding extra divs?
Try CSS pseudo elements!
Add 2 free DOM elements before and after an existing element in the DOM. Ideal in cases when you don't want to add stuff to your markup to satisfy styling needs.
CSS Markup
.item:before {
content:"";
display: inline-block;
width: 20px;
height: 20px;
background-color: silver;
}
.item:after {
content:"";
display: inline-block;
width: 20px;
height: 20px;
background-color: gray;
}
HTML
<div class="item">Content</div>
Check this JSFiddle for a demo.
Make sure you set content: "" and display:block in order to see them.
Here's what I ended up with -- extending the borders and cropping them with overflow: hidden; (a little hacky, but it works and doesn't add elements to the DOM):
.navbar {
width: 100%;
height: 60px;
position: fixed;
overflow: hidden;
}
ul {
border-left: solid black 2000px;
border-right: solid black 2000px;
position: absolute;
top: 0;
left: 50%;
margin-left: -2000px;
}
The above worked nicely for my purposes, and behaves in a responsive environment.
The other answer on this page, using :before and :after pseudo elements didn't work for my purposes. It ended up being too fussy, the pseudo elements wouldn't align properly, and kept wrapping to the next line when the browser window was resized. That solution as suggested works with fixed-width elements, not percentages as was specified in the original question.

unable to get the scroll when position:fixed -- elements disappears form the screen

Top Bar (fixed) - As seen on twitter and facebook,tried to mimic the same on a web project that i'm working on -- no matter how much i try,the content disappears beyond scroll.Tried this tutorial http://www.sohtanaka.com/web-design/facebook-style-footer-admin-panel-part-1/
but,the contents in that overlaps when resolution is changed or when on zoom.Do not want that -- as we see on twitter/FB - want the scroll to come up on zoom (or lower resolutions)
Been flocking around this issue since 2days with no positive outcome.
Here is the test code that i've edited from the tutorial --
<html>
<style type="text/css">
#footpanel {
position: fixed;
top: 0; left: 0;
z-index: 9999;
background: #e3e2e2;
border: 1px solid #c3c3c3;
border-top: none;
width: 100%;
height: 25px;
}
#footpanel ul {
padding: 0; margin: 0;
float: left;
width: 100%;
list-style: none;
border-bottom: 1px solid #fff; /*--Gives the bevel feel on the panel--*/
}
#footpanel ul li{
padding: 0; margin: 0;
float: left;
position: relative;
}
#footpanel ul li a{
padding: 5px;
float: left;
height: 16px; width: 36px;
text-decoration: none;
color: black;
position: relative;
}
#footpanel a.home{
width: 50px;
padding-left: 40px;
border-right: 1px solid #bbb;
text-indent: 0; /*--Reset text indent since there will be a combination of both text and image--*/
}
#footpanel a.chat{
width: 126px;
border-left: 1px solid #bbb;
border-right: 1px solid #bbb;
padding-left: 40px;
text-indent: 0; /*--Reset text indent since there will be a combination of both text and image--*/
}
#footpanel li#chatpanel, #footpanel li#alertpanel { float: right; } /*--Right align the chat and alert panels--*/
</style>
<div id="footpanel">
<ul id="mainpanel">
<li>A </li>
<li>B </li>
<li>C </li>
<li>D </li>
<li>E </li>
<li>P </li>
<li>V </li>
<li id="alertpanel">S</li>
<li id="chatpanel">F (<strong>18</strong>)</li>
</ul>
</div>
</html>
What is happening -- on zoom(or lower resolution) the contents of the footpanel is coming out (i can prevent this with overflow:hidden , but that's not what i want) of the container(footpanel)
What i want it to do -- like twitter/FB,i want a scroll to come in and the footpanel to save its layout and not fall out of place.
Please help
--CSS beginner
I can't think of a way to do this in pure CSS and Twitter seems to use Javascript to achieve that effect.
First, set the same min-width on #footpanel and the body. You may also want to set the heights of your various items to auto or em equivalents so they resize nicely on zoom and text resize.
Then put this Javascript on your page:
<script type="text/javascript">
function hscrollbar() {
/* First, we need the horizontal scroll position of the viewer's display,
but there are different ways to call it in JS depending on browser.
I'm using the if/else shorthand notation to detect if a call is legit:
somevar = (statement) ? statement_true_value : statement_false_value */
var left =
/* window.pageXOffset should work for most recent browsers: */
window.pageXOffset ? window.pageXOffset :
/* If it DOESN'T, let's try this: */
document.documentElement.scrollLeft ? document.documentElement.scrollLeft :
/* And if THAT didn't work: */
document.body.scrollLeft;
/* Now that we have the horizontal scroll position, set #footpanel's left
position to NEGATIVE the value, so it APPEARS to follow the scroll: */
document.getElementById('footpanel').style.left = -left;
}
window.onscroll = hscrollbar; /* Call the function when the user scrolls */
window.onresize = hscrollbar; /* Call the function when the window resizes */
</script>
Remove all comments in gray to unbloat the code!
Just in case somebody stumbled upon this answer (like me) and didn't find #LucyLou's answer working (with all respect), I got it working from #Vimal's answer on another question:
Don't need to set the min-width and put this Javascript instead:
$(window).scroll(function(){
$('#footpanel').css('left',-$(window).scrollLeft());
});

Resources