在CSS Grid中防止双重边框

89

在当前的CSS网格示例中,如何折叠边框以避免双重边框?

使用HTML表格很容易实现这一点。但是如果要使用display: grid,该怎么做呢?

.wrapper {
  display: grid;
  grid-template-columns: 50px 50px 50px 50px;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border: 1px solid black;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

10个回答

93

不要在网格项周围使用实际边框,而是使用容器的背景色(作为“边框”颜色)和grid-gap属性(作为“边框”宽度)。

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  border: 1px solid black;
  grid-gap: 1px;
  background-color: black;
}

.wrapper > div {
  background-color: white;
  padding: 15px;
  text-align: center;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>


@pttsky 你可以改变整个 div 的不透明度。 - Mohammed Joraid
1
它不起作用,存在不同的边框宽度。 - Maksim Shamihulau
3
如果单元格有不同的边框大小/颜色,则此方法无效。 - Onur Arı
这个想法的一个补充是在每个瓦片上使用“轮廓”属性。 - Richard Fogaca Nienkotter
1
我注意到间隙存在轻微变化,可能并不总是被准确地遵守。 - Ambrus Tóth

80

你可以这样做:

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  border-bottom: 1px solid black;
  border-left: 1px solid black;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border-top: 1px solid black;
  border-right: 1px solid black;
}

body {
 background:pink;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

另一个思路是依靠渐变来填补以下空白:

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  grid-gap:1px;
  background:
    linear-gradient(#000,#000) center/100% 1px no-repeat,
    repeating-linear-gradient(to right,transparent 0 50px,#000 0 51px);
  border:1px solid;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
}

body {
 background:pink;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

您还可以调整初始解决方案,使其更具灵活性,并适用于行内任意数量的项目。

在完整页面上运行以下代码并调整窗口大小:

.wrapper {
  display: grid;
  max-width:800px;
  grid-template-columns: repeat(auto-fill,minmax(100px,1fr));
  border-top: 1px solid black;
  border-left: 1px solid black;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid black;
  border-right: 1px solid black;
}

body {
 background:pink;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>
</div>


这个答案在非实线和半透明边框下效果更好。然而,单元格项目在这里是49像素,可能有点麻烦。这很容易修复。 - René
3
如果容器有上边框,这样的话如果网格中只有6个项目,网格就不会出现随机线条,会更加合理。 - GeorgeButter
1
这是真正的答案!它甚至可以处理包装内容。 - Hairi
这个解决方案很好,但有一个缺点:元素本身在调整大小时会改变宽度。这使得它不太适合构建移动响应式的分页器,在那里我希望所有元素始终都是完美的正方形。 - Jay
@Jay https://dev59.com/A2025IYBdhLWcg3wNTEV#68073761 / https://dev59.com/XVQI5IYBdhLWcg3w9AYl#54927248 - Temani Afif
感谢您的建议。但是,有预定义的列数,我希望保持这些列的动态性。似乎无法使用纯CSS实现:https://dev59.com/2bLma4cB1Zd3GeqPaGWL。 - Jay

34

我通过使用outline属性找到了解决方案。

.grid {
 width: 100%;
 height: 700px;
 display: grid;
 grid-template-columns: repeat(4, 25fr);
 grid-template-rows: repeat(4, 25fr);
 margin-bottom: 30px;
 grid-gap: 1px;
}

.grid-item {
 background-color: silver;
 outline: 1px solid gray; /* The outline creates the border */
 text-align: center;
 position: relative;
 z-index: 1; /* original z-index */
}

/* If you want to change the color on the hover state */
.grid-item:hover {
 outline: 1px solid red;
 z-index: 2; /* You must apply a z-index bigger than the original z-index or else some parts of the outline will be behind other grid elements */
}
<div class="grid">
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
</div>


3
只需添加.grid { grid-gap: 1px; }即可修复元素重叠问题。 - EoghanM

27

.wrapper {
  display: grid;
  grid-template-columns: 50px 50px 50px 50px;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border: 1px solid black;
  margin:0 -1px -1px 0;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

margin:0 -1px -1px 0; 

这应该可以解决问题。


2
有点取巧,但至少能解决问题。真不敢相信没有更简单的方法来做这件事。我可能要用 flexbox 来构建我的网格了。 - klugjo

14

有一种简单的方法来完成这个任务:

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 1px;
}

.grid__item {
  border: 1px solid gray;
  box-sizing: content-box;
  width: 100%;
  height: 100%;
}
<div class="grid">
  <div class="grid__item">1</div>
  <div class="grid__item">2</div>
  <div class="grid__item">3</div>
  <div class="grid__item">4</div>
  <div class="grid__item">5</div>
  <div class="grid__item">6</div>
  <div class="grid__item">7</div>
  <div class="grid__item">8</div>
  <div class="grid__item">9</div>
  <div class="grid__item">10</div>
  <div class="grid__item">11</div>
  <div class="grid__item">12</div>
</div>

顺便提一句,关键在于box-sizing: content-box。如果你不需要全局覆盖它的其他值,那么你就不需要它。但是很多人使用border-box,在这种情况下,这种覆盖可以解决间隙问题。


4

我成功使用的方法是给网格项添加一个盒子阴影,同时加上列和行间距。这样可以确保列的大小始终与grid-template-columns中定义的一样。 然后只需更改列和行间距以及盒子阴影的大小即可实现更粗的边框。

.wrapper {
  display: grid;
  grid-template-columns: 50px 50px 50px 50px;
  grid-column-gap: 1px;
  grid-row-gap: 1px;
}
.wrapper > div {
  padding: 15px;
  text-align: center;
  box-shadow: 0 0 0 1px;
}
<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>


如果您只想要顶部和底部边框,而左侧和右侧没有边框,则此方法非常有效。网格:row-gap: 1px项目:box-shadow: 0 1px black, 0 -1px black; - mfgmicha

0
如果你的网格在行和列上有相同数量的项目,并且大小也相同(类似于井字棋游戏),那么你可以将一半的边框放在包含的 div 上(即你添加了网格样式的那个 div),另一半放在每个内部容器上,这样它们就都只有正常的边框宽度。

0
对于那些遇到奇数个元素和特定数量帧的人,可以使用以下方法。
<style>
  .wrapper {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    border: 1px solid;
    grid-gap: 1px;
  }

  .element {
    display: flex;
    flex-direction: column;
    background-color: azure;
    min-height: 10rem;
    border: 1px solid;
    margin: -1px;
  }
</style>

<body>
  <div class="wrapper">
    <div class="element"></div>
    <div class="element"></div>
    <div class="element"></div>
    <div class="element"></div>
    <div class="element"></div>
    <div class="element"></div>
  </div>
</body>

https://codepen.io/sergeytkhojevskiy/pen/XWZOJOL


-1
如果您想要固定每行的项目数量,那么这个解决方案适合您,
这个例子是每行3个,但您可以进行编辑。

.grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr;
  gap: 0;
  grid-template-areas: '. . .';
}

.grid-item {
  order: 0;
  flex: 0 1 auto;
  text-align: center;
  padding: 1rem;
  font-size: 12px;
  background-color: #e8e8e8;
  border-color: #000;
  border-style: solid;
  border-width: 0;

  border-right-width: 1px;
  border-bottom-width: 1px;
}

/*first 3 items*/
  .grid-item:nth-child(-n + 3) {
    border-top-width: 1px;
  }

/*last item on each row*/
  .grid-item:nth-child(3n + 0) {
    border-right-width: 1px;
    background-color: cadetblue;
  }
  
/*first item on each row*/

.grid-item:first-child,
  .grid-item:nth-child(3n + 1) {
    border-left-width: 1px;
    background-color: red;
  }
  
/*middel item on each row (not used)*/
  .grid-item:nth-child(3n - 1) {
   // border-left-width: 1px;
   background-color: yellow;
  }

/*last item (not used)*/
  .grid-item:last-child {
   // border-left-width: 0;
    background-color: green
    }
<div class="grid-container">

<div class="grid-item"> 1 </div>

<div class="grid-item"> 2 </div>

<div class="grid-item"> 3 </div>

<div class="grid-item"> 1 </div>

<div class="grid-item"> 2 </div>

<div class="grid-item"> 3 </div>

<div class="grid-item"> 1 </div>

<div class="grid-item"> 2 </div>


</div>


-1

双赢的代码应该设置:

  • 网格项:border-bottom和border-right
  • 网格包装器:border-top和border-left

这样即使顶部列与底部列不相等也可以正确显示。

.wrapper {
  display: inline-grid;
  grid-template-columns: 50px 50px 50px 50px;
  border-top: 1px solid black;
  border-left: 1px solid black;
}

.wrapper > div {
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid black;
  border-right: 1px solid black;
}

<div class="wrapper">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接