Making the second item of flex container sticky with CSS - html

I have flex container that contains two columns.
Each column is a flex container as well.
I wish to make the second item of the side column sticky, so when you scroll down it will stay visible until the end of the page
In my example you can see that I tried with position: sticky;
But it seems like the item gets stick but not all the way to the end of the page.
What am I missing?
I tried some answers like My position: sticky element isn't sticky when using flexbox but I didn’t managed to make it work.
Demo: https://codepen.io/avneri/pen/yLONZVy
.page-container {
display: flex;
justify-content: space-evenly;
}
.column-container {
max-width: 50%;
}
.item-wrapper {
display: flex;
flex-direction: column;
}
.item {
min-width: 150px;
margin: 15px;
padding: 30px;
background: red;
text-align: center;
}
.sticky {
background: green;
position: -webkit-sticky;
position: sticky;
top: 0;
align-self: flex-start;
}
<div class="page-container">
<div class="column-container">
<div class="item-wrapper">
<div class="item">
Item 1
</div>
<div class="item">
Item 2
</div>
<div class="item">
Item 3
</div>
<div class="item">
Item 4
</div>
<div class="item">
Item 5
</div>
...
</div>
</div>
<div class="column-container">
<div class="item-wrapper">
<div class="item">
Side item 1
</div>
<div class="item sticky">
Side item 2
</div>
</div>
</div>
</div>

It's because the second column's inner wrapper doesn't extend to the full height; sticky will not let the element pass the limits of its container.
Try adding height: 100%; as below (I did it with a class):
.page-container {
display: flex;
justify-content: space-evenly;
}
.column-container {
max-width: 50%;
}
.item-wrapper {
display: flex;
flex-direction: column;
}
.item {
min-width: 150px;
margin: 15px;
padding: 30px;
background: red;
text-align: center;
}
.sticky {
background: green;
position: -webkit-sticky;
position: sticky;
top: 0;
align-self: flex-start;
}
.full-height {
height: 100%;
}
<div class="page-container">
<div class="column-container">
<div class="item-wrapper">
<div class="item">
Item 1
</div>
<div class="item">
Item 2
</div>
<div class="item">
Item 3
</div>
<div class="item">
Item 4
</div>
<div class="item">
Item 5
</div>
...
</div>
</div>
<div class="column-container">
<div class="item-wrapper full-height">
<div class="item">
Side item 1
</div>
<div class="item sticky">
Side item 2
</div>
</div>
</div>
</div>

Related

how to center the first item in a flexbox slider/carousel

I want to build a simple scroll slider with flexbox with three items. I want the first item to be centered in the page (under the headline) but the following items only should have a less margin.
HTML:
<div class="page-width">
<h1>Headline</h1>
<div class="container">
<div class="flex-item">
<div class="flex-wrapper">
Center me
</div>
</div>
<div class="flex-item">
<div class="flex-wrapper">
Hello World
</div>
</div>
<div class="flex-item">
<div class="flex-wrapper">
Hello World
</div>
</div>
</div>
</div>
CSS:
.page-width {
max-width: 500px;
border: 5px solid green;
}
h1 {
text-align: center;
}
.container {
display: flex;
justify-content: flex-start;
overflow: scroll;
}
.flex-item {
margin-left: 20px;
}
.flex-wrapper {
background: blue;
width: 250px;
height: 250px;
}
How can I achieve to center the first item, while the second and third only remain with a margin of 20px? Also, it should be responsive, for example when the page width is smaller, the first item should still be centered.
I tried to use
.flex-item {
flex: 0 0 100%
}
and center the wrapper inside, so the box would be in the center, but then the second and third item are outside of the screen.
Codepen: https://codepen.io/ascena/pen/wvqZgzg
.page-width {
max-width: 500px;
border: 5px solid green;
}
h1 {
text-align: center;
}
.container {
display: flex;
justify-content: flex-start;
overflow: scroll;
padding-left:20%;
}
.flex-item {
margin-left: 20px;
}
.flex-wrapper {
background: blue;
width: 250px;
height: 250px;
}
<div class="page-width">
<h1>Headline</h1>
<div class="container">
<div class="flex-item">
<div class="flex-wrapper">
Center me
</div>
</div>
<div class="flex-item">
<div class="flex-wrapper">
Hello World
</div>
</div>
<div class="flex-item">
<div class="flex-wrapper">
Hello World
</div>
</div>
</div>
</div>

How to change the order of divs in a 2x2 grid

I am trying to make my 2x2 grid of divs take on a different order. I am trying to use flexbox for this.
I have tried to simplify my situation in a Codepen and I come quite far, yet I cannot perform the last step.
I want to swap number 2 and 3 so the order is goes from top right to top left.
Here is the code I use for the above output:
.container {
height: 600px;
width: 800px;
background-color: red;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
}
.container2 {
// flex-direction: column-reverse <-- this does not work
}
.square {
font-size: 84px;
text-align: center;
margin: 20px;
background-color: green;
width: 300px;
height: 200px;
}
<div class="container">
<div class="container1">
<div class="square">
0
</div>
<div class="square">
1
</div>
</div>
<div class="container2">
<div class="square">
2
</div>
<div class="square">
3
</div>
</div>
</div>
Does anyone know a simple addition or, if necessary, a bigger change that will make this work?
Thanks in advance for your responses!
EDIT: Perhaps it is important to say that there will not always be 4 squares. 4 will be the maximum but there may also be 1, 2 or 3 squares.
You can manage this by manipulating the size of the overall container and adjusting the various flex-directions of each sub-container.
.container {
height: 180px;
width: 180px;
background-color: red;
display: inline-flex;
flex-direction: row-reverse;
flex-wrap: wrap;
}
.container1 {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.container2 {
display: flex;
flex-direction: column-reverse;
}
.square {
font-size: 42px;
text-align: center;
background-color: green;
width: 50px;
height: 50px;
margin: 20px;
}
<div class="container">
<div class="container1">
<div class="square">
0
</div>
<div class="square">
1
</div>
</div>
<div class="container2">
<div class="square">
2
</div>
<div class="square">
3
</div>
</div>
</div>
<div class="container">
<div class="container1">
<div class="square">
0
</div>
<div class="square">
1
</div>
</div>
<div class="container2">
<div class="square">
2
</div>
</div>
</div>
why don't you use a simple approach?
#flex { display: flex; flex-direction: column; }
#a { order: 2; }
#b { order: 1; }
#c { order: 3; }
<div id="flex">
<div id="a">A</div>
<div id="b">B</div>
<div id="c">C</div>
</div>
you can change the order of any flex child using order
check this to know more about flex in css
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.container {
height: 600px;
width: 800px;
background-color: red;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
}
.container1,.container2 {
display:flex;
flex-direction: column;
justify-content:flex-end;
}
.square {
font-size: 84px;
text-align: center;
margin: 20px;
background-color: green;
width: 300px;
height: 200px;
}
.order-1{
order:1;
}
.order-2{
order:2
}
<div class="container">
<div class="container1">
<div class="square">
0
</div>
<div class="square">
1
</div>
</div>
<div class="container2">
<div class="square order-2">
2
</div>
<div class="square order-1">
3
</div>
</div>
</div>

How to get nested css flex to have the right width after wrap in this setup?

I have this mockup, there are some nested containers. some of the link-class have multiple elements (par and ref) and I want them to display next to each other if there's space, but responsively move them below each other when total width gets smaller.
It works somewhat, but I expect (want) the link-element containing two childs to return to the same width as the link-element with one single child as it wraps.
For some reason, it remains wider than the single-child ones.
Any hints appreciated!
Code:
let name = 'world';
:global(body) {
margin: 0;
padding: 0
}
.main {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
background-color: gray;
}
.Container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: lightblue;
padding: 3px
}
.linkContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 3px;
background-color: salmon;
}
.par {
width: 80vw;
max-width: 300px;
background-color: red
}
.links {
display: flex;
flex-flow: row wrap;
padding: 3px;
background-color: orange
}
.ref {
background-color: olive;
width: 30vw;
max-width: 100px
}
.item {
width: 80vw;
max-width: 300px;
background-color: steelblue
}
<div class="main">
<div class="Container">
<div class="item">
header
</div>
<div class="linkContainer">
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="Container">
<div class="item">
another header
</div>
<div class="linkContainer">
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
</div>
</div>
</div>
</div>
</div>
you could simply add a max-width:300px; to .links and have the box in size but then you couldn't have the desired stacking effect you wanted so i went a bit further and with the help of css variables and media queries and adding a class .single to single .pars which didn't have a .ref after them, i came up with this:
:root {
--ref-size: 100px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.main {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
background-color: gray;
}
.Container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: lightblue;
padding: 3px
}
.links {
min-width: 300px;
display: flex;
flex-flow: row wrap;
padding: 3px;
background-color: orange;
}
.par {
width: calc(100% - var(--ref-size));
background-color: red;
}
.ref {
background-color: olive;
width: var(--ref-size);
}
.item {
width: 80vw;
max-width: 300px;
background-color: steelblue
}
#media all and (max-width:300px){
.par{
width: 100%;
}
}
#media all and (min-width: 300px){
.par.single{
width: 100%;
}
}
<div class="main">
<div class="Container">
<div class="item links">
header
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="item links">
another header
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
</div>
</div>

position part of the div underneath another

I'm trying to hide part of the div underneath another.
https://jsfiddle.net/71obhkzh/7/ shows what I have now.
<div>
some stuff here
</div>
<div id="container">
<div id="top">
</div>
<div id="bottom">
</div>
</div>
<div>
some stuff here
</div>
#container {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
width: 300px;
}
#top {
height:100px;
width: 100px;
background-color: red;
}
#bottom {
height:100px;
width: 120px;
background-color: blue;
margin-top: -40px;
}
In the fiddle I used the negative margin-top to move the blue div up a bit, but it covers the bottom of the red div. I need the red one to be on top of blue one like this https://awwapp.com/b/unzo2gs6g/
Ok, if I add the z index as suggested it works on the fiddle, but in real app the colors are mixed like here
http://i67.tinypic.com/34pets8.png
I'm using bootstrap and the reality is bit more complicated (flex boxes in the top and bottom div with more content). I tried to set opacity on the top div but it did not help
real code (login container is the red one, info the blue one)
<div class="container">
<div class="row justify-content-center login-container">
<div class="col-6 login-box">login form here</div>
<div class="col-4 register-box">register box here</div>
</div>
<div class="d-flex justify-content-center info-container">
<div id="advantages" class="d-flex flex-column justify-content-center align-items-center">
some text
</div>
<div id="image" class="d-flex flex-column justify-content-center align-items-center">
<img src="some image"/>
</div>
</div>
</div>
https://jsfiddle.net/71obhkzh/31/
Make use of z-index.
#container {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
width: 300px;
}
#top {
height:100px;
width: 100px;
background-color: red;
z-index: 2
}
#bottom {
height:100px;
width: 200px;
background-color: blue;
margin-top: -40px;
z-index: 1
}
<div>
some stuff here
</div>
<div id="container">
<div id="top">
</div>
<div id="bottom">
</div>
</div>
<div>
some stuff here
</div>
Use z-index to do that:
#container {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
width: 300px;
}
#top {
height:100px;
width: 100px;
background-color: red;
z-index:2;
}
#bottom {
height:100px;
width: 120px;
background-color: blue;
margin-top: -40px;
z-index:1;
}
<div>
some stuff here
</div>
<div id="container">
<div id="top">
</div>
<div id="bottom">
</div>
</div>
<div>
some stuff here
</div>

Can't wrap columns in a flexbox flow except under Chrome

How can I fix the max-height of the "content" div. The code works only under Chrome :/
the "content" div should not expand outside the bottom of the window. the items should wrap to the right.
item1 item4 item7
item2 item5 ...
item3 item6
html
<div class="top">
<div class="title">Title</div>
</div>
<div class="wrapper">
<div class="left">
<div class="link">Link</div>
</div>
<div class="content">
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
<div class="item">Item6</div>
<div class="item">Item7</div>
<div class="item">Item8</div>
<div class="item">Item9</div>
<div class="item">Item10</div>
<div class="item">Item11</div>
<div class="item">Item12</div>
<div class="item">Item13</div>
<div class="item">Item14</div>
<div class="item">Item15</div>
<div class="item">Item16</div>
<div class="item">Item17</div>
<div class="item">Item18</div>
<div class="item">Item19</div>
</div>
</div>
</div>
css
html, body { height: 100%; margin: 0px; padding: 0px }
.main {
height: 100%;
max-heigth: 100%; /* not required under chrome, do not works for others */
display: flex;
flex-direction: column;
background-color: red;
color: white;
}
.wrapper {
flex: 1 1 auto;
display: flex;
background-color: silver;
}
.left {
width: 50px;
background-color: lightblue;
}
.content {
flex:1;
display: flex;
flex-flow: column wrap; /* warp only under Chrome */
}
https://jsfiddle.net/L7zzucms/
Change your wrapper rule to this and it works everywhere (tested on Chrome,Firefox,Edge,IE11)
.wrapper {
height: 100%;
display: flex;
background-color: silver;
}
Updated fiddle
I suppose the flex: 1 in content need a height, other than flex: 1 1 auto, from its parent to be able to wrap properly