0

I'm making a chess game with the HTML5 canvas and I'm having trouble getting the rank and file labels to display correctly. By labels I mean the 1,2,..,8 and A,B,...H text that is positioned around the outskirts of the board to uniquely identify board positions. Currently I'm using two divs outside of the "board" element to display the the labels. The way I currently do this isn't responsive and often doesn't display properly when shown on devices other than the one I designed it on. The text for the file (letters) and rank (numbers) might be different sizes, or the characters might not align with the center of each column or row.

This is what the board looks like when everything is working as intended chess board

And here's the problem I run into on the phone. The letters don't line up with the tiles of the board, as well as the control widget moving outside the page:enter image description here

chessboard = document.getElementById('chessboard');
ctxPiece = document.getElementById('chesspieceCanvas').getContext('2d');
ctxHighlight = document.getElementById('highlight').getContext('2d');

drawBoard(chessboard, chessboard.getContext('2d'));

function drawBoard(canvas, ctx) {
 var rows = 8;
 TILE_SIZE = canvas.height / rows;
    var white = true;
    var TILE_COLOR1 = "rgb(160,82,45)";
  var TILE_COLOR2 = "rgb(245,222,179)";
    for (var row = 0; row < rows; row++) {
        for (var col = 0; col < rows; col++) {
            if (!white) {
                ctx.fillStyle = TILE_COLOR1;
                ctx.fillRect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                white = true;
            } else {
                ctx.fillStyle = TILE_COLOR2; 
                ctx.fillRect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                white = false;
            }
        }
        white = !white;
    }
}
#gameArea {
    width: 650px;
    font-size: 16px;
}

#output {
    text-align: center;
}
  #outputMessage {
      display: inline-block;
      font-size: 2.5em;
      font-weight: bold;
  }

#boardAndInfo {
    overflow: visible;
    position: relative;
    width: 1000px;
}

#board {
display: inline-block;
border: 0.12em solid black;
height: inherit;
position: relative;
width: 600px;
line-height: 0;
overflow: hidden;
}

#chessboard {
    position: absolute;
    z-index: 0;
}

#highlight {
    position: absolute;
    z-index: 1;
}

#gameInfo {
    display: inline-block;
    height: 585px;
    width: 190px;
    vertical-align: top;
    position: relative;
}

#fileNotation {
    color: gray;
    font-size: 2.0em;
    margin-left: 50px;
    letter-spacing: 54px;
}

#chesspieceCanvas {
    font-size: 70px;
    font-family: 'Open Sans', sans-serif;
    position: relative;
    z-index: 2;
}

#rankNotation {
    color: gray;
    float: left;
    font-size: 2.0em;
    line-height: 235%;
    position: relative;
    width: 1.5ch;
    word-wrap: break-word;
}
<body>
 <div id='gameSynopsis'>
 </div>
 <div id="gameArea" lang='en'>
   <div id="output">
      <span id="outputMessage">Some text here</span>
      <span id="aiThinkingIndicator" class="loading hide"></span>
    </div>
   <div id="fileNotation" class="boardLabel">
      ABCDEFGH
   </div>
   <div id="rankNotation" class="boardLabel">
      87654321
   </div>
   <div id="boardAndInfo">
    <div id="board">
     <canvas id="chessboard" width="600" height="600"></canvas>
     <canvas id="highlight" width="600" height="600"></canvas>
     <canvas id="chesspieceCanvas" width="600" height="600">
      <p id='canvasSupportMsg'></p>
     </canvas>
    </div>
    <fieldset id="gameInfo">
     <legend id='gameInfoTitle'>Stuff</legend>
    </fieldset>
   </div>
  </div>
</body>

The fiddle for my game can be found here. If I'm missing anything else please let me know.

I'm looking for a way to change the way this works in order to have it scale properly but I haven't been able to find a solution yet.

Greener
  • 1,327
  • 3
  • 13
  • 19
  • 3
    Maybe provide a complete snippet/fiddle so we can reproduce the problems you face. – trincot Sep 03 '17 at 19:46
  • How are the dimensions of your board squares determined? Are they fixed, or do they vary with the viewport size? – arbuthnott Sep 03 '17 at 20:04
  • give a try to vw , vh or vmin/vmax values , but it is only a guess we see nothing in action (canvas's size ? ) – G-Cyrillus Sep 03 '17 at 20:52
  • @trincot I've made some changes which hopefully remedy that problem – Greener Sep 11 '17 at 21:01
  • @arbuthnott they don't vary with viewport size currently. How does one know how to scale elements properly for so many viewing devices? Media queries? – Greener Sep 11 '17 at 21:03
  • If I were you, I'd abandon pixel `width` and `height` entirely, and go for `vw` and `vh` instead. One `vw` is 1% of the viewport width, and one `vh` is one percent of the viewport height. That way, the board can resize automatically. You could also consider a `max-width` to keep the board reasonably sized on large displays. For letter spacing, you may consider `letter-spacing: calc( vw / 8);` where `vw` obviously has the same with as the board. – Tijmen Sep 11 '17 at 21:12
  • @Greener Sure, media queries can work. But they may also be (for ex) a percentage of the `body` width or something. There's a solution to your problem either way, but it would vary depending on which. – arbuthnott Sep 11 '17 at 21:13

1 Answers1

0

Here's what I ultimately ended up doing and I'm pretty happy with the result. I wasn't able to figure out a solution using straight HTML and CSS but hopefully this might be of use to someone else down the road.

I created wrappers for the individual components of the rank and file and applied styles to each element to set the spacing between them. The individual element wrappers for the letters and numbers are formatted as they are to eliminate the white-space that is created between inline elements by default.

<div id="rank" class="boardLabel">
   <div class="rankNumber">8</div>
   <div class="rankNumber">7</div>
   <div class="rankNumber">6</div>
   <div class="rankNumber">5</div>
   <div class="rankNumber">4</div>
   <div class="rankNumber">3</div>
   <div class="rankNumber">2</div>
   <div class="rankNumber">1</div>
</div>

<div id="fileNotation" class="boardLabel">
   <span class="fileLetter">A
   </span><span class="fileLetter">B
   </span><span class="fileLetter">C
   </span><span class="fileLetter">D
   </span><span class="fileLetter">E
   </span><span class="fileLetter">F
   </span><span class="fileLetter">G
   </span><span class="fileLetter">H
   </span>
</div>

The following Javascript/jQuery code is then used to set the spacing

// to set the rank spacing
var tileSize = $('#board').height() / 8;
$('.rankNumber').css('line-height', tileSize + 'px');

// to set file spacing   
$('#file > .fileLetter').width($('#board').width() / 8);

Essentially the board width is divided by 8 to calculate the width of each file element (as chess is played on an 8x8 grid), with a similar process occurring for calculating the height. This calculation is then used to set the value for the relevant CSS properties. For the file I added a left-margin with the same magnitude as the width of the rank so that it aligned properly with the start of the board

If one would like more information on the issue it can be obtained from the Stack Overflow question, How to remove the space between inline-block elements?.

Greener
  • 1,327
  • 3
  • 13
  • 19