How to make a fixed column in CSS using CSS Grid Layout?

Viewed 54652

I've made a simple site with a #container div that is parent to two divs: #left and #right, by using Grid Layout:

Is there any way to make the left column fixed? I'd like the left text to persist on its position, and the right text to be scrollable as it is now. Adding position: fixed to #left breaks the layout.

I'm aware that this question has been already solved, but I'd appreciate a way to make it work with the grid layout.

Thanks.

body {
  margin: 0 0 0 0;
}

#container {
  display: grid;
  grid-template-columns: 50% 50%;
}

.section {
  padding: 5% 5% 5% 5%;
}

#left {
  background-color: aquamarine;
}

#right {
  background-color: beige;
}
<div id="container">
  <div id="left" class="section">
    <p>This should not scroll</p>
  </div>
  <div id="right" class="section">
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla aliquet consectetur purus nec volutpat. Donec vel libero nec est commodo facilisis vel et nisl. Praesent porta sed eros eu porta. Cras dolor nulla, ullamcorper et tincidunt quis, porta ut
      tellus. Maecenas cursus libero sed accumsan luctus. Integer sed consequat ante. Morbi sit amet lectus tempor elit tempor cursus ut sed enim. Donec placerat bibendum volutpat.
    </p>
    <p>
      Nunc sit amet eleifend sapien, sed tincidunt neque. Donec id sapien et nunc scelerisque iaculis dignissim nec mauris. Fusce at pretium nulla. Maecenas vel rutrum tellus, a viverra nunc. Aenean at arcu vitae dui faucibus dapibus. Vivamus hendrerit blandit
      mollis. Aenean sit amet lectus a metus faucibus condimentum. Proin vel eros ut elit pharetra lacinia vitae eu orci. Etiam massa massa, aliquam at pulvinar ut, porttitor eu mauris. Ut in iaculis sapien.
    </p>
    <p>
      In vitae rhoncus arcu. Maecenas elementum nunc quis magna finibus, vitae imperdiet diam pulvinar. Phasellus sit amet nibh eu massa facilisis luctus. Nulla ullamcorper sodales ante id vestibulum. Fusce felis nisi, lacinia sit amet mauris vel, euismod suscipit
      neque. Mauris quis libero eget enim facilisis pharetra. Fusce non ligula auctor nunc pretium dignissim eget eget turpis. Nam ultricies dolor ac libero maximus vestibulum. Mauris et tortor vitae nisi ultrices vestibulum ac id mauris. Proin interdum
      dapibus sollicitudin. Phasellus ultricies vulputate sem id hendrerit. Cras eget posuere nunc, in placerat velit. Pellentesque sed ante at elit ornare efficitur. Donec sed condimentum nisl. Curabitur dapibus leo id ligula dignissim pharetra.
    </p>
  </div>
</div>

8 Answers

You can't make left be sticky, but you can make all content in it be sticky. For this you should make sticky wrapper element and place all content in it like so:

HTML:

<div class="grid">

    <div class="left">
       <div class="sticky_wrapper">Content</div>
    </div>

    <div class="right">
        Content
    </div>

</div>

CSS:

.grid { display: grid; grid-template-columns: 50% 50%; }
.left { background-color: aquamarine; }
.right { background-color: beige; }
.sticky_wrapper { position: sticky; top: 0; }

So all content in the sticky wrapper will not scrool.

I had a bit of the same problem. I needed a fixed sidenav (col 1) with scrollable content (col 2). Here's how I solved the problem (note that I use styled-component, but you can surely do it with regular css, sass, less, or whatever):

<Grid>
  <SideNav>
    <Sider>
  </SideNav>
  <Content />
<Grid>

Now the css property for each of those styled-components:

const Grid = styled.div`
  position: relative;
  display: grid;
  height: 100%;
  grid-template-columns: auto 1fr;
  grid-template-areas: 'sidenav content';
`

const Sidenav = styled.div`
  position: relative;
  grid-area: sidenav;
`
const Content = styled.div`
  position: relative;
  grid-area: content;
  width: 100%;
`

const Sider = styled.aside`
  position: fixed;
  height: 100vh;
`

It looks like this, but a bit more complex on my side since I also have a header and footer in my grid, and the sidenav is collapsable. But I think this could work for you.

I stumbled upon this today and got it working by adding:

#left {
  position: sticky;
  left: 0;
}
Related