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>
You wrote:
Is there any way to make the left column fixed?
I'd appreciate a way to make it work with the grid layout.
If you want the element to remain a grid item, then the answer is "no".
Once an element has position: absolute
or position: fixed
(which is a form of absolute positioning, with reference to the viewport), it takes on new characteristics:
- the element is removed from the document flow
- the element is removed from the grid formatting context
- the element is no longer a grid item
From the spec:
10. Absolute
Positioning
An absolutely-positioned child of a grid container is out-of-flow and
not a grid item, and so does not affect the placement of other items
or the sizing of the grid.
So a grid item doesn't work well with absolute positioning.
However, you won't have a problem applying position: fixed
to a grid container.
Consider managing your #left
and #right
elements separately. #left
can be a fixed-position grid container. #right
can be another grid container and remain in-flow.
Also, as an aside, you've given your grid items percentage-based padding:
.section {
padding: 5% 5% 5% 5%;
}
When applying margin
and padding
to grid items (and flex items), it's best to stay away from percentage units. Browsers may compute the values differently.
- Percentage padding on grid item being ignored in Firefox
- Why doesn't percentage padding work on flex items in Firefox?
You can achieve this by adding these CSS rules to your id #left:
position: sticky; // See link
top: 0; //to make it stick to the top of the screen
height: 100vh; // make the height equal to 100 view height
Link for sticky position: Sticky position with nothing but CSS
sticky is a new value for the position property, added as part of CSS3 Layout Module Spec. It acts similarly to relative positioning, in that it doesn’t remove anything from the document flow. In other words, a sticky element has no effect on the position of adjacent elements and doesn't collapse its parent element.
Hope it helps you
EDIT (fix jumpy behaviour)
In order to avoid the left part to jump up at the end of the page, just add the following CSS rule to your id #left:
box-sizing: border-box;
See updated code snippet:
body {
margin: 0 0 0 0;
}
#container {
display: grid;
grid-template-columns: 50% 50%;
}
.section {
padding: 5% 5% 5% 5%;
}
#left {
background-color: aquamarine;
position: sticky;
top: 0;
height: 100vh;
box-sizing: border-box;
}
#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>
You can do something like this
here is the fiddle
here is the code
body {
margin: 0 0 0 0;
}
#container {
display: grid;
}
.section {
padding: 5% 5% 5% 5%;
}
#left {
background-color: aquamarine;
height: 100%;
position: fixed;
width: 50%
}
#right {
background-color: beige;
overflow: scroll;
width: 50%;
right: 0;
position: absolute;
}
Add one more div in right panel which panel you want to scroll for that give some max-height
and overflow: auto;
so left panel will be stick and right panel content will scroll.
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;
}
.scroll-div {
max-height: 300px;
overflow: auto;
}
<div id="container">
<div id="left" class="section">
<p>This should not scroll</p>
</div>
<div id="right" class="section">
<div class="scroll-div">
<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>
</div>
try this:
body {
margin: 0 0 0 0;
}
#container {
display: grid;
grid-template-columns: 50% 50%;
}
.section {
padding: 5% 5% 5% 5%;
}
#left {
background-color: aquamarine;
p {
position: fixed;
}
}
#right {
background-color: beige;
}
https://jsfiddle.net/km5gdrcm/3/
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.