Make elements sticky to their parent container

Viewed 338

I am attempting to create the following layout: enter image description here

As you can see when I scroll, the alignment of the 1st and 3rd items has scrolled with the content. I need a way to get the first and third items to stay sticky to their respective sides. I also need this solution to be responsive as the container scales with screen size.

#container {
  height: 300px;
  width: 50%;
  position: relative;
  overflow: auto;
  border: solid 1px black;
}

.item {
  height: 500px;
  width: 100px;
  z-index: 5;
  position: absolute;
  background-color: red;
}

.item:nth-child(2) {
  width: 800px;
  z-index: 2;
  background-color: green;
}

.item:nth-child(3) {
  right: 0;
}
<div id="container">
  <div class="item">&nbsp</div>
  <div class="item">&nbsp</div>
  <div class="item">&nbsp</div>
</div>

What I Am Actually Building This is a generalized problem. The actual problem I am trying to solve is that of a custom-built HTML table. The left and right items (red sections) are going to be containers for static (sticky) columns. With that being said, I need the constraints of the problem to stay the same. Changing the width of the item:nth-child(2) to 100% will not work. Wrapping the contents inside of the item:nth-child(2) in another div and adding overflow: auto to that div will not work because then the scrollbar will not be shared amongst the entire container like it is in my example.

4 Answers

You can try like below:

#container {
  height: 300px;
  display:flex; /* added */
  overflow: auto;
  border: solid 1px black;
}

.item {
  height: 500px;
  width: 100px;
  background-color: red;
  flex-shrink:0; /* added */
}

.item:nth-child(2) {
  width: 800px;
  background-color: green;
}

.item:nth-child(1) {
  left: 0;
  top:0;
  position: sticky;
}
.item:nth-child(3) {
  right: 0;
  top:0;
  margin-left:auto; /* this is important*/
  position: sticky;
}
<div id="container">
  <div class="item">&nbsp</div>
  <div class="item">&nbsp</div>
  <div class="item">&nbsp</div>
</div>

.item:nth-child(2) {
    width: 100%;
    z-index: 2;
    background-color: green;
}

You can make .item:nth-child(2) width is 100%

As I understand, you want the left and right sections to be fixed and the middle item to be responsive. If you consider a different approach to the problem. Here's my solution to it.

#container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  height: 80vh;
}

.item1 {
  padding: 20px;
  background-color: #f90;
}

.item2 {
  flex: 1;
  padding: 20px;
}

.item3 {
  padding: 20px;
  background-color: #936;
}
<div id="container">
  <div class="item1">Left</div>
  <div class="item2">Middle</div>
  <div class="item3">Right</div>
</div>

You can add the position: sticky; as required to any item to make it sticky.

The main idea is use absolute wrapper to contain fixed child.

Also remember to add padding in long content.

body {
  padding: 10px;
  background: #eee;
  display: flex;
  justify-content: center;
}
.parent {
  width: 100%;
  height: 100px;
  overflow-x: scroll;
  position: relative;
  border: 1px solid #000;
  background: #0f0;
}
.fix {
  position: fixed;
  background: rgba(255, 0, 0, .3);
  width: 100px;
  height: 100px;
  z-index: 2;
}
.fix-wrapper {
  position: absolute;
  top: 0;
}
.left {
  left: 0;
}
.right {
  right: 100px;
}
.content {
  height: 100%;
  width: 1000px;
  padding: 0 100px;
}
<div class="parent">
  <div class="fix-wrapper left">
    <div class="fix">Left</div>
  </div>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pellentesque id nibh tortor id aliquet lectus proin. Viverra nam libero justo laoreet sit amet. Gravida cum sociis natoque penatibus et magnis dis parturient montes. At urna condimentum mattis pellentesque id nibh tortor id aliquet. Aenean pharetra magna ac placerat. Pellentesque habitant morbi tristique senectus et netus. Sed odio morbi quis commodo odio aenean. Ac turpis egestas maecenas pharetra convallis posuere morbi. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Mollis aliquam ut porttitor leo a diam sollicitudin tempor. Amet mattis vulputate enim nulla aliquet porttitor lacus. Curabitur vitae nunc sed velit. Cursus eget nunc scelerisque viverra. Morbi tincidunt augue interdum velit euismod in pellentesque massa placerat. Etiam non quam lacus suspendisse faucibus.
  </div>
  <div class="fix-wrapper right">
    <div class="fix">Right</div>
  </div>
</div>

Related