Created
March 12, 2024 11:33
-
-
Save pserwylo/2e690109da397cc10f30b84afd257a67 to your computer and use it in GitHub Desktop.
Example card dealing using HTML + CSS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
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
Similar approach and using CSS variables
https://gist.github.com/IT-Jeroen/cfe23195b2652a5ca886f81e780e8e89