dye
dye

Reputation: 83

CSS Grid with dynamic height columns

<div class="grid">
  <div class="grid__item topbar"></div>
  <div class="grid__item title"></div>
  <div class="grid__item box1"></div>
  <div class="grid__item box2"></div>
  <div class="grid__item box3"></div>
  <div class="grid__item box4">
    <button class="add-content-btn">Add content</button>
    <p>Dynamic content</p>
  </div>
  <div class="grid__item sidebar">
    <button class="add-content-btn">Add content</button>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
    <p>Dynamic content</p>
  </div>
</div>

body {
  padding: 16px;
}

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template-areas: 
    "topbar topbar"
    "title  sidebar"
    "box1   sidebar"
    "box2   sidebar"
    "box3   sidebar"
    "box4   sidebar";
  grid-template-columns: 70% 30%;
  grid-template-rows: 28px 30px 500px 50px 20px auto;
}

.grid__item {
  border: 1px solid black;
}

.topbar {
  grid-area: topbar;
}

.title {
  grid-area: title;
}

.box1 {
  grid-area: box1;
}

.box2 {
  grid-area: box2;
}

.box3 {
  grid-area: box3;
}

.box4 {
  grid-area: box4;
  padding: 10px;
}

.sidebar {
  grid-area: sidebar;
  overflow: scroll;
  padding: 10px;
}

const btns = document.querySelectorAll('.add-content-btn');
btns.forEach(btn => {
  btn.addEventListener('click', e => {
    const parent = e.target.parentElement;
    for (let i = 0; i < 3; i++) {
      const newLine = document.createElement('p');
      newLine.innerText = 'Dynamic content';
      parent.append(newLine);
    }
  });
})

http://codepen.io/dye/pen/YVyoVd

In this layout, I have 2 columns that can each grow in size. I want the height of the right column to be controlled by the height of the left column, but not the other way around.

Clicking the "Add content" button in the bottom left box will grow the left column as well as the right column. That works as intended.

At the moment, clicking the "Add content" button in the right column will grow the left column. This is unintended. I would like the height of the right column to be at most the height of the left column, and have content inside be scrollable. Is this possible with CSS grid or do I need to use JS?

Upvotes: 0

Views: 3521

Answers (1)

G-Cyrillus
G-Cyrillus

Reputation: 105863

you may use an extra wrapper in absolute position to avoid interaction with the original layout.

const btns = document.querySelectorAll('.add-content-btn');
btns.forEach(btn => {
  btn.addEventListener('click', e => {
    const parent = e.target.parentElement;
    for (let i = 0; i < 3; i++) {
      const newLine = document.createElement('p');
      newLine.innerText = 'Dynamic content';
      parent.append(newLine);
    }
  });
})
body {
  padding: 16px;
}

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template-areas: "topbar topbar" "title  sidebar" "box1   sidebar" "box2   sidebar" "box3   sidebar" "box4   sidebar";
  grid-template-columns: 70% 30%;
  grid-template-rows: 28px 30px 500px 50px 20px auto;
}

.grid__item {
  border: 1px solid black;
}

.topbar {
  grid-area: topbar;
}

.title {
  grid-area: title;
}

.box1 {
  grid-area: box1;
}

.box2 {
  grid-area: box2;
}

.box3 {
  grid-area: box3;
}

.box4 {
  grid-area: box4;
  padding: 10px;
}

.sidebar {
  grid-area: sidebar;
  position: relative;
}

.buffer {
  padding: 10px;
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0;
  overflow:auto;
}
<div class="grid">
  <div class="grid__item topbar"></div>
  <div class="grid__item title"></div>
  <div class="grid__item box1"></div>
  <div class="grid__item box2"></div>
  <div class="grid__item box3"></div>
  <div class="grid__item box4">
    <button class="add-content-btn">Add content</button>

    <p>Dynamic content</p>
  </div>
  <div class="grid__item sidebar">
    <div class="buffer">
      <button class="add-content-btn">Add content</button>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
      <p>Dynamic content</p>
    </div>
  </div>
</div>


from my comment:

you can try max-height and overflow, but specification are unclear about this and firefox will show the scroll where chrome will not http://codepen.io/gc-nomade/pen/Wjryym

You should relay on javascript or use an extra element set in absolute position within sidebar http://codepen.io/gc-nomade/pen/JNGZwW

Upvotes: 1

Related Questions