Skip to content

Instantly share code, notes, and snippets.

@pserwylo
Created March 12, 2024 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pserwylo/2e690109da397cc10f30b84afd257a67 to your computer and use it in GitHub Desktop.
Save pserwylo/2e690109da397cc10f30b84afd257a67 to your computer and use it in GitHub Desktop.
Example card dealing using HTML + CSS
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-7">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
/*
* Force the height of the board to take up the whole viewport height "100vh".
* The "relative" is also important, because later on when our cards are specifying
* an absolute position, this is what the position is relative to. e.g. a position of "left: 2em"
* means "search through all parents until we find one with "position: relative", and then move
* 2em from the left of that. If no parent has the position: relative property, then use the screen."
*/
.board {
position: relative;
height: 100vh;
/*
* Hack debugging trick I regularly use to figure out if I'm laying things out correctly.
*/
border: solid 1px red;
}
.card {
width: 4em;
height: 6em;
border: solid 2px black;
background-color: white;
border-radius: 1em;
transition: left 0.3s ease-in-out,
right 0.3s ease-in-out,
top 0.3s ease-in-out,
bottom 0.3s ease-in-out,
transform 0.3s ease-in-out;
}
/*
* Larger cards on a larger screen.
*/
@media screen and (min-width: 768px) {
.card {
width: 6em;
height: 10em;
}
}
/*
* Technically the positions here are a bit off, because it is placing the
* top-left of the card is in the centre of the board. We'd need to replace the
* "50%" with a "calc(50% - whatever-half-the-dimension-of-the-card-is".
* Same goes for all other positions in card-centre, card-top, etc.
*/
.card-undealt {
position: absolute;
top: 50%;
bottom: 50%;
left: 50%;
right: 50%;
}
.card-centre {
position: absolute;
top: calc(50% - 3em);
bottom: calc(50% + 3em);
left: 50%;
right: 50%;
}
.card-top {
position: absolute;
top: 2em;
left: 50%;
right: 50%;
transform: rotate(180deg)
}
.card-bottom {
position: absolute;
bottom: 2em;
left: 50%;
right: 50%;
}
.card-left {
position: absolute;
left: 2em;
bottom: 50%;
right: 50%;
transform: rotate(90deg)
}
.card-right {
position: absolute;
right: 2em;
bottom: 50%;
top: 50%;
transform: rotate(-90deg)
}
/*
* This is a terrible hack because we need all cards to be children of the one
* DOM node so that CSS transitions work as expected when dealing from the centre
* to their respective positions.
*
* We assume three cards in each hand (e.g. .card-bottom) and thus
* we shift the first card (e.g. ".card-bottom") to the left of centre,
* the second card (".card-centre ~ .card-centre") is centred, and the
* third one (e.g. ".card-centre ~ .card-centre ~ .card-centre") is offset to the right.
*
* I've never used this syntax before, I just found it while googling around for this
* very specific problem of dealing cards from the centre of the board to elsewhere..
*/
.card-centre {
left: calc(50% - 5em)
}
.card-centre ~ .card-centre {
left: calc(50%)
}
.card-centre ~ .card-centre ~ .card-centre {
left: calc(50% + 5em)
}
.card-bottom {
left: calc(50% - 2em)
}
.card-bottom ~ .card-bottom {
left: calc(50%)
}
.card-bottom ~ .card-bottom ~ .card-bottom {
left: calc(50% + 2em)
}
.card-top {
left: calc(50% - 2em)
}
.card-top ~ .card-top {
left: calc(50%)
}
.card-top ~ .card-top ~ .card-top {
left: calc(50% + 2em)
}
.card-right {
top: calc(50% - 2em)
}
.card-right ~ .card-right {
top: calc(50%)
}
.card-right ~ .card-right ~ .card-right {
top: calc(50% + 2em)
}
.card-left {
top: calc(50% - 2em)
}
.card-left ~ .card-left {
top: calc(50%)
}
.card-left ~ .card-left ~ .card-left {
top: calc(50% + 2em)
}
</style>
</head>
<body>
<div class="board">
<!--
Without animations/transitions, we can show the cards statically in
their correct position using the HTML below. For a more fancy animated
dealing, use the JS below:
`
<div class="card card-1 card-bottom"></div>
<div class="card card-2 card-bottom"></div>
<div class="card card-3 card-bottom"></div>
<div class="card card-4 card-left"></div>
<div class="card card-5 card-left"></div>
<div class="card card-6 card-left"></div>
<div class="card card-7 card-right"></div>
<div class="card card-8 card-right"></div>
<div class="card card-9 card-right"></div>
<div class="card card-10 card-top"></div>
<div class="card card-11 card-top"></div>
<div class="card card-12 card-top"></div>
<div class="card card-13 card-centre"></div>
<div class="card card-14 card-centre"></div>
<div class="card card-15 card-centre"></div>
-->
</div>
<script>
(function() {
function createCard(index) {
const card = document.createElement('div')
card.classList.add('card', `card-${index + 1}`, 'card-undealt')
document.querySelector('.board').append(card)
return card
}
const cardPositions = [
'bottom',
'bottom',
'bottom',
'left',
'left',
'left',
'top',
'top',
'top',
'right',
'right',
'right',
'centre',
'centre',
'centre',
]
for (let i = 0; i < 15; i ++) {
const card = createCard(i)
setTimeout(() => {
card.classList.remove('card-undealt')
card.classList.add(`card-${cardPositions[i]}`);
}, i * 250)
}
})()
</script>
</body>
</html>
@IT-Jeroen
Copy link

@IT-Jeroen
Copy link

I am not sure if this would still be a good approach when playing with a full deck of cards. As it isn't exactly scalable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment