css 如何创建带有粘性列和标题的网格?

yizd12fk  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(76)

我有一个电子表格样式的网格。根看起来像这样:

<div id="grid">
  <div id="left-column"></div>
  <div id="center-column"></div>
  <div id="right-column"></div>
<div>

字符串
左列和右列各为1列,但中心列为N列数。
当向左和向右滚动时,我想锁定左列和右列,这样它们总是可见的。并且只滚动-x中间的列。
但是,当垂直滚动时,我想锁定所有列中的第一个单元格(标题单元格),这样它们总是可见的。
我有这个几乎工作:

// JS is only used to generate the cells

const cells = Array.from({ length: 20 }).map(c => c = `${Math.floor(Math.random() * 200) + 50}px`)
cells[0] = '120px'
cells[19] = '120px'

const first = cells.shift()
const last = cells.pop()

const rows = Array.from({ length: 100 })

const grid = document.getElementById("grid")
const leftColumn = document.getElementById("left-column")
const centerColumn = document.getElementById("center-column")
const rightColumn = document.getElementById("right-column")

grid.style.display = "grid"
grid.style.gridTemplateColumns = `${first} 1fr ${last}`

function makeItem(text) {
  const div = document.createElement("div")
  div.classList.add('cell')
  const newContent = document.createTextNode(text);
  div.appendChild(newContent);
  return div;
}

function makeRow() {  
  const innerGrid = document.createElement("div")
  innerGrid.style.display = "grid"
  innerGrid.style.gridTemplateColumns = cells.join(' ')
  
  cells.forEach((cell, index) => {
    const child = makeItem(`cell ${index + 1}`)
    innerGrid.appendChild(child)
  })
  
  const a = makeItem('First')
  const z = makeItem('Last')
  
  leftColumn.appendChild(a)
  centerColumn.appendChild(innerGrid)
  rightColumn.appendChild(z)
}

rows.forEach(() => {
  makeRow()
})
.cell {
  background: #eee;
  font-family: Arial;
  border: 0.5px solid black;
  color: #333;
  height: 30px;
  display: grid;
  align-items: center;
  text-align: center;
}

#grid {
  width: min(100%, 1000px);
  max-height: 300px;
  overflow: scroll;
  position: relative;
  border: 0.5px solid black;
}
#center-column {
  overflow-x: scroll;
}
#left-column > .cell, #right-column > .cell, #center-column > :first-child > .cell {
  font-weight: bold;
  color: black;
  background: #aaa;
  color: #eee;
}

#left-column > :first-child,
#right-column > :first-child,
#center-column > :first-child,
#center-column > :first-child > .cell{
  position: sticky;
  top: 0;
  background: #d70000;
}
#center-column {
  position: relative;
}
<div id="grid">
  <div id="left-column"></div>
  <div id="center-column"></div>
  <div id="right-column"></div>
<div>

但是,当您垂直滚动时,左列标题和右列标题保持锁定,但中心标题不保持锁定。
我知道为什么。这是因为为了实现我想要的水平滚动行为,我需要使中心列有溢出滚动。这杀死了使标题锁定在适当位置的位置粘性(仅适用于中心列)。
所以我知道导致它不工作的问题。但是我找不到一个纯CSS的解决方案。我可以使用JavaScript来实现这个功能,但是我正在努力找到一个纯CSS的解决方案。
我可以使用任何嵌套的html元素和样式需要我只是想要一个纯css的解决方案。

oewdyzsn

oewdyzsn1#

你不需要创建物理 Package 器DIV。只需创建你的单元格,将它们放在#grid元素中,然后使用CSS和:nth-child()伪类选择器,并将所需的行sticky分别设置为topleftright
下面是一个6列网格的例子:

// This JS is only used to dynamically generate the cells.

const el = (sel, par) => (par || document).querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
const repeat = (n, cb) => [...Array(n)].forEach((_, i) => cb(i));

const elGrid = el("#grid");
repeat(90, (i) => {
   elGrid.append(elNew("div", {
     className: "cell",
     textContent: `Cell ${i+1}`
   }));
});
body {
  font-family: Arial;
}

#grid {
  max-height: 180px;
  overflow-y: scroll;
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  
  .cell {
    border: 1px solid black;
    text-align: center;
    padding: 0.5rem;
    min-width: 20vw;
    
    /* leftmost column */
    &:nth-child(6n-5) {
      background: #ddd;
      position: sticky;
      left: 0;
    }
    
    /* rightmost column */
    &:nth-child(6n) {
      background: #ddd;
      position: sticky;
      right: 0;
    }
    
    /* top row */
    &:nth-child(-n+6) {
      background: #aaa;
      position: sticky;
      top: 0;
      z-index: 1;
    }
    
    /* first cell */
    &:nth-child(1) {
      z-index: 2;
    }

  }
}
<div id="grid"></div>

相关问题