Search code examples
htmlcssradial-gradients

How to position multiple CSS radial gradients in pseudo element background


I am working on building on Othello game board in html and css. I'm using a <table> element for the board, with 8 rows, containing 8 cells each. Pretty standard element structure.

To draw the black and white Othello game pieces within the table cell elements themselves (as well as a red dot for a most recent move indicator), I wanted to just be able to add certain classes to the <td> elements and have certain background styles applied using the :before pseudo element. Something like this:

<td class="circle white"></td> for where a white piece should be displayed

and

<td class="circle black"></td> for where a black piece should be displayed.

and something like

<td class="circle black most-recent-move"></td> for where a black piece was the most recent move made.

So far on that, I'm good using the following HTML and CSS:

#board-table tbody tr td.circle:before {
    content: "";
    display:inline-block;
    width:60px;
    height:60px;
    line-height: 60px;
    text-align: center;
    vertical-align: middle;
    border-radius: 50%;
    position:relative;
    left:3px;
}

#board-table tbody tr td{
    background-color:#2EAE52;
    padding:4px;
    min-height:70px;
    min-width:70px;
    height:70px;
    width:70px;
    border:solid 2px #000000;
}

#board-table tbody tr td.white:before {
    border:solid 2px white;
    background: linear-gradient(225deg, #959696 10%, #FFFFFF);
    background-repeat: no-repeat;
}

#board-table tbody tr td.black:before {
    border:solid 2px black;
    background: linear-gradient(225deg, #6c6c6c 10%, #000000);
    background-repeat: no-repeat;
}

#board-table tbody tr td.white.most-recent-move:before {
    border:solid 2px white;
    background-repeat: no-repeat;
    background: radial-gradient(circle, red 15%,rgba(255,0,0,0) 10%) 100%,
                linear-gradient(225deg, #959696 10%, #FFFFFF);
}

#board-table tbody tr td.black.most-recent-move:before {
    content: "";
    border:solid 2px black;
    background-repeat: no-repeat;
    background: radial-gradient(circle, red 15%,rgba(255,0,0,0) 10%) 100%,
                linear-gradient(225deg, #6c6c6c 10%, #000000);
}
<div>
<table id="board-table" cellpadding="0" cellspacing="0">
                        <thead>
                            
                        </thead>
                        <tbody>
                            <tr>
                                <td id="a1" class="circle"></td>
                                <td id="b1" class="circle"></td>
                                <td id="c1" class="circle"></td>
                                <td id="d1" class="circle"></td>
                                <td id="e1" class="circle"></td>
                                <td id="f1" class="circle"></td>
                                <td id="g1" class="circle"></td>
                                <td id="h1" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a2" class="circle"></td>
                                <td id="b2" class="circle black most-recent-move"></td>
                                <td id="c2" class="circle"></td>
                                <td id="d2" class="circle"></td>
                                <td id="e2" class="circle"></td>
                                <td id="f2" class="circle"></td>
                                <td id="g2" class="circle"></td>
                                <td id="h2" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a3" class="circle"></td>
                                <td id="b3" class="circle"></td>
                                <td id="c3" class="circle"></td>
                                <td id="d3" class="circle"></td>
                                <td id="e3" class="circle"></td>
                                <td id="f3" class="circle"></td>
                                <td id="g3" class="circle"></td>
                                <td id="h3" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a4" class="circle"></td>
                                <td id="b4" class="circle"></td>
                                <td id="c4" class="circle"></td>
                                <td id="d4" class="circle white"></td>
                                <td id="e4" class="circle black"></td>
                                <td id="f4" class="circle"></td>
                                <td id="g4" class="circle"></td>
                                <td id="h4" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a5" class="circle"></td>
                                <td id="b5" class="circle"></td>
                                <td id="c5" class="circle"></td>
                                <td id="d5" class="circle black"></td>
                                <td id="e5" class="circle white"></td>
                                <td id="f5" class="circle"></td>
                                <td id="g5" class="circle"></td>
                                <td id="h5" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a6" class="circle"></td>
                                <td id="b6" class="circle"></td>
                                <td id="c6" class="circle"></td>
                                <td id="d6" class="circle"></td>
                                <td id="e6" class="circle"></td>
                                <td id="f6" class="circle"></td>
                                <td id="g6" class="circle"></td>
                                <td id="h6" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a7" class="circle"></td>
                                <td id="b7" class="circle"></td>
                                <td id="c7" class="circle"></td>
                                <td id="d7" class="circle"></td>
                                <td id="e7" class="circle"></td>
                                <td id="f7" class="circle"></td>
                                <td id="g7" class="circle"></td>
                                <td id="h7" class="circle"></td>
                            </tr>
                            <tr>
                                <td id="a8" class="circle"></td>
                                <td id="b8" class="circle"></td>
                                <td id="c8" class="circle"></td>
                                <td id="d8" class="circle"></td>
                                <td id="e8" class="circle"></td>
                                <td id="f8" class="circle"></td>
                                <td id="g8" class="circle"></td>
                                <td id="h8" class="circle"></td>
                            </tr>            
                        </tbody>
                    </table>
                  </div>

The problem I'm having is with adding "star points" to the board. There are 4 star points that I want to put on the board - little black dots at the corners of the inner 16 (4 x 4) squares. These star points need to be shown at all times, whether there are game pieces around them or not. You can see them in this image

I've tried adding a third radial gradient to some of the background gradients I already have but then that third gradient seems to be taking over the entire table cell and nothing else gets displayed. I can't seem to figure out a way to position the little black circles where I want them without messing up what I already have.

I'm also a little unsure about whether I should continue using the :before pseudo element of a <td> or if maybe I should add all the dots to the :before of the <table> instead or something else. I don't do a lot of CSS work usually so this is a bit of a challenge for me to get figure out.


Solution

  • If you are open to a different idea, I would change the markup and use a grid layout then create the board (with the dots) using gradients.

    I removed all the ID for the sake of the demo but you can easily put them back.

    .board {
      --t: 3px; /* line thickness */
      
      display: grid;
      max-width: 800px;
      margin: auto; 
      grid-template-columns: repeat(8,1fr); /* 1fr to keep things responsive, changed with a pixel for fixed size */
      aspect-ratio: 1;
      border: calc(var(--t)/2) solid #000;
      background:
        /* the 4 dots above the grid */
        radial-gradient(calc(3*var(--t)),#000 90%,#0000) 0 0/50% 50%,
        /* the grid lines */
        conic-gradient(from 90deg at var(--t) var(--t),#0000 25%,#000 0)
        calc(var(--t)/-2) calc(var(--t)/-2)/calc(100%/8) calc(100%/8)
        /* the main color */
        #2EAE52;
    }
    .board > div {
      width: 80%;
      aspect-ratio: 1;
      border-radius: 50%;
      margin: auto;
      box-sizing: border-box;
    }
    .white {
      border: solid 2px #fff;
      background: var(--b, ) linear-gradient(225deg, #959696 10%, #fff);
    }
    .black{
      border: solid 2px #000;
      background: var(--b, ) linear-gradient(225deg, #6c6c6c 10%, #000);
    }
    .most-recent-move {
      --b: radial-gradient(red 15%,#0000 16%),;
    }
    <div class="board">
      <!-- 1st row -->
      <div class="white"></div><div class="black"></div><div></div><div></div><div></div><div></div><div></div><div></div>
      <!-- 2nd row and so on -->
      <div></div><div class="white most-recent-move"></div><div class="black most-recent-move"></div><div></div><div></div><div></div><div></div><div></div>
      
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
      
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
      
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
      
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
      
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
      
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
    </div>