CSS using z-index doesn't place child element behind its parent - html

I am trying to make a drop down menu that slides from header.
I have a header and inside it I have some div with border-bottom 1px line and background-color. Inside this div I would like to place logo, searchbox some links and a user profile button. When this button is clicked I would like to drop down menu below this button. Unfortunately this dropdown menu appears in front of header and not slides from behind of header (obscuring the header background and bottom-border line). I have tried solution like below (it is simplified version).
header {
position: relative;
z-index: 5;
}
.dropdown {
background-color: yellow;
width: 100px;
height: 100px;
position: absolute;
z-index: 1;
}
.background {
position: absolute;
background-color: #ccca;
border-bottom: 1px solid black;
width: 100%;
height: 50px;
z-index: 2;
}
<header>
<div class="background">
<div class="dropdown">
</div>
</div>
</header>
I have tried many z-index configurations and none of them seems to work.
1. div.background with z-index 2, div.dropdown with z-index 1 or even -1
2. div.background without z-index and position, div.dropdown with z-index -1 (here dropdown was behind header but menu links stopped working and menu was also behind main content of webpage)
How can I make my div.dropdown to slide from behind the header bar with background and border bottom line? Isn't it possible to have this div.dropdown inside header div tree as the descendant element.

This is possible with a negative z-index; however, it doesn't work with a parent element that has a non-auto z-index. Set the .background element to have a z-index:auto (or just take it off. auto is the default). It's OK (and recommended imo) to have an ancestor element with a positive z-index to avoid your negative z-indexed element dropping below the <html> or <body> elements. In this case, you do (header has a z-index of 5), so it's fine.
<html>
<head>
<style type="text/css">
header {
position:relative;
z-index:5;
}
.dropdown {
background-color: yellow;
width: 100px;
height: 100px;
position: absolute;
z-index: -1;
}
.background {
position: absolute;
background-color:#ccca;
border-bottom: 1px solid black;
width: 100%;
height: 50px;
z-index: auto;
}
</style>
</head>
<body>
<header>
<div class="background">
<div class="dropdown">
</div>
</div>
</header>
</body>
</html>

z-index is based on elements at the same level in the DOM, in other words, elements with the same parent.
Since your class="dropdown" element is a child of the class="background" element it can never be below its parent.

Child elements cannot be displayed under their parent. Make the two divs seperate elements like this.
header {
position:relative;
z-index:5;
}
.dropdown {
background-color: yellow;
width: 100px;
height: 100px;
position: absolute;
z-index: 1;
}
.background {
position: absolute;
background-color:#ccca;
border-bottom: 1px solid black;
width: 100%;
height: 50px;
z-index: 2;
}
<html>
<head>
</head>
<body>
<header>
<div class="background"></div>
<div class="dropdown"></div>
</header>
</body>
</html>

Related

Fixed position issue and z-index: how to make a child of a sticky element "on top" of a (unrelated) fixed element? [duplicate]

This question already has answers here:
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 8 months ago.
What I'm trying to do is placing the <button> element on top of the <div> element and, at the same time, place the <nav> behind the <div>. In other words, anything but the <button> should be visible.
Demo: https://play.tailwindcss.com/DW91IdO9dL
A sticky <nav> element with position: sticky
The <nav> has a <button> child with position: relative; z-index: 30
A <div> element with position: fixed; z-index: 20
Of course, this isn't working, <button> isn't visible at all, despite the greater z-index. I guess because the <nav> crate a new stacking context. Setting a z-index: 30 on the <nav> itself would show the <button>, but also other <nav> elements and its background color:
This is the HTML structure, but I can change as I wish (place the <div> before/after):
<nav style="position: sticky">
<button style="position: relative; z-index: 30"></button>
</nav>
<div style="position: fixed: z-index: 20"></div>
What you're trying to do isn't possible. What I would suggest is to have the nav set with no background color or z-index. Add another div to your nav and use that as a background color. You can then set the z-index of every element in the nav set lower than the div. But set the button's index higher.
Edit: Here's a working example:
https://codepen.io/kenjibailly/pen/wvyNYqx
HTML:
✕
<div></div>
CSS:
nav {
width: 100%;
position: relative;
background: white;
}
nav > div:last-child {
background: white;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
nav > div {
width: 100px;
height: 20px;
background: green;
margin-top: 5px;
}
button {
color: white;
position: relative;
z-index: 3;
background: red;
}
nav + div {
position: fixed;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: blue;
}
This has already been answered here in a different but similar context:
can I override z-index inheritance from parent element?

Issue with fixed positioned header and href

I am struggling with in-page links and fixed header.
I have a sticky header (position fixed) of 50px. This allows me to have the header always visible even if scrolling down in the page.
In my page, I have then a menu with links to other sections in the page.
I used href with IDs target.
Problem is that when I click on the link, the page positions the target at the very top of the page, where the header hides my target section for 50px.
The code below shows the issue
<html>
<head>
<style>
.header {
position: fixed;
top: 0px;
right: 0;
left: 0;
margin-left: auto;
margin-right: auto;
background-color: red;
height: 50px;
}
.container1 {
content: none;
height: 200px;
background-color: green;
}
.container2 {
content: none;
height: 800px;
background-color: lightblue;
}
</style>
</head>
<body>
<div class="header">header</div>
<div class="container1"></div>
<div class="container2">
block1
<div id="block1">Some text</div>
</div>
</body>
This is just how anchors work.
To achieve your goal, try giving the target a padding of your header height. That will fix it.
#block1 {
padding: 60px 0;
}

How do I position a div under a fixed position div

I have a position:fixed div at the top of my page, so that when a user scrolls down the menu always stays at the top.
How do I position another div element underneath the fixed div.
I'm using CSS and HTML.
I'm using a smooth scrolling jQuery and need each section header to appear just under the menu bar.
Something like this — http://codepen.io/sergdenisov/pen/pJyMGb:
HMTL:
<div class="menu">
<div class="menu-item">Home</div>
<div class="menu-item">About</div>
<div class="menu-item">Demo</div>
<div class="menu-item">Contact</div>
</div>
<div class="menu-item menu-item_sub">Contact</div>
CSS:
body {
height: 2000px;
}
.menu {
position: fixed;
background: blue;
width: 100%;
}
.menu-item {
display: inline-block;
padding: 30px;
}
.menu-item_sub {
position: fixed;
left: 0;
top: 60px;
}
Do everything in absolute position domain.
.1(class){
position: absolute;
left: 10px;
top20px;
}
Like above classify each object with a class and set their position.

CSS Positioning

I have a header at the top that holds the following css rule:
position: fixed;
I also have some images that hold (and need to hold) the following css rule:
position: relative;
The problem is that my header always sits at the top of the page as the user scrolls, but when they get to the image (with position:relative) this sits on top of my header. But the header should always be on top. Is there another css rule I can apply to allow this to happen?
That problem might be with z-index. Give your header z-index:999999999 and your problem will be solved.
There is no need to set position as relative or absolute. You can use the following code:
<html>
<head>
<title>Document Edit</title>
</head>
<style type="text/css">
body {
padding: 0px;
margin: 0px;
}
.wrap {
width: 100%;
height: 1500px;
background-color: #DDD;
}
.header {
width: 100%;
height: 60px;
background-color: #004080;
position: fixed;
}
.imgdiv {
width: 400px;
height: 400px;
float: left;
background-color: green;
}
</style>
<body>
<div class="wrap">
<div class="header"></div>
<div class="imgdiv"><img src="error1.png" width="400" height="400"></div>
</div>
</body>
</html>
In your header CSS add z-index property:
with:
z-index:10 // can be any number but should be greater than the z-index of image
in image CSS add:
z-index:5; //should be less than the z-index of header
Just set in CSS z-index: 9999 to the header div.

Link fragment not working on fixed positioned target

Im making a 1 page website so my menu has link fragments that move you to the correct section of the page.
My issue is that the bottom section has fixed positioning meaning that the link fragment doenst work. Ive added bottom padding to the body so when you scroll down it appears the last section is underneith the rest of the page content. What solutions are there for this?
I could just use JavaScript to scroll down the page when the link is clicked, but im not sure what the impact for screen readers or other usability devises is in doing this.
http://codepen.io/anon/pen/pKulL
<div id="menu">
One
Two
Three
Four
Five
Last
</div>
<div id="one">
One
</div>
<div id="two">
Two
</div>
<div id="three">
Three
</div>
<div id="four">
Four
</div>
<div id="five">
Five
</div>
<div id="last">
Last
</div>
#one, #two, #three, #four, #five {
border: 3px solid red;
background: grey;
width: 100%;
height: 300px;
z-index: 2;
position: relative;
}
#last {
position: fixed;
bottom: 0;
border: 3px solid green;
background: yellow;
z-index:1;
width: 100%;
height: 300px;
}
body {
padding-bottom: 300px;
}
#menu {
position: fixed;
top: 0;
right: 0;
z-index: 3;
background: white;
}
The problem is not that #last is not being linked to, it is that it has a lower z-index. When you link to it, that div remains hidden behind the other divs. You just need to change the z-index when you click on the #last link. You can alternatively use scrollTop to move to the bottom of screen and display the #Last div by moving the others out of the way.
To be clear about position
relative flows the element normally, but allows the position to be set relative to its normal position using the values set on the top, left, right, and bottom properties.
absolute places the element relative to the edge of its most recently positioned parent element. This element will be the body of the document or the element within which it is nested if that element's positioning has been set.
Using your example I have updated it so that clicking on #last will make that div appear.
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$( document ).ready( function() {
$("#last-link").click(function() {
//$("#last").css("z-index", "3")
$("html, body").animate({ scrollTop: $(document).height()-$(window).height() }, "fast");
});
$("a:not(#last-link)").click(function() {
$("#last").css("z-index", "1")
});
})
</script>
<style type="text/css" media="all">
#one, #two, #three, #four, #five {
border: 3px solid red;
background: grey;
width: 100%;
height: 300px;
z-index: 2;
position: relative;
}
#last {
position: fixed;
bottom: 0;
border: 3px solid green;
background: yellow;
z-index:1;
width: 100%;
height: 300px;
}
body {
padding-bottom: 300px;
}
#menu {
position: fixed;
top: 0;
right: 0;
z-index: 3;
background: white;
}
</style>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div id="menu">
One
Two
Three
Four
Five
Last
</div>
<div id="one">One</div>
<div id="two">Two</div>
<div id="three">Three</div>
<div id="four">Four</div>
<div id="five">Five</div>
<div id="last">Last</div>
</body>
</html>
I think ive found a solution. Making the link fragment target statically positioned, and having the div within it fixed positioned seems to work.
You can't make this work with fixed position, because when click the link, html retrieves the current position #last and scroll's the page to that position. Since, your #last div is in visible area, html doesn't scroll all the way down. You gotta have to use js to make it work.