Nested sticky element with zero left does not sticky - html

Why my nested sticky element with left: 0 does not stick while the nested element with top: 0 sticks normally?
.scroll {
width: 200px;
height: 200px;
border: 1px solid;
overflow: auto;
}
.container {
width: 600px;
height: 1000px;
}
.sticky-left {
position: sticky;
left: 0;
}
.sticky-top {
position: sticky;
top: 0;
}
<div class="scroll">
<div class="sticky-top">sticky-top</div>
<div class="sticky-left">sticky-left</div>
<div class="container">
<div class="sticky-top">sticky-top-nested</div>
<div class="sticky-left">sticky-left-nested</div>
</div>
</div>

Let's add some border and we will clearly see what is happening:
.scroll {
width: 200px;
height: 200px;
border: 1px solid;
overflow: auto;
}
.scroll > div {
border:2px solid green;
}
.container {
width: 600px;
height: 1000px;
border:2px solid red!important;
}
.container > div {
border:2px solid green;
}
.sticky-left {
position: sticky;
left: 0;
}
.sticky-top {
position: sticky;
top: 0;
}
<div class="scroll">
<div class="sticky-top">sticky-top</div>
<div class="sticky-left">sticky-left</div>
<div class="container">
<div class="sticky-top">sticky-top-nested</div>
<div class="sticky-left">sticky-left-nested</div>
</div>
</div>
As you can see, the nested sticky elements are both having their width equal to parent width (since they are block element) so there is no room for the left-sticky to have any sticky behavior1 since it has width:100% unlike the top one that can still stick because its height is less that the parent height.
For the non-nested elements I think it's clear.
Make the element inline-block or reduce the width and you will have a sticky behavior:
.scroll {
width: 200px;
height: 200px;
border: 1px solid;
overflow: auto;
}
.scroll > div {
border:2px solid green;
}
.container {
width: 600px;
height: 1000px;
border:2px solid red!important;
}
.container > div {
border:2px solid green;
width:150px;
}
.sticky-left {
position: sticky;
left: 0;
}
.sticky-top {
position: sticky;
top: 0;
}
<div class="scroll">
<div class="sticky-top">sticky-top</div>
<div class="sticky-left">sticky-left</div>
<div class="container">
<div class="sticky-top">sticky-top-nested</div>
<div class="sticky-left">sticky-left-nested</div>
</div>
</div>
1 A stickily positioned element is an element whose computed position value is sticky. It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing block.ref
In your case you were always meeting the opposite edge.

As per the MDN documentation on position: sticky, the top, right, bottom, and left properties determine the final location of positioned elements. My guess is that in order for it to be stickied from the top, it needs to also contain top: 0. The snippet I added seems to work.
.scroll {
width: 200px;
height: 200px;
border: 1px solid;
overflow: auto;
}
.container {
width: 600px;
height: 1000px;
}
.sticky-left {
position: sticky;
left: 0;
top: 0; // Add this so it sticks to top
}
.sticky-top {
position: sticky;
top: 0;
}
<div class="scroll">
<div class="sticky-top">sticky-top</div>
<div class="sticky-left">sticky-left</div>
<div class="container">
<div class="sticky-top">sticky-top-nested</div>
<div class="sticky-left">sticky-left-nested</div>
</div>
</div>

Related

width:100vw of element breaks position: sticky

I am trying to stretch a sticky element to size of the screen. I have the following HTML
.large {
height: 200vw;
width: 200vw;
}
.header {
left: 0;
top: 0;
color:white;
position: sticky;
width: 100px;
height: 100px;
background: black;
}
<div class="header">Header</div>
<div class="large">Content</div>
The problem is that this works but the element is not stretched. If I change width:100px to width:100vw the sticky to the left breaks. So it seems like I cannot specify relative width and use sticky to the left at the same time?
You can achieve this by adding a div around both elements and giving that div a display: inline-block;:
.container {
display: inline-block;
}
.large {
height: 200vw;
width: 200vw;
}
.header {
left: 0;
top: 0;
position: sticky;
width: 100vw;
height: 100px;
background: black;
}
<div class="container">
<div class="header"></div>
<div class="large"></div>
</div>

Make a div float within another Div

I need a div to float within another div. Tried using position: fixed, but the div floats beyond the parent div now.
Here is the sample code.
I need the "Div to Float" to float inside "Div 1". now it floats outside 'Div 1' and go behind 'Div 2'
Here is the code.
.wrapper {<!--from www .j av a2s.c o m-->
width:100%;
height: 200px;
overflow-y: scroll;
}
.container {
width: 301px;
margin: 0px auto;
height: 1501px;
background: green;
position: relative;
}
.element {
background:yellow;
position:fixed;
width:101px;
height:71px;
top:51px;
right:0px;
left:769px;
border:2px solid blue;
}
<div class="wrapper">
<div class="container">
Div 1
<div class="element">Div to float</div>
</div>
</div>
<div class="container" style="margin-top: 30px; background: purple">Div 2</div>
What I've tried?
.wrapper {<!--from www .j av a2s.c o m-->
width:100%;
height: 200px;
overflow-y: scroll;
}
.container {
width: 301px;
margin: 0px auto;
height: 1501px;
background: green;
position: relative;
}
.element {
background:yellow;
position:fixed;
width:101px;
height:71px;
top:51px;
right:0px;
left:769px;
border:2px solid blue;
}
<div class="wrapper">
<div class="container">
Div 1
<div class="element">Div to float</div>
</div>
</div>
<div class="container" style="margin-top: 30px; background: purple">Div 2</div>
What I've expected?
I need the "Div to Float" to float inside "Div 1".
What is the result now?
Now it floats outside 'Div 1' and go behind 'Div 2'
.container {
position:relative;
}
.element{
position:absolute;
}
I don't fully understand what you mean by "float", but this code will place your div.element inside div.container
Position: Fixed
position: fixed; is positioning the element relative to the viewport, which means it always stays in the same place even if the page is scrolled.
Position: Sticky
position: sticky; is positioning the element relative until a given offset position is met in the viewport - then it "sticks" in place. When the user scrolls past the parent div, the element will stay with its parent.
Read more about Layout positioning
.wrapper {
width: 100%;
height: 200px;
overflow-y: scroll;
position: relative;
}
.container {
width: 301px;
margin: 0px auto;
height: 1501px;
background: green;
position: relative;
z-index: 2;
}
.second {
z-index: 0;
}
.element {
background: yellow;
position: sticky;
width: 90%;
height: 80px;
top: 50px;
right: 0px;
left: 769px;
border: 2px solid blue;
}
.fixed {
position: fixed;
top: 50px;
left: 0;
width: 50%;
z-index: 1;
}
<div class="wrapper">
<div class="container">
Div 1
<div class="element">I am 50px away from the top of my green parent, and I will stop being sticky when document gets scrolled away from my parent.</div>
</div>
<div class="fixed" style="margin-top: 30px; background: red">I am just gonna stay in this place forever cause I'm fixed. Using z-index on me or the elements will control whether I'm above or below any other elements.</div>
</div>
<div class="container second" style="margin-top: 30px; background: purple">Div 2</div>

Position Absolute Not Scrolling Properly

I'm trying to create an area that contains all my absolutely positioned items. It works great until its sibling has an overflow attached to it. In the example below, when you start scrolling, the child div scrolls as if it's fixed. If you comment out the overflow: auto in the #app CSS, you'll get the desired behavior, but obviously the layout is incorrect. How can I fix this issue without moving the absolute div into the #app div?
#app {
height: 200px;
/* If I take this off, I get the desired behavior */
overflow: auto;
}
.content {
height: 300px;
width: 100%;
color: white;
background-color: darkblue;
}
.absolute {
position: absolute;
top: 0;
left: 0;
}
.child {
top: 20px;
height: 20px;
position: absolute;
background-color: white;
width: 300px;
}
body, html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<div id="app">
<div class="content">
Content 1
</div>
</div>
<div class="absolute">
<div class="child">
Shouldn't be fixed when scrolling
</div>
</div>
If you want to use absolute positioning on .absolute you'll have to nest that code within #app and set it to position: relative;. The absolute positioning is referring to its nearest positioned ancestor, in this case, the body element, hence, why it is staying fixed. So you'll have to set #app to relative and it should work just fine.
#app {
height: 200px;
/* If I take this off, I get the desired behavior */
overflow: auto;
position: relative;
}
.content {
height: 300px;
width: 100%;
color: white;
background-color: darkblue;
}
.absolute {
position: absolute;
top: 0;
left: 0;
}
.child {
top: 20px;
height: 20px;
position: absolute;
background-color: white;
width: 300px;
}
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<div id="app">
<div class="content">
Content 1
</div>
<div class="absolute">
<div class="child">
Shouldn't be fixed when scrolling
</div>
</div>
</div>
This should also work for you, see changes I made to HTML and CSS below.
#app {
height: 200px;
/* If I take this off, I get the desired behavior */
overflow: auto;
}
.content {
height: 300px;
width: 100%;
color: white;
background-color: darkblue;
}
.absolute {
position: relative;
top: 0;
left: 0;
}
.child {
top: 0px;
height: 20px;
position: absolute;
background-color: white;
width: 300px;
color: black;
}
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<div id="app">
<div class="content">Content 1
<div class="absolute">
<div class="child">
Shouldn't be fixed when scrolling
</div>
</div>
</div>
</div>

Parent div responsiveness with inner div

I need to have div border responsive. However, as you can see .buttonsDiv needs to be at the bottom and wrapper border needs to be stretched underneath .buttonsDiv. But when I use this code buttons are at the bottom but border stays at the top. I can't use margin because content div contains elements that are shown/hidden and the page needs to be fixed aka disabled scrolling.
html
.wrapper {
border: 1px solid black;
}
.buttonsDiv {
position: fixed;
bottom: 10px;
}
<div class="wrapper">
<div class="borderedDiv">Content</div>
<div class="buttonsDiv">Butons</div>
</div>
Put position: absolute; to the parent and define top, bottom, left, right as 0;
PS: This solution will not add scroll bar which appears if you put height 100vh
.wrapper {
border: 1px solid black;
position: absolute;
bottom: 0;
top: 0;
right: 0;
left: 0
}
.buttonsDiv {
position: fixed;
bottom: 10px;
}
<div class="wrapper">
<div class="borderedDiv">Content</div>
<div class="buttonsDiv">Butons</div>
</div>
Its hard to understand what you are after. Do you mean something like this?
html, body{
margin: 0;
padding: 0;
}
.wrapper{
height: 100vh;
width: 100vw;
padding: 10px;
box-sizing: border-box;
}
.inner_wrap{
position:relative;
width: 100%;
height: 100%;
border: 1px solid black;
box-sizing: border-box;
}
.buttonsDiv{
position: absolute;
bottom: 10px;
}
<div class="wrapper">
<div class="inner_wrap">
<div class="borderedDiv">Content</div>
<div class="buttonsDiv">Butons</div>
</div>
</div>
To add to the previous answer:
.wrapper {
border: 1px solid black;
height: 100vh;
}
.buttonsDiv {
position: absolute;
bottom: 1px;
}
<div class="wrapper">
<div class="borderedDiv">Content</div>
<div class="buttonsDiv">Butons</div>
</div>
The wrapper doesn't need an position: relative, position static will do fine.
With the position absolute of the button div you place the element relative to its parent element. Therefore if we put .buttonsDiv to bottom:1px it will stick to the bottom of the element.

Setting content below image

Is there anyway I can position my div content stuff to go below image.I don't want to give padding to wrap class as no one know how big the image would be so I need a solution where text goes below to image as mentioned in html structure.
.parent {
width: 500px;
background-color: red;
margin: 0 auto;
position: static;
}
.wrap {}
.child {
background-color: yellow;
position: absolute;
left: 0;
right: 0;
height: 100px;
top: 30px
}
div {
height: 400px;
}
body {
background-color: blue;
}
<div class="parent">
<div class="child"><img src="https://images.mapsofworld.com/around-the-world/Chinese-economy-faces-tough-times.jpg" /></div>
<div class="wrap">stuff</div>
</div>
Position wrap inside child
html, body { padding: 0; margin:0; }
.parent {
width: 500px;
background-color: red;
margin: 0 auto;
position: static;
}
.wrap {}
.child {
background-color: yellow;
position: absolute;
left: 0;
right: 0;
height: 100px;
top: 30px
}
div {
height: 400px;
}
body {
background-color: blue;
}
<div class="parent">
<div class="child"><img src="https://images.mapsofworld.com/around-the-world/Chinese-economy-faces-tough-times.jpg" />
<div class="wrap">stuff</div>
</div>
</div>
You could use Transform: Translate() to move it under, inside the parent <div>. I did this myself with a table and input fields inside a <div>