Border inside Grid Layout
Asked Answered
A

8

14

I have a CSS grid that represents the tic-tac-toe game. I wanted to put an border only inside the grid. Today, I proceed in this way:

:root {
  --border: 2px dashed #393939;
  --symbol-color: #FF7F5B;
}

.grid {
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, calc(100%/3));
  grid-template-rows: repeat(3, calc(100%/3));
}

.child {
  display: flex;
  align-items: center;
  align-content: center;
  color: var(--symbol-color);
  font-size: 2.5rem;
}

.child:nth-child(1),
.child:nth-child(2),
.child:nth-child(3) {
  border-bottom: var(--border);
}

.child:nth-child(7),
.child:nth-child(8),
.child:nth-child(9) {
  border-top: var(--border);
}

.child:nth-child(1),
.child:nth-child(4),
.child:nth-child(7) {
  border-right: var(--border);
}

.child:nth-child(3),
.child:nth-child(6),
.child:nth-child(9) {
  border-left: var(--border);
}
<div class="grid">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Result:

Result

This solution works but I find it unattractive. Do you have an idea to refactor this solution?

Automata answered 29/3, 2018 at 11:18 Comment(3)
given snippet is not working. missed any css??Primine
I just copy / paste the interesting part of my problem, the snippets do not work because it misses the grid container. The HTML I copied in my post is an output of ReactJS. My main problem is to find a CSS factorization to put borders in the same way as it is shown in my screenshot. Thank you for your interest in my post!Automata
There is no align-content flex container property. I guess you meant justify-content.Indrawn
P
11

One thing you can use the nth-child selector in a better way like below instead of targeting one by one.

.child:nth-child(-n+3) {
  border-bottom: var(--border);
}

.child:nth-child(3n+1) {
  border-right: var(--border);
}

.child:nth-child(3n) {
  border-left: var(--border);
}

.child:nth-child(n+7) {
  border-top: var(--border);
}

:root {
  --border: 2px dashed #393939;
  --symbol-color: #FF7F5B;
}

.grid {
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, calc(100%/3));
  grid-template-rows: repeat(3, calc(100%/3));
}

.child {
  display: flex;
  align-items: center;
  align-content: center;
  color: var(--symbol-color);
  font-size: 2.5rem;
}

.child:nth-child(-n+3) {
  border-bottom: var(--border);
}

.child:nth-child(3n+1) {
  border-right: var(--border);
}

.child:nth-child(3n) {
  border-left: var(--border);
}

.child:nth-child(n+7) {
  border-top: var(--border);
}
<div class="grid">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
  <div class="child">5</div>
  <div class="child">6</div>
  <div class="child">7</div>
  <div class="child">8</div>
  <div class="child">9</div>
</div>
Primine answered 29/3, 2018 at 11:33 Comment(0)
B
27

Since you want a stylized border (dashed, in this case), then your approach and the approach taken in the other answers appears to be useful.

However, if you decide to use a simple, solid line border, then the approach can be simplified. Just use the background color of the grid for border color, and the grid-gap property for border width.

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  background-color: black;
  grid-gap: 1px;
  height: 100vh;
}

.child {
  background-color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #FF7F5B;
  font-size: 2.5rem;
}

body { margin: 0;}
<div class="grid">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child">X</div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child">O</div>
  <div class="child"></div>
</div>
Bulahbulawayo answered 29/3, 2018 at 12:46 Comment(3)
Indeed, for this solution, I need stylized border however, I did not know your solution for simple borders! I keep it in mind for next time, thank you!Automata
I do prefer this solution, and using a diagonally striped background would give you your dashes... css-tricks.com/stripes-cssVancouver
You could always have a background image in the main .grid div with dots for you to achieve the desired effect using this approachEnochenol
P
11

One thing you can use the nth-child selector in a better way like below instead of targeting one by one.

.child:nth-child(-n+3) {
  border-bottom: var(--border);
}

.child:nth-child(3n+1) {
  border-right: var(--border);
}

.child:nth-child(3n) {
  border-left: var(--border);
}

.child:nth-child(n+7) {
  border-top: var(--border);
}

:root {
  --border: 2px dashed #393939;
  --symbol-color: #FF7F5B;
}

.grid {
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, calc(100%/3));
  grid-template-rows: repeat(3, calc(100%/3));
}

.child {
  display: flex;
  align-items: center;
  align-content: center;
  color: var(--symbol-color);
  font-size: 2.5rem;
}

.child:nth-child(-n+3) {
  border-bottom: var(--border);
}

.child:nth-child(3n+1) {
  border-right: var(--border);
}

.child:nth-child(3n) {
  border-left: var(--border);
}

.child:nth-child(n+7) {
  border-top: var(--border);
}
<div class="grid">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
  <div class="child">5</div>
  <div class="child">6</div>
  <div class="child">7</div>
  <div class="child">8</div>
  <div class="child">9</div>
</div>
Primine answered 29/3, 2018 at 11:33 Comment(0)
I
5

You can reduce number of nth-child selector here from this answer.

body {
  margin: 0;
}

:root {
  --border: 2px dashed #393939;
  --symbol-color: #FF7F5B;
}

.grid {
  height: 100vh;
  display: grid;
  grid-template-columns: repeat(3, calc(100%/3));
  grid-template-rows: repeat(3, calc(100%/3));
}

.child {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--symbol-color);
  font-size: 2.5rem;
}

.child:not(:nth-child(3n)) {
  border-right: var(--border);
}

.child:not(:nth-last-child(-n + 3)) {
  border-bottom: var(--border);
}
<div class="grid">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child">x</div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child">o</div>
  <div class="child"></div>
</div>
Indrawn answered 9/4, 2018 at 18:0 Comment(0)
S
4

You may consider this workaround.

You may use grid-template-columns to do the trick.

  • create a parent container that will hold your four images.

  • set a background color (desire color of the border).

  • set the padding to 0

  • then do the trick arrange the images by grid-template-column: auto
    auto;

  • then add gap to them grid-gap: 10px; (to show the background color of the container as grid).

please see code below for reference

.container {
  width: 200px;
  display: grid;
  grid-template-columns: auto auto;
  grid-gap: 10px;

  background-color: #000;
  padding: 0;
}
.container > div {
  background-color: #ccc;
  padding: 20px;
  text-align: center;
}

html

<div class="container">
      <div>Image here</div>
      <div>Image Here</div>
      <div>Image here</div>
      <div>Image here</div>
    </div>

to help you visualize i create a sample code

http://plnkr.co/edit/gIeumXLt0k3FPVCgGlDd?p=preview

Hope it helps

Cheers!

Stephanus answered 16/7, 2019 at 8:7 Comment(0)
I
1

Try to make use of negative margin in .child class with overflow:hidden in parent .grid class here...No need to use nth-child selector here...

:root {
  --border: 2px dashed #393939;
  --symbol-color: #FF7F5B;
}

.grid {
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, calc(100%/3));
  grid-template-rows: repeat(3, calc(100%/3));
  overflow: hidden;
}

.child {
  height: 100px;
  display: flex;
  align-items: center;
  align-content: center;
  color: var(--symbol-color);
  font-size: 2.5rem;
  border-bottom: var(--border);
  border-left: var(--border);
  margin-left: -2px;
  margin-bottom: -2px;
}
<div class="grid">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>
Israel answered 29/3, 2018 at 12:15 Comment(1)
The nth-child selectors seem more understandable for code review than tricks with negative margins and overflow hidden. Thanks anyway !Automata
H
0

What about using background and linear-gradient:

body {
  margin: 0;
}

.grid {
  --b: #393939 0px, #393939 5px, transparent 5px, transparent 8px;
  height: 100vh;
  display: grid;
  grid-template-columns: repeat(3, calc(100% / 3));
  grid-auto-rows:calc(100% / 3);
  background: 
    repeating-linear-gradient(to right ,var(--b)) 0   calc(100% / 3), 
    repeating-linear-gradient(to bottom,var(--b)) calc(2 * (100% / 3)) 0, 
    repeating-linear-gradient(to right ,var(--b)) 0 calc(2 * (100% / 3)), 
    repeating-linear-gradient(to bottom,var(--b)) calc(100% / 3) 0;
  background-size:100% 2px,2px 100%;
  background-repeat: no-repeat;
}

.child {
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="grid">
  <div class="child">A</div>
  <div class="child">B</div>
  <div class="child">C</div>
  <div class="child">D</div>
  <div class="child">E</div>
  <div class="child">F</div>
  <div class="child">G</div>
  <div class="child">H</div>
  <div class="child">I</div>
</div>
Heraclitean answered 29/3, 2018 at 11:42 Comment(1)
I do not think that this solution is very pretty but I thank you for your answer, I will look at it !Automata
I
0

Im a bit late for that question but have a solution. Each child must have the border-right and border-bottom set. The parent div have pseudo over the edge border to mimic a removal. It only works if you use this on a plain background-color.

In my example, background is white.

<div class="grid">
  <div class="child">A</div>
  <div class="child">B</div>
  <div class="child">C</div>
  <div class="child">D</div>
  <div class="child">E</div>
  <div class="child">F</div>
  <div class="child">G</div>
  <div class="child">H</div>
  <div class="child">I</div>
</div>

CSS:

.grid{ display: flex; flex-wrap: wrap; position: relative; }
.grid:before{ border-right: 1px solid #fff; content: ''; display: block; right: 0; top: 0; bottom: 0; position: absolute; }
.grid:after{ border-bottom: 1px solid #fff; content: ''; display: block; left: 0; right: 0; bottom: 0; position: absolute;  }
.child{ border: 1px solid #000; border-width: 0 1px 1px 0; }
Interline answered 13/4, 2023 at 1:47 Comment(0)
L
0

You can do something like this :)

https://codepen.io/atnesness/pen/dyQabBM

main hack is in this code. Not that (6) should be replaced with the max amount of columns in your page

@for $i from 1 through 6 {
  @container (min-width: #{$i * $cardWidth}px) {
    .summary__item:nth-child(n):before {
       display: block;
    }
    
    .summary__item:nth-child(n):after {
      display: none;
    }

    .summary__item:nth-child(#{$i}n):before {
       display: none;
    }
    
    .summary__item:nth-child(#{$i}n):after {
      display: block;
      content: '';

      position: absolute;
      left: 0;
      
      transform: translateY(#{$cardHeight - $cardPadding * 2}px);

      width: 100%;
      height: 1px;
      background: black;
    }
  }
}


.summary .summary__item:last-child:before {
  display: none;
}

.summary .summary__item:last-child:after {
  display: none;
}

Leannleanna answered 2/8, 2023 at 0:24 Comment(1)
This is not a 3x3 tic-tac-toe tableAlyce

© 2022 - 2024 — McMap. All rights reserved.