Sticky position not works as expected. works as buggy - html

I am trying to use the stick position with my header part. on scroll it works with couple of side move. then the header hides. it should be always in the top for my requirement. i have give z-index as well in higher value. any one help me to understand the issue.
HTML:
<div class="wrapper">
<div class="navi">Navigation</div>
<header>Header goes here</header>
<div class="container">
<div class="child1">Chile-1</div>
<div class="child2">Chile-2</div>
<div class="child3">Chile-3</div>
<div class="child4">Chile-4</div>
<div class="child4">Chile-5</div>
<div class="child4">Chile-6</div>
<div class="child4">Chile-7</div>
</div>
</div>
css:
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
.wrapper {
height: 100%;
position: relative;
}
.container {
border: 2px solid blue;
height: 100%;
}
.navi {
border: 2rem solid lightpink;
}
header {
background-color: gray;
padding: 1rem;
top: 0;
left: 0;
right: 0;
position: sticky;
z-index: 100;
}
.container > div {
height: 50%;
border: 1px solid red;
}
.child1 {
background-color: brown;
}
.child2 {
background-color: yellow;
}
.child3 {
background-color: lightblue;
}
.child4 {
background-color: greenyellow;
}
Live demno

when adding 100% height to .wrapper and .container, the height get computed as below picture (838px in my case).. and when scroll crosses 838px, the header looses the sticky property.. when you set to auto, height will be computed automatically (adding all the divs' height) and it works expected..
height as 100%
height as auto

html,
body {
padding: 0;
margin: 0;
}
.wrapper {
position: relative;
}
.navi {
border: 2rem solid lightpink;
}
header {
top: 0;
padding: 1rem;
z-index: 100;
position: sticky;
background-color: gray;
}
.container>div {
padding: 30px;
position: relative;
z-index: 0;
}
.child1 {
background-color: brown;
}
.child2 {
background-color: yellow;
}
.child3 {
background-color: lightblue;
}
.child4 {
background-color: greenyellow;
}
<div class="wrapper">
<div class="navi">Navigation</div>
<header>Header goes here</header>
<div class="container">
<div class="child1">Chile-1</div>
<div class="child2">Chile-2</div>
<div class="child3">Chile-3</div>
<div class="child4">Chile-4</div>
<div class="child4">Chile-5</div>
<div class="child4">Chile-6</div>
<div class="child4">Chile-7</div>
<div class="child4">Chile-7</div>
<div class="child4">Chile-7</div>
<div class="child4">Chile-7</div>
<div class="child4">Chile-7</div>
<div class="child4">Chile-7</div>
<div class="child4">Chile-7</div>
</div>
</div>

Related

CSS How to smooth transition between two headers

I have a project that contains a header. This header consists of a certain background color and text color. These colors aren't going well with one part of the website. So I want to transition the header to different colors. But I want the colors to change gradually at the border and not swap immediately.
The headers should transition from one color to the other at the border of the container when entering and leaving. But I don't seem to get this to work.
body {
height: 300rem;
margin: 0;
padding: 0;
}
#main-container {
width: 100%;
height: 100%;
background-color: red;
}
#header {
width: 100%;
height: 2rem;
background-color: blue;
position: sticky;
top: 0;
}
#someDiv {
position: relative;
width: 100%;
height: 20rem;
background-color: purple;
margin-top: 30rem;
}
#headerSomeDiv {
width: 100%;
height: 2rem;
background-color: green;
color: white;
position: sticky;
top: 0;
}
<body>
<div id="main-container">
<div id="header">
<h1>HEADER</h1>
</div>
<div id="someDiv">
<div id="headerSomeDiv">
<h1>HEADER</h1>
</div>
</div>
</div>
</body>
position:fixed can do this
body {
height: 300rem;
margin: 0;
}
#main-container {
height: 100%;
background-color: red;
clip-path:inset(0); /* to clip the position:fixed to its container */
overflow:auto;
}
#header,
#headerSomeDiv{
width: 100%;
height: 2rem;
background-color: blue;
position: fixed;
top: 0;
}
#headerSomeDiv {
background-color: green;
color: white;
}
h1 {
margin:0;
}
#someDiv {
position: relative;
height: 20rem;
background-color: purple;
margin-top: 30rem;
clip-path:inset(0); /* to clip the position:fixed to its container */
}
<body>
<div id="main-container">
<div id="header">
<h1>HEADER</h1>
</div>
<div id="someDiv">
<div id="headerSomeDiv">
<h1>HEADER</h1>
</div>
</div>
</div>
</body>

why the div id="wrap" moves when we give margin top to inside div class=''header"

Why the div id="wrap" moves when we give margin top to inside div class="header" ? Please explain why the div moves?
* {
margin: 0;
padding: 0;
}
#wrap {
height: 200px;
background: #000;
}
.header {
height: 200px;
width: 200px;
margin-top: 20px;
background: #F00;
}
<div id="wrap">
<div class="header">
d
</div>
</div>
Use overflow:auto or overflow:hidden on wrapper. This will basically prevent margin to collapse.
* {
margin: 0;
padding: 0;
}
#wrap {
height: 200px;
background: #000;
overflow:auto;
}
.header {
height: 200px;
width: 200px;
margin-top: 20px;
background: #F00;
}
<div id="wrap">
<div class="header">
d
</div>
</div>
* {
margin: 0;
padding: 0;
}
#wrap {
height: 200px;
background: #000;
}
.header {
height: 200px;
width: 200px;
margin-top: 20px;
background: #F00;
}
<div id="wrap">
<div class="header">
<center> d </center>
</div>
</div>
The div moves because of the child's margin which is relative positioned.
If you want the #wrap div not to be pushed down, set its position to absolute. Try the snippet below
* {
margin: 0;
padding: 0;
}
#wrap {
height: 200px;
background: #000;
position: absolute;
}
.header {
height: 200px;
width: 200px;
margin-top: 20px;
background: #F00;
}
<div id="wrap">
<div class="header">
d
</div>
</div>
You can read more about css positions here

Getting CSS :hover on overlapping siblings

This is easiest to understand when running the code below. I'm looking to trigger the hover state on both a column and the middle row when hovering over the red bar.
I'd like to keep the columns based on flex and have the bar absolutely positioned over them.
Is this possible?
EDIT:
I'd like just the column that the mouse is hovering over to turn blue. Sorry for the ambiguity. Snippet updated with desired result.
The columns are divided by a white line. Hover over a grey area to see the column highlighted.
Thanks.
.root {
width: 100px;
height: 100px;
background: grey;
position: relative;
display: flex;
}
.column {
display: flex;
flex: 1 1 auto;
border-right: 1px solid white;
}
.column:hover {
background: blue;
}
.bar {
position: absolute;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
background: red;
}
.bar:hover {
background: green;
}
.green {
background: green;
}
.blue {
background: blue;
}
Hover over the middle of the square. I want the middle column to turn blue and the bar to turn green.
Right now, only the bar turns green.
<div class='root'>
<div class='column'>
</div>
<div class='column'>
</div>
<div class='column'>
</div>
<div class='bar'>
</div>
</div>
Desired result:
<div class='root'>
<div class='column'>
</div>
<div class='column blue'>
</div>
<div class='column'>
</div>
<div class='bar green'>
</div>
</div>
Final Edit:
I'm providing a fully fleshed out version of what my use case is. I don't think CSS will be able to solve this, but I've accepted an answer that works for my original question.
function enterColumn() {
document.getElementById('column-status').innerHTML = 'In column'
}
function leaveColumn() {
document.getElementById('column-status').innerHTML = 'Out of column'
}
function enterBar() {
document.getElementById('bar-status').innerHTML = 'In bar'
}
function leaveBar() {
document.getElementById('bar-status').innerHTML = 'Out of bar'
}
.root {
width: 100px;
height: 100px;
background: grey;
position: relative;
display: flex;
}
.column {
display: flex;
flex: 1 1 auto;
border-right: 1px solid white;
}
.column:hover {
background: blue;
}
.bar-container {
position: absolute;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
}
.bar {
position: absolute;
top: 0;
bottom: 0;
background: red;
}
.bar:hover {
background: green;
}
.green {
background: green;
}
.blue {
background: blue;
}
Hovering over a column or bar should be independent. Right now you can never have the 'In column' and 'In bar' status at the same time :(
<br />
It should scale to support any number of columns and any number of bars (where bars can be absolutely positioned anywhere along the x-axis)
<br />
Javascript events should be called on mouse events for both columns and bars.
<div class='root'>
<div class='column' onmouseenter='enterColumn();' onmouseleave='leaveColumn()'>
</div>
<div class='column' onmouseenter='enterColumn();' onmouseleave='leaveColumn()'>
</div>
<div class='column' onmouseenter='enterColumn();' onmouseleave='leaveColumn()'>
</div>
<div class='bar-container'>
<div class='bar' style='left: 5px; right: 40px' onmouseenter='enterBar();' onmouseleave='leaveBar()'>
</div>
<div class='bar' style='left: 65px; right: 5px' onmouseenter='enterBar();' onmouseleave='leaveBar()'>
</div>
</div>
</div>
<div id='column-status'>
Out of column
</div>
<div id='bar-status'>
Out of bar
</div>
There you go, after 2 hours of trial and error I finally came up with this little hack.
.root {
width: 100px;
height: 100px;
background: grey;
position: relative;
display: flex;
}
.column {
display: flex;
flex: 1 1 auto;
border-right: solid #fff 1px;
}
.column:hover {
background: blue;
}
.column .toggle{
margin-top:33px;
height: 33px;
width: 100%;
}
.column .toggle:before{
content: "";
position: absolute;
width: 34px;
height: 33px;
}
.column .toggle:hover:after{
content: "";
position: absolute;
z-index: 10;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
background: green;
pointer-events:none;
}
.bar {
position: absolute;
z-index: 1;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
background: red;
pointer-events:none;
}
<div class='root'>
<div class='column'><div class='toggle'></div></div>
<div class='column'><div class='toggle'></div></div>
<div class='column'><div class='toggle'></div></div>
<div class='bar'></div>
</div>
Now if you need to bind some javascript events to the .bar element, attach them to .toggle instead.
If rearrangement of divs is allowed, you can position the .bar just before the middle .column and use adjacent sibling selector.
.bar:hover + .column {
background: blue;
}
.root {
width: 100px;
height: 100px;
background: grey;
position: relative;
display: flex;
}
.column {
display: flex;
flex: 1 1 auto;
border-right: 1px solid white;
}
.column:hover {
background: blue;
}
.bar {
position: absolute;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
background: red;
}
.bar:hover {
background: green;
}
.bar:hover + .column {
background: blue;
}
.green {
background: green;
}
.blue {
background: blue;
}
<div class='root'>
<div class='column'>
</div>
<div class='bar'>
</div>
<div class='column'>
</div>
<div class='column'>
</div>
</div>
If I understand what you mean, you mean that if you hover over any element the .column should turn blue and .bar should turn green. If that's the case then actually its pretty simple. Just place your hover event on .root element instead like so:
.root {
width: 100px;
height: 100px;
background: grey;
position: relative;
display: flex;
}
.column {
display: flex;
flex: 1 1 auto;
border-right: 1px solid white;
}
.bar {
position: absolute;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
background: red;
}
.root:hover .bar {
background: green;
}
.root:hover .column {
background: blue;
}
<div class='root'>
<div class='column'>
</div>
<div class='column'>
</div>
<div class='column'>
</div>
<div class='bar'>
</div>
</div>
If that' not the case and you want the color of the .column to change when you hover over the .bar then check out the snippet below. Note that I've a changed the HTML markup a bit. Since .bar has position: absolute so it won't affect at all where you place it inside the .root element.
.root {
width: 100px;
height: 100px;
background: grey;
position: relative;
display: flex;
}
.column {
display: flex;
flex: 1 1 auto;
border-right: 1px solid white;
}
.bar {
position: absolute;
left: 0;
right: 0;
top: 33px;
bottom: 33px;
background: red;
}
.bar:hover {
background: green;
}
.bar:hover ~ .column {
background: blue;
}
<div class='root'>
<div class='bar'>
</div>
<div class='column'>
</div>
<div class='column'>
</div>
<div class='column'>
</div>
</div>
Let me know if that helps you :-)

Second DIV on all remaining space

I want to create two divs, one under other without JS and with IE8 support.
Each has 100% width.
Each with relative or absolute positioning for nested layout.
Top div have height by content, not fixed (it is important) and bottom div on whole leftover space.
In my example bottom div is too short, how i can stretch it to bottom?
<html>
<head>
<style type="text/css"><!--
* {
padding: 1px;
margin: 0px;
border: solid 1px;
width: 100%;
}
#super {
position: absolute;
height: 100%;
}
#top {
position: relative;
}
#bottom {
position: relative;
top: 0px;
bottom: 0px;
}
--></style>
</head>
<body>
<div id="super">
<div id="top">top</div>
<div id="bottom">bottom</div>
</div>
</body>
</html>
You can use css table properties to create this layout.
HTML:
<div id="super">
<div id="top">
<div class="content">
top
</div>
</div>
<div id="bottom">
<div class="content">
bottom
</div>
</div>
</div>
Necessary CSS:
html,
body {
height: 100%;
}
#super {
height: 100%;
width: 100%;
display: table;
}
#super > div {
display: table-row;
}
#top {
background: green;
}
#bottom {
background: blue;
}
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
#super {
height: 100%;
width: 100%;
display: table;
}
#top {
background: green;
overflow: hidden;
height: 1%;
}
.content {
padding: 10px;
}
#bottom {
background: blue;
}
#super > div {
display: table-row;
}
<div id="super">
<div id="top">
<div class="content">
top
</div>
</div>
<div id="bottom">
<div class="content">
bottom</div>
</div>
</div>
Output Image:
You can use display: table for wrapping container and table-row for top and bottom divs:
* {
padding: 1px;
margin: 0px;
border: solid 1px;
width: 100%;
}
#super {
display: table;
position: absolute;
height: 100vh;
}
#top {
display: table-row;
height: 1px;
position: relative;
background: orange;
}
#bottom {
display: table-row;
position: relative;
top: 0px;
bottom: 0px;
background: teal;
}
<div id="super">
<div id="top">top<br>top text</div>
<div id="bottom">bottom</div>
</div>
Use flex-box
.parent{
display: flex;
flex-direction: column;
min-height: 100vh
}
.child2{
flex: 1;
background: blue;
}
<div class="parent">
<div class="child1"> first child</div>
<div class="child2"> second child</div>
</div>
Demo here
Try this :
#bottom {
position: relative;
top: 0px;
bottom: 0px;
HEIGHT: 800px;
}

Centering Div while being able to expand div

I found this solution to centering my div vertically and horizontally. However if I fill in the content section past the length defined for the div it will run outside of it. I was hoping to make it expand depending on the content inside the div. How do I make it so this can happen?
JSFIDDLE
HTML:
<body>
<div id="wrapper">
<div id="headerwrapper">
<div id="header" class="center">header</div>
</div>
<div id="titlewrapper">
<div id="title" class="center">title</div>
</div>
<div id="contentwrapper">
<div id="content" class="center">content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br></div>
</div>
<div id="footerwrapper">
<div id="locationwrapper">
<div id="location" class="center">location</div>
</div>
<div id="copyrightwrapper">
<div id="copyright" class="center">copyright</div>
</div>
</div>
</div>
</body>
CSS:
html body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.center {
position: relative;
top: 50%;
transform: translateY(-50%);
margin-right: auto;
margin-left: auto;
width: 100%;
height: 100%
max-width: 5em;
}
#wrapper {
background-color: pink;
height: 100%;
width: 100%;
}
#headerwrapper {
background-color: green;
width: 100%;
height: 8em;
}
#header {
color: white;
background-color: black;
}
#titlewrapper {
background-color: red;
width: 100%;
height: 8em;
}
#title {
color: white;
background-color: black;
}
#contentwrapper {
background-color: blue;
width: 100%;
height: 8em;
}
#content {
color: white;
background-color: black;
}
#locationwrapper {
background-color: yellow;
width: 100%;
height: 8em;
}
#location {
color: white;
background-color: black;
}
#footerwrapper {
background-color: brown;
width: 100%;
height: 100%;
}
#copyrightwrapper {
background-color: green;
width: 100%;
height: 8em;
}
#copyright {
color: white;
background-color: black;
}
If you want the "content" sections to dynamically adjust height, take off the fixed height.
Change:
#contentwrapper {
background-color: blue;
width: 100%;
height: 8em;
}
To:
#contentwrapper {
background-color: blue;
width: 100%;
}
Working fiddle to your requirement: http://jsfiddle.net/k5YUu/6/