CSS stacking order, transform element breaks absolute sibling - javascript

How to apply a transform to element without affecting position: absolute sibling. Been playing with this for a few hours to no avail. I think the code will explain clearer than I can put into words.
The below works as intented, until transform: translateX(10px) is applied to the ul. I need the transform to move the ul based on screen size, it's a longer list in reality. Can the hover state be preserved? Thanks, webstudent
.relative {
position: relative;
}
nav {
min-width: 100vw;
height: fit-content;
overflow: hidden;
}
ul {
display: block;
min-width: 100vw;
list-style-type: none;
margin: 0;
padding: 0;
/* breaks stacking order */
/* transform: translateX(10px); */
}
li {
display: inline-block;
}
li a {
display: block;
padding: 4px 8px;
font-size: 1rem;
max-height: 1rem;
}
li a:hover {
background-color: red;
}
.absolute-sibling {
position: absolute;
left: 0;
top: calc(1rem + 8px);
width: 100vw;
height: fit-content;
display: none;
}
li a:hover + .absolute-sibling,
.absolute-sibling:hover {
background-color: red;
display: block;
}
<div class="relative">
<nav>
<ul>
<li>
<a>text one</a>
<!-- absolute child of .relative -->
<div class="absolute-sibling">content one</div>
</li>
<li>
<a>text two</a>
<!-- absolute child of .relative -->
<div class="absolute-sibling">content two</div>
</li>
<li>
<a>text three</a>
<!-- absolute child of .relative -->
<div class="absolute-sibling">content three</div>
</li>
</ul>
</nav>
</div>
Broken version with transform included, jsfiddle to reduce wall of code. Same code, apart from transform: translate(10px);
Update:
This describes the issue I'm trying to counter CSS stacking contexts
Also, for instance if I replace the transform: translateX(10px); with margin-left: 10px; everything is as intended. Just I'd like to use the transform for animation smoothness.

Heres one more solution, set the transform on your parent component div.relative and remove it from the ul. (you could also wrap that div and transform that if it works better for your layout)
Change this line in your css
.relative {
position: relative;
transform: translateX(10px)
}
If this still breaks your design then you need to rethink your HTML. As per your article setting a transform creates a new stacking context causing these weird effects. By setting the transform on a parent or wrapper element then you are moving that context up the chain and the child elements should behave like normal.

Related

How do I scroll in a <div> - within a fixed <div>

I have a div which has to scroll. The problem is that it's within a fixed div.
I tried to fix this in different ways, I went through these posts:
Div with scrollbar inside div with position:fixed
Have a fixed position div that needs to scroll if content overflows
but none of them worked for me.
I'd like to test it with you guys and find out what's the problem.
I am working on a mobile responsive website.
It has a nav menu button that opens .list div up - when clicking the menu button.
I inserted the div of the .list right after the nav bar.
When the menu opens it doesn't show all list items in my tag.
I have to give my main div .list different height sizes and I find it not so efficient.
I will paste my relevant code part of the nav bar, and the relevant CSS parts.
HTML:
<div class="list">
<h2 id="cat-header"> ALL CATEGORIES</h2>
<ul class="sports">
<li class="mainli"></li>
<li class="mainli"></li>
<li class="mainli"></li>
</ul>
</div>
CSS:
.sports{
/*display: none;*/
padding: 0 ;
background-color: #fff;
margin: 0;
width:100%;
/*height: 210%*/
-webkit-overflow-scrolling: touch;
}
.list{
width: 99.9%;
/* overflow: hidden; */
/* overflow-y: scroll; */
/* top: 65%; */
overflow-x: hidden;
/*overflow-y: scroll;*/
height: 75%;
display: none;
-webkit-overflow-scrolling: touch;
}
when clicking #mob-menu-btn it opens .list and makes my whole tag fixed:
$('#mob-menu-btn').click(function(){
var isHidden = $('.sports').is(':visible');
if (isHidden){
$( "body" ).removeClass( "makeFixed" );
} else {
$( "body" ).addClass( "makeFixed" );
}
$('.list').slideToggle("fast");
})
my .makeFixed looks like this:
.makeFixed{
position: fixed;
}
I tested this last, and it didn't solve my problem:
.makeFixed{
position: fixed;
top: 0;
bottom:0;
overflow-y:scroll;
overflow-x:hidden;
}
and changed height: auto; and overflow-y: scroll; within .sports and .list.
What might be the problem?
I have a problem with the following:
if (isHidden){
$( "body" ).removeClass( "makeFixed" );
} else {
$( "body" ).addClass( "makeFixed" );
}
having the following CSS:
.makeFixed{
position: fixed;
}
Which means you are fixing the body to... the body? Here is my suggestion:
// I'll keep your HTML intact
<div class="list">
<h2 id="cat-header"> ALL CATEGORIES</h2>
<ul class="sports">
<li class="mainli"></li>
<li class="mainli"></li>
<li class="mainli"></li>
</ul>
</div>
// Your list will be your fixed element. It might be better to call this your nav.
.list {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
transition: height 500ms;
overflow-x: hidden;
}
// I add an active state for it. It will also nicely animate thanks to the previously named transition.
.list.active {
height: 99%;
}
// I only toggle the .active class on the click of the mobile button
$('#mob-menu-btn').click(function(){ $(".list").toggleClass("active"); });
This way you simplify your menu quite a bit. You animate with CSS, you have a simple wrapper that determines where your menu will be positioned and how, and the contents will push the overflow to be scrollable if they are larger.
Also, 'overflow: auto' is unnecessary, I have not come across a need for this. Heres an example where the yellow area is fixed to be very heigh so the scrolling will work, but the gist is the same (actually, I've adjusted all values to make the example more visually obvious):
window.onload = function(){
document.getElementById("button").addEventListener("click", function(){
if(document.getElementById("list").className == "active"){
document.getElementById("list").className = "";
} else {
document.getElementById("list").className = "active";
}
});
}
#list {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
transition: height 500ms;
overflow-x: hidden;
background: blue;
}
#list.active {
height: 80%;
}
#list ul {
height: 3000px;
background: yellow;
}
#button {
z-index: 4;
position: absolute;
top: 10px;
left: 10px;
background: #fff;
}
<div id="button">click me</div>
<div id="list">
<h2 id="cat-header"> ALL CATEGORIES</h2>
<ul class="sports">
<li class="mainli"></li>
<li class="mainli"></li>
<li class="mainli"></li>
</ul>
</div>
Use overflow: auto; on the div that you want to scroll, if the div have right height this will work
Give the height to the div with overflow-y:scroll !important and
like
write your div like this..
<div style="overflow-y:scroll !important;height:80px;">
/*your scrollable content
</div>
Try position the list by using
.list{
width: 99.9%;
/* overflow: hidden; */
/* overflow-y: scroll; */
/* top: 65%; */
overflow-x: hidden;
/*overflow-y: scroll;*/
height: 75%;
display: none;
-webkit-overflow-scrolling: touch;
position: fixed;
z-index:99999;
}
Try this..
<h2 id="cat-header">ALL CATEGORIES</h2> <div style="overflow-y:scroll ;height:80px;border:1px solid #000"> <ul class="sports"> <li class="mainli">hello</li> <li class="mainli">hello</li> <li class="mainli">hello</li> </ul> </div>

Display none takes up space

I'm having some trouble with my Pagination nav that is display:none. When I check on inspect element it takes no space, but for some reason, where the pagination nav is, there's an empty space that is not supposed to be there.
I've tried adding overflow:hidden, visibility:none, height:0, but none of it it's working.
Maybe it's something to do with position relative and absolute, I don't understand it very well yet.
themeexp1.tumblr.com
Edit: It's not the 14px margin, it's a much bigger margin
Empty space: http://postimg.org/image/hiixhonoh/
HTML
<div id="content">
<div class="container" id="{postID}">
<div class="container-overlay"></div>
<div class="photo inner">
<a href="{permalink}">
<img src="{block:indexpage}{PhotoURL-500}{/block:indexpage}{block:permalinkpage}{PhotoURL-HighRes}{/block:permalinkpage}" alt="{PhotoAlt}">
</a>
</div>
</div>
<nav id="pagination">
<ul>
{block:PreviousPage}<li>Previous page</li>{/block:PreviousPage}
{block:NextPage}<li><a id="nextPage" href="{NextPage}">Next page</a></li>{/block:NextPage}
</ul>
</nav>
</div>
CSS
#content{
margin: 0 auto;
position: relative;
}
.container{
margin-bottom: 14px;
}
.container-overlay{
width: 100%;
height: 100%;
opacity: 0;
position:absolute;
}
.icons{
opacity: 0;
position: absolute;
left: 50%;
top: 50%;
width: 100%;
text-align: center;
}
#pagination{
display: none;
position: absolute;
}
It's hard to tell what you want without a demo, but there is space at the bottom because your .container div has margin-bottom: 14px;.
Example Fiddle

Responsive navigation inside a fixed width

I am using a responsive navigation solution called Naver (http://formstone.it/components/Naver) for my websites. However, I am running into issues when I use the responsive navigation in a fixed width (like a grid for example). The responsive navigation takes the width of it's parent element and doesn't show at 100% width.
Here are two examples, one with the navigation inside of a grid and one just floated to the right:
http://jsfiddle.net/9FCq2/11/
http://jsfiddle.net/9FCq2/10/
Note: I have a couple of external resources in each of those fiddles.
I'm wondering how I can somehow adjust my CSS or JavaScript to make my responsive dropdown show at 100% when clicked on, no matter what the width of the parent element.
HTML
<div class="clearfix">
<div class="float-left">
<a href="http://concisecss.com">
<img src="http://concisecss.com/images/logo.svg" alt="Concise Logo" width="150" />
</a>
</div>
<div class="float-right">
<nav class="nav-responsive">
<ul class="list-inline list-unstyled">
<li>Welcome
</li>
<li>Why Concise
</li>
<li>Get Started
</li>
<li>Documentation
</li>
<li>Add-Ons
</li>
</ul>
</nav>
</div>
</div>
CSS
.naver .naver-handle {
color: inherit;
cursor: pointer;
display: none;
font-size: 24px;
font-size: 1.5rem;
line-height: 1;
text-align: right;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.naver .naver-wrapper {
height: auto;
}
.naver.enabled .naver-handle {
display: block;
}
.naver.enabled .naver-wrapper {
height: 0px;
overflow: hidden;
}
.naver.enabled .naver-wrapper ul li {
display: block;
padding: 8px;
text-align: left;
width: 100%;
}
.naver.enabled .naver-wrapper ul li:hover {
background: #f9f9f9;
}
.nav-responsive.naver .naver-handle:after {
content:"\f0c9";
font-family: FontAwesome;
text-align: right;
}
Naver jQuery library: http://formstone.it/components/Naver/jquery.fs.naver.js
You need to give the nav and it's top container width of 100%. By doing this you guarantee that both will take 100% of your screen's width (or whatever is the container both are in)
for your first jsfiddle use .naver-wrapper{width:100%;} because naver-wrapper is the top parent for your navigation. Check here
while in your second example you have to give both the navigation and the top container (parent) width:100% Check here
.naver-wrapper{width:100%;}
.float-right{width:100%;}
Use Below CSS. I hope this is useful for you:
CSS
.naver.enabled .naver-wrapper{
overflow: hidden; position: absolute; left: 0px; width: 100%; }

Make an <li> element stretch wider than the containing <ul>

At the moment, I'm developing a layout for work, and I'm just a tiny bit stuck with a dynamic drop down menu. I'm using a child 'ul' within an 'li' element that will display the children of the navigation links - but the 'li' above (so the main one, that you hover on to view the children), stretches to the length of the 'ul', which is, of course, defined by the width of the 'li' elements inside that.
Also, I'm using jQuery to display the child items when the user hovers over the parent navigation item.
However, I need this not to happen! Here's a screenshot link: http://d.pr/v5Wk (I'm sorry - I'm not registered, so I can't post images! D: )
Basically, I need to get rid of the gap on the right of 'Section One', dynamically, without defining any preset widths.
Here's the HTML:
<div class="menu">
<ul class="navigation">
<li>
Section One
<ul class="children">
<li>
Child Item One
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
</ul>
</li>
<li>
Section Two
</li>
<li>
Section Three
</li>
<li>
Section Four
</li>
<li>
Section Five
</li>
<li>
Section Six
</li>
</ul>
</div>
And here's the CSS:
.menu { width: 100%; overflow: hidden; display: block; position: absolute; margin: 75px auto; background: #666 url('../image/stripe.png'); }
ul.navigation { list-style-type: none; width: 900px; margin: 0 auto; }
ul.navigation li a { color: #fff; text-decoration: none; display: block; padding: 10px; }
ul.navigation li a:hover { color: #fff; background: #444 url('../image/stripe_active.png');}
ul.navigation li { float: left; }
ul.navigation li ul.children { list-style-type: none; display: block; overflow: hidden; position: relative; z-index: 1; }
ul.navigation li ul.children li { color: #fff; float: left; font-size: 11px; white-space: nowrap; }
Any help on this would be great!
Many thanks,
Matt
ul.navigation li ul.children {
list-style-type: none;
display: block;
overflow: hidden;
position: absolute;
z-index: 1;
top: 2em;
left: auto;
right: auto;
}
If you still can't see them, add height: 5em to ul.navigation
Position:Absolute causes an element to be rendered at a specific spot on the page, taking it out of the normal flow. Since it is no longer being rendered inside the topnav li, it doesn't cause it's width to be too large.
Have you tried to position:absolute the children?
Does it need to be an ul/li solution? wouldn't it be easier to update the contents of the submenu with javascript when you hover over the top nav?

CSS Floats On Same Line Variable Amount

I want to have horizontal lists that can run as wide as possible but within a fixed width container. I am using jQuery to allow scrolling on the really wide list, and overflow:automatic for users without javascript.
I have code along the lines of this:
<div class="list">
<ul>
<li class="feed">
<section>
<h1><span class="name">Title</span></h1>
<div class="scroll_left"><a class="ir" href="#">Scroll Back</a></div>
<div class="article_list">
<ul class="article_list">
<li>
<a href="article.php">
<div class="article_thumb"><img src="img/placeholder.png" alt="blah" /></div>
<h2>Title of article</h2>
</a>
</li>
<li>
<a href="article.php">
<div class="article_thumb"><img src="img/placeholder.png" alt="blah" /></div>
<h2>Title of article</h2>
</a>
</li>
<li>
<a href="article.php">
<div class="article_thumb"><img src="img/placeholder.png" alt="blah" /></div>
<h2>Title of article</h2>
</a>
</li>
<!-- variable number of li's, from 10s to 100s -->
</ul>
</div>
</section>
</li>
<!-- More of these lists -->
</ul>
</div>
I'll just give a subset of my css that I think is relevant:
.feed .article_list {
position: relative;
overflow: auto;
float: left;
width: 900px;
}
.feed .article_list ul {
position: relative;
width: 10000px; /** I want this to be wide, but not allow scrolling past the end*/
margin: 0;
background-color: #ffffff;
}
.feed .article_list li {
display: block;
width: 130px;
height: 150px;
position: relative;
float: left;
border-right: 2px solid #b5e8f4;
border-left: 2px solid #b5e8f4;
margin: 0 5px 0 0;
}
My javascript is:
$(document).ready(function() {
$('div.article_list').css({
'overflow' : 'hidden'
});
$('.scroll_left a').click(function() {
toScroll = $(this).parent().next();
toScroll.animate({scrollLeft: "-=135"});
return false;
});
$('.scroll_right a').click(function() {
toScroll = $(this).parent().prev();
toScroll.animate({scrollLeft: "+=135"});
return false;
});
});
So as it is, I either have to make the inner ul really wide, so users can scroll well beyond the list items, or I can restrict it but if I add too many items (dynamically, so I don't have a lot of control), then the layout breaks.
Can I somehow get that scrollable area to just be as wide as its floated contents?
Or is the only solution to set the width in javascript (less than ideal, but I can do that)?
Its the float: left on the .feed .article_list that you really don't want but I've removed it from all of them that I could.
I would move to an inline setup instead of floating:
.feed .article_list {
position: relative;
overflow: auto;
width: 100%; /* specify what ever width you want. I think 100% is proper. */
}
.feed .article_list ul {
position: relative;
overflow-x: scroll;
margin: 0;
background-color: #ffffff;
white-space: nowrap;
}
By making the overflow-x: scroll you have a permanent scroll bar (not totally necessary, it can be removed if you prefer). The white-space: nowrap Will keep the children on one line (instead of floating.)
.feed .article_list li {
display: inline-block;
// etc. etc. etc. ...
on the children display: inline-block; will let you specify height/width like a block element and keep them inline at the same time.
JsFiddle:- http://jsfiddle.net/GBtCb/
UPDATE :-
In an effort to make it cross-browser compatible make the following changes:
remove the overflow: auto from .feed .article_list
and add:
.feed
{
overflow: hidden;
}
.article_list
{
overflow: auto;
from quirksmode.com:
http://www.quirksmode.org/css/whitespace.html : white-space: nowrap is compatible IE7+.
-

Categories