如何定位 CSS 网格中的最后一列?

How to target the last column in a CSS grid?

当您使用 grid-areas 时,元素的顺序可能会改变。这将导致视觉 :last-child 发生变化。是否有一个 CSS 选择器来定位网格中的最后一列?类似于 :last-grid-column.

我正在尝试解决的问题。我喜欢用边框线分隔列。但是我不希望最后一列有边框,因为那样在视觉上没有意义。现在,如果我用 :last-child 定位它,它会起作用,直到我将 grid-template-areas 的顺序更改为 d b c a 之类的东西。现在第一列没有边框,因为在 DOM 中它仍然是最后一个子项。

我知道你可以解决你明确说这些是网格区域的问题,在这种情况下我会省略 a 的边框。但是如果我能用语义来描述它会更加灵活,那么我可以自由地改变模板区域而不用担心边界线会被弄乱。

.grid 
{
  display: grid;
  grid-template-areas: "d b c a";
  grid-template-columns: repeat( 4, 1fr );
}

.column.a { 
  grid-area: a; 
}

.column.b { 
  grid-area: b; 
}

.column.c { 
  grid-area: c; 
}

.column.d { 
  grid-area: d; 
}

.column:not(:last-child) {
  border-right: 1px solid black;
}

/* Flavor */
.grid 
{
  margin: 20px auto;
  max-width: 600px;
  padding: 20px;
  background: #F4F4F4;
}

.column { 
  width: 100%; 
  text-align: center;
}
<div class="grid">
  <div class="column a">A</div>
  <div class="column b">B</div>
  <div class="column c">C</div>
  <div class="column d">D</div>
</div>

解决此问题的一种方法是在容器元素上使用伪元素显示每一列的边框并隐藏最后一列的边框,其中 CSS:

.grid::after {
   content: '';
   position: absolute;
   width: 20px;
   right: 0;
   height: 100%;
   background: #F4F4F4;
}

这里的技巧是让伪元素与容器 .grid 元素的颜色相同,并且其宽度等于 .grid 元素的填充。

为了使该解决方案更易于维护,您可以对 .grid 元素的 paddingbackground-color 使用 CSS 变量。

演示

.grid {
  display: grid;
  grid-template-areas: "d c b a";
  grid-template-columns: repeat( 4, 1fr);
  margin: 20px auto;
  max-width: 600px;
  padding: 20px;
  background: #F4F4F4;
  position: relative;
}

.column.a {
  grid-area: a;
}

.column.b {
  grid-area: b;
}

.column.c {
  grid-area: c;
}

.column.d {
  grid-area: d;
}

.column {
  width: 100%;
  text-align: center;
  border-right: 1px solid black;
}

.grid::after {
   content: '';
   position: absolute;
   width: 20px;
   right: 0;
   height: 100%;
   background: #F4F4F4;
}
<div class="grid">
  <div class="column a">A</div>
  <div class="column b">B</div>
  <div class="column c">C</div>
  <div class="column d">D</div>
</div>

这是之前的演示,其中包含一些 Javascript 以允许动态更改 grid-template-areas 属性。

const grid = document.querySelector(".grid");
const btn = document.querySelector("button");

btn.addEventListener("click", () => {
  grid.classList.toggle("change-column-order");
});
.grid {
  display: grid;
  grid-template-areas: "a b c d";
  grid-template-columns: repeat( 4, 1fr);
  margin: 20px auto;
  max-width: 600px;
  padding: 20px;
  background: #F4F4F4;
  position: relative;
}

.column.a {
  grid-area: a;
}

.column.b {
  grid-area: b;
}

.column.c {
  grid-area: c;
}

.column.d {
  grid-area: d;
}

.column {
  width: 100%;
  text-align: center;
  border-right: 1px solid black;
}

.grid::after {
   content: '';
   position: absolute;
   width: 20px;
   right: 0;
   height: 100%;
   background: #F4F4F4;
}

.change-column-order {
  grid-template-areas: "d c b a";
}
<div class="grid">
  <div class="column a">A</div>
  <div class="column b">B</div>
  <div class="column c">C</div>
  <div class="column d">D</div>
</div>

<button>Change Column Order</button>

这样selector exist但我们还远远没有对它有很好的支持。您可以阅读:

To be able to represent such implied column-based relationships, the column combinator and the :nth-col() and :nth-last-col() pseudo-classes are defined

对于您的具体情况,背景可以胜任:

.grid 
{
  display: grid;
  grid-template-areas: "d b c a";
  grid-template-columns: repeat( 4, 1fr );
  background:
    linear-gradient(90deg,#0000 calc(100% - 1px), #000 0)
    0 50%/calc((100% + 1px)/4) 50% repeat-x
    #F4F4F4;
}

.column.a { 
  grid-area: a; 
}

.column.b { 
  grid-area: b; 
}

.column.c { 
  grid-area: c; 
}

.column.d { 
  grid-area: d; 
}


/* Flavor */
.grid 
{
  margin: 20px auto;
  max-width: 600px;
  padding: 20px;
}

.column { 
  width: 100%; 
  text-align: center;
}
<div class="grid">
  <div class="column a">A</div>
  <div class="column b">B</div>
  <div class="column c">C</div>
  <div class="column d">D</div>
</div>