0

I am doing The Odin Project right now and I am on the Tic Tac Toe project. I am sure this will be very difficult for me but I am looking forward to it. However, I am here to ask for help with setting the board up in HTML and CSS. How would I even go about this?

<div class="board" id="upperLeft"></div>
<div class="board" id="upperCenter"></div>
<div class="board" id="upperRight"></div>
<div class="board" id="middleLeft"></div>
<div class="board" id="middleCenter"></div>
<div class="board" id=middleRight></div>
<div class="board" id="lowerLeft"></div>
<div class="board" id="lowerMiddle"></div>
<div class="board" id="lowerRight"></div>
InSync
  • 4,851
  • 4
  • 8
  • 30
Natsu
  • 49
  • 3

4 Answers4

1

You can use CSS grids to lay it out.

.board {
  width: 500px;
  height: 500px;
  margin: 0 auto;
  
  display: grid;
  grid-template-columns: auto auto auto;
}

.box{
  border: 3px solid;
  border-radius: 2px;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="board">
  <div class="box" id="upperLeft"></div>
  <div class="box" id="upperCenter"></div>
  <div class="box" id="upperRight"></div>
  <div class="box" id="middleLeft"></div>
  <div class="box" id="middleCenter"></div>
  <div class="box" id="middleRight"></div>
  <div class="box" id="bottomLeft"></div>
  <div class="box" id="bottomCenter"></div>
  <div class="box" id="bottomRight"></div>
</div>

Also, you can make everything a member of one class by including it in one big div like I did with the board :)

Connie
  • 251
  • 4
  • 17
0

You can use grid; this way, cells can be direct children of the board:

<div id="board">
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
</div>
#board {
  display: grid;

  /* Make three rows of equal height */
  grid-template-rows: repeat(3, 1fr);
  /* Make three columns of equal width */
  grid-template-columns: repeat(3, 1fr);

  /* Controls the gap between cells */
  gap: 1em;

  /* A size of your choice */
  height: 400px;
  /* Make it a perfect square */
  aspect-ratio: 1 / 1;
}

Try it:

#board {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  grid-template-columns: repeat(3, 1fr);
  gap: 1em;
  margin: 2em auto;
  height: 400px;
  aspect-ratio: 1 / 1;
}

.cell {
  background: #ddd;
}
<div id="board">
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
</div>
InSync
  • 4,851
  • 4
  • 8
  • 30
0

The following example uses flexbox and vmin which makes it fluidly adaptable to most viewport sizes. Excluding edge cases (TBH, I can't think of any), the squares always maintain even lengths and and the whole game will always be centered vertically and horizontally within the viewport. The line feature is controlled by changing classes on div.line.

As a bonus a <dialog> is included which is under the OPTION comment as a popup to display a message as to who won and buttons for the user to exit or play again. JavaScript is required for it to function of course (see <dialog>)

Details are commented in example

/**
 * All lengths (with the exception of outlines) are in "vmin"
 * ex. 5vmin = 5vh
 *             if viewport height is smaller than viewport width.
 *                                 OR
 *             5vw 
 *             if viewport width is smaller than viewport height.
 */
 
:root {
  font: 5vmin/1 "Segoe UI";
}

/**
 * All elements center it's contents vertically and horizontally.
 * "form" is part of the <dialog> (see OPTION below)
 * it is not required.
 */
body,
main,
.frame,
.square,
form {
  display: flex;
  justify-content: center;
  align-items: center;
}

body {
  min-height: 100vh;
  padding: 0;
  background: white;
  overflow: hidden;
}

main {
  flex-flow: row wrap /* ".square"s will orient in rows and will
                         make a new row when 3 of them have
                         filled the previous row */ ;
  position: relative /* This sets the borders of "main" as the
                        reference for ".frame" positioning */ ;
  width: 75vmin;
  height: 75vmin;
}

.square {
  width: 25vmin;
  height: 25vmin;
  margin: 0;
  outline: 3px inset grey;
  font-size: 5rem;
  font-family: Consolas /* Monospaced fonts center the best */ ;
  vertical-align: middle;
  text-transform: uppercase;
  cursor: pointer;
}

.frame {
  position: absolute /* Sets ".frame" out of normal "flow" so
                        that it's dimensions do not interfere
                        with the "static" of the elements */ ;
  z-index: 1 /* Brings ".frame" above the "static" elements in
                the z-axis */ ;
  top: 0 /* Position top left corner to the top of "main" */;
  left: 0 /* Position top left corner to the left of "main" */ ;
  min-width: 100%;
  min-height: 100%;
  outline: 3vw solid white /* Mask the outer edges of all ".square" */ ;
  overflow: hidden /* Hide all content that exceeds it's borders */ ;
  pointer-events: none /* ".frame" sits above all of the ".square"s 
                          which also blocks the user from clicking 
                          or hovering over any ".square". This allows
                          ".frame" to be bypassed so that ".square" is
                          clickable and hoverable again */ ;
}

.line {
  position: relative /* ".line" references it's original position
                        when moving to a new position */ ;
  min-width: 150%;
  height: 3vmin;
  border: 0;
  background: black;
  transform-origin: center center /* Allows it to spin from it's
                                     center when it rotates */;
}

/**
 * Line positions are assigned by a class to ".line"
 * Each number represents the position of a ".square"
 * ".s000" hides ".line" which is it's normal state
 */
/* No ".line" */
.s000 {
  display: none;
}
/* Top horizontal */
.s123 {
  bottom: 25vmin;
}
/* Middle horizontal */
.s456 {/* This is default position the same effect can be 
          accomplished by not assigning any class to ".line"*/ }
/* Bottom horizontal */
.s789 {
  top: 25vmin;
}
/* Left vertical */
.s147 {
  right: 25vmin;
  transform: rotate(90deg);
}
/* Center vertical */  
.s258 {
  transform: rotate(90deg);
}
/* Right vertical */
.s369 {
  left: 25vmin;
  transform: rotate(90deg);
}
/* Left to right diagonal */
.s159 {
  transform: rotate(45deg);
}
/* Right to left diagonal */
.s357 {
  transform: rotate(-45deg);
}

/* OPTION */
dialog {
  position: fixed;
  z-index: 2;
  border-radius: 8px;
}

dialog::backdrop {
  background: rgba(0, 0, 0, 0.3);
}

form {
  flex-flow: column nowrap;
  font-variant: small-caps;
}

fieldset {
  border: 0;
}

#message {
  font-size: 3rem;
  text-align: center;
}

input {
  width: 5rem;
  font: inherit;
  font-size: 2rem;
  vertical-align: middle;
  cursor: pointer;
}
<main>
  <div class="square">x</div>
  <div class="square">o</div>
  <div class="square">o</div>
  <div class="square"></div>
  <div class="square">x</div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square">x</div>
  <section class="frame">
    <div class="line s159"></div>
  </section>
</main>

<!-- OPTION -->
<dialog>
  <form method="dialog">
    <output id="message">X wins!</output>
    <fieldset>
      <input type="submit" value="Exit">
      <input type="submit" value="Play">
    </fieldset>
  </form>
</dialog>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
0

1.Here's a table that would help.

2.Html:

    <table>
<tr>
    <td></td>
    <td></td>
    <td></td>
</tr>
<tr>
    <td></td>
    <td></td>
    <td></td>
</tr>
<tr>
    <td></td>
    <td></td>
    <td></td>
</tr>
3.Css:
    td {
        border: 1px solid black; 
        height: 50px;
        width: 50px;
        }
  • Hello and welcome to the contributor side of things :) Note that you should improve your answer, e.g. by giving more explanation in how it works, why it works, what the difference to other answers is etc. This will help the OP to better understand your suggestion and choose the best answer for him-/herself – randmin Jun 13 '23 at 19:38