The Ultimate HTML and CSS Dice Face

CSS3
8 min read

The SolidJS (HTML)

Built in Astro using a SolidJS component. The HTML doesn’t change much except for the num value in the [data-dice-face] attribute should represent the dice face from 1 to 6.

DiceFace.jsx
export default function DiceFace({ num }) {
  return (
    <div class={`dice-face`} data-dice-face={num}>
      <div class='column'>
        <span class='pip'></span>
        <span class='pip'></span>
        <span class='pip'></span>
      </div>
      <div class='column'>
        <span class='pip'></span>
      </div>
      <div class='column'>
        <span class='pip'></span>
        <span class='pip'></span>
        <span class='pip'></span>
      </div>
    </div>
  );
}

Flat HTML

The html code is virtually the same as the code found in the solid js component.

[data-dice-face] should be a value between 1 and 6.

DiceFace.html
<div class="dice-face" data-dice-face="6">
  <div class="column">
    <span class="pip"></span>
    <span class="pip"></span>
    <span class="pip"></span>
  </div>
  <div class="column">
    <span class="pip"></span>
  </div>
  <div class="column">
    <span class="pip"></span>
    <span class="pip"></span>
    <span class="pip"></span>
  </div>
</div>

The SCSS

Has a base size of --square: 64px.

Changing the value will scale the pip height and width as well as the padding.

Dice Face has a padding of 10% and pips are 20% of --square.

diceface.scss
.dice-face {
  --square: 64px;
  --dice-color: blue;
  height: var(--square);
  width: var(--square);
  background-color: var(--dice-color);
  border-radius: 10%;
  object-fit: contain;
  padding: calc(var(--square) * 0.1);
  display: flex;
  justify-content: space-between;

  .column {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  .column:nth-of-type(2) {
    align-self: center;
  }

  &[data-dice-face="1"] {
    .column:nth-of-type(2) {
      justify-content: center;
      align-items: center;
      flex: 1;
    }
    .column:nth-of-type(1),
    .column:nth-of-type(3) {
      display: none;
    }
  }
  &[data-dice-face="2"] {
    .column:nth-of-type(1),
    .column:nth-of-type(3) {
      .pip:nth-of-type(1),
      .pip:nth-of-type(2) {
        display: none;
      }
    }
    .column:nth-of-type(3) {
      justify-content: end;
    }
    .column:nth-of-type(2) {
      display: none;
    }
  }
  &[data-dice-face="3"] {
    .column:nth-of-type(1),
    .column:nth-of-type(3) {
      .pip:nth-of-type(1),
      .pip:nth-of-type(2) {
        display: none;
      }
    }
    .column:nth-of-type(3) {
      justify-content: end;
    }
  }
  &[data-dice-face="4"] {
    .column:nth-of-type(2) {
      display: none;
    }
    .column:nth-of-type(1),
    .column:nth-of-type(3) {
      .pip:first-child {
        display: none;
      }
    }
  }
  &[data-dice-face="5"] {
    .column:nth-of-type(1),
    .column:nth-of-type(3) {
      .pip:first-child {
        display: none;
      }
    }
  }
  &[data-dice-face="6"] {
    .column:nth-of-type(2) {
      display: none;
    }
  }

  .pip {
    --pip-square: calc(var(--square) * 0.2);
    display: block;
    width: var(--pip-square);
    height: var(--pip-square);
    border-radius: 50%;
    margin: 0;
    background-color: #ffffff;
  }
}