CSSだけでオセロゲームを作ってみる

CSS Gridの記事を見ているときにふと、「これオセロ作れそう」と思いたち作ってみました。
作る過程で色々学びがあったのでメモします。

デモはこちら（クリックでコマめくります）

<p class="codepen" data-height="550" data-theme-id="0" data-default-tab="html,result" data-user="kawamataryo" data-slug-hash="eoRPpg" style="height: 550px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="Othello  build with CSS only">
  <span>See the Pen <a href="https://codepen.io/kawamataryo/pen/eoRPpg/">
  Othello  build with CSS only</a> by ryo (<a href="https://codepen.io/kawamataryo">@kawamataryo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# ボードの作り方 [CSS grid]
ボードはCSS gridを使い作成します。
CSS gridについてはこちらの記事で、とてもわかりやすく解説されていました。
https://app.codegrid.net/entry/display-grid-1

たったこれだけの記述で8x8のマス目を持つボードを作成できます！

```slim
div.grid
  div
```

```scss
.grid {
  background-color: #008000;
  padding: 10px;
  width: 400px;
  height: 400px;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  
  div {
    border: 1px solid #000;
  }
}
```

# コマの作り方 [:Checked]
結構詰まったのが、CSSだけで以下3の状態を保持することです。

|透明|黒|白|
|---|---|---|
|<img width="60" alt="スクリーンショット 2019-04-13 10.38.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/4f323546-09cf-0045-0e85-8a262abea843.png"> |<img width="59" alt="スクリーンショット 2019-04-13 10.38.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/75d5739f-2950-9e21-a1e5-d310ea32e703.png"> | <img width="59" alt="スクリーンショット 2019-04-13 10.38.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/5f161157-42e5-4355-b52a-e5ae20510ada.png">

「CSS 状態保持」で色々調べていると、
チェックボックスやラジオボタンなどの疑似要素:checkedを使うと良さそうという記事を見つけたのでやってみました。

HTML部分（pug）

```slim
  div(id='disc-1')
    input(id='none-1' type='radio' name='field-1' class='none' checked)
    label(for='white-1')
    input(id='white-1' type='radio' name='field-1' class='white')
    label(for='black-1')
    input(id='black-1' type='radio' name='field-1' class='black')
    label(for='none-1')
```

CSS部分（scss）

```scss
 div {
    border: 1px solid #000;
    padding: 3px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  input {
    display: none;
  }
  label {
    display: none;
    cursor: pointer;
    line-height: 0;
    width: 90%;
    height: 90%;
    border-radius: 50%;
  }
  input {
    &:checked + label {
      display: inline-block;
    }
    &.none + label {
      background-color: transparent;
    }
    &.black + label {
      background-color: #000;
    }
    &.white + label {
      background-color: #fff;
    }
  }
```

ポイントは、labelのfor=""部分で次のコマの状態を指定していることです。
こうすることで、表示されているコマをクリックすると、次ののコマがclickedになり、disｐlay: noneからdisplay: inline-blockに変わり描画されます。
あとは、その繰り返しで3つの状態でループを作れば完了です。

![名称未設定2.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/31a27e82-b386-750e-c821-0d59d72154aa.jpeg)


これ使えば、3つと限らずクリックに合わせた色々な状態を保持ができそうです。


# 終わりに
CSS grid使ってみようで初めたオセロ作りですが、ほぼほぼオセロのコマの状態管理に時間使いました。
CSS gridは、htmlの順番を無視した、かなり自由な配置が可能なので何かと便利そうです。
特にレスポンシブデザインでの配置換えに使えそうですね。
また、checkedBoxでの状態管理は使い所はいまいち見つかりませんが、表現の幅は広がりそうです。

# 参考
https://app.codegrid.net/entry/display-grid-1
https://codepen.io/dourvaris/pen/QqKPWb