I made this a 20 card game, with 10 matching pairs. First, you need to design the cards. Do the front with the faces, then you need to design 1 back.
When you are done you are going to do into WebFlow and throw in a Grid, name the class “game-container”. Make it 5 x 4
Then inside that put another div, name the class “card”
Then within the card div, there are going to be two divs within it. The first div class will be “card-front”, the second is “card-back”
In the card-front div you are going to place an image of all the face cards. You will have to do the random order yourself, as the code doesn’t randomize it. The card-back is where you’ll put the image of the card back.
Do this for all 20 cards.
You will have to back to the card div, and change it to overflow hidden, and change the card height to just show the front of the card. Do this for all different views, from desktop to mobile.
Paste the CSS style inside the head tag of the page. You may have to adjust the numbers.
<style>
/* Container for the game grid */
.game-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); /* Adjust columns based on space */
gap: 30px;
justify-content: center;
padding: 10px; /* Add padding for smaller screens */
}
/* Card styles */
.card {
width: 100%; /* Card width adapts to container */
height: 0;
padding-bottom: 140%; /* Aspect ratio: 1:1.4 for card height */
perspective: 1000px;
cursor: pointer;
position: relative;
}
/* Front and back of the card */
.card-front,
.card-back {
width: 100%;
height: 100%;
position: absolute;
backface-visibility: hidden;
transition: transform 0.5s;
}
.card-front {
transform: rotateY(180deg);
background-color: none; /* Example color */
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em; /* Scales based on card size */
}
.card-back {
background-color: none; /* Example color */
}
.card.flipped .card-front {
transform: rotateY(0);
}
.card.flipped .card-back {
transform: rotateY(180deg);
}
/* Adjustments for smaller screens */
@media (max-width: 768px) {
.game-container {
gap: 5px; /* Reduce gap between cards */
}
.card {
padding-bottom: 150%; /* Adjust aspect ratio for smaller screens */
}
.card-front,
.card-back {
font-size: 1em; /* Smaller font size for smaller cards */
}
}
/* Adjustments for very small screens (e.g., phones) */
@media (max-width: 480px) {
.game-container {
gap: 5px; /* Smaller gap for phones */
}
.card {
padding-bottom: 160%; /* Taller aspect ratio for smaller screens */
}
.card-front,
.card-back {
font-size: 0.8em; /* Even smaller font size for tiny screens */
}
}
</style>
Then paste the javascript before the </body> tag
<script>
const cards = document.querySelectorAll('.card');
const winPopup = document.getElementById('win-popup');
const restartBtn = document.getElementById('restart-btn');
let flippedCards = [];
let matchedPairs = 0;
let flipCount = 0;
let timeElapsed = 0;
let timerInterval;
// Start the timer
function startTimer() {
timerInterval = setInterval(() => {
timeElapsed++;
document.getElementById('timer').textContent = `Time: ${timeElapsed}s`;
}, 1000);
}
// Flip a card
function flipCard(card) {
if (!timerInterval) startTimer(); // Start timer on first flip
if (!card.classList.contains('flipped') && flippedCards.length < 2) {
card.classList.add('flipped');
flippedCards.push(card);
flipCount++;
document.getElementById('flips').textContent = `Flips: ${flipCount}`;
if (flippedCards.length === 2) {
checkForMatch();
}
}
}
// Check for a match
function checkForMatch() {
const [card1, card2] = flippedCards;
if (card1.dataset.card === card2.dataset.card) {
// Match found
matchedPairs++;
flippedCards = [];
if (matchedPairs === 10) {
clearInterval(timerInterval);
showWinPopup();
}
} else {
// No match, flip back
setTimeout(() => {
card1.classList.remove('flipped');
card2.classList.remove('flipped');
flippedCards = [];
}, 1000);
}
}
// Show the Win Popup
function showWinPopup() {
winPopup.style.display = 'block';
}
// Restart the game
restartBtn.addEventListener('click', () => {
resetGame();
});
// Reset the game
function resetGame() {
matchedPairs = 0;
flipCount = 0;
timeElapsed = 0;
clearInterval(timerInterval);
timerInterval = null;
document.getElementById('timer').textContent = `Time: ${timeElapsed}s`;
document.getElementById('flips').textContent = `Flips: ${flipCount}`;
winPopup.style.display = 'none';
// Reset all cards (flip them back but keep their positions and data)
cards.forEach(card => {
card.classList.remove('flipped');
});
}
// Attach event listeners
cards.forEach(card => {
card.addEventListener('click', () => flipCard(card));
});
// Initialize game (no shuffle needed)
document.getElementById('timer').textContent = `Time: ${timeElapsed}s`;
document.getElementById('flips').textContent = `Flips: ${flipCount}`;
</script>
I did add some stats where it times the player and the number of flips.
Throw a text span and give it an ID in the settings “timer”
Throw a text span and give it an ID in the settings “flips”
There is also a popup that lets the player know they won and to restart the game.
Put in a div and name the class “win-popup”
Put your congratulations message in it, then put a button in it. This button is will restart the game, give it and ID in the settings “restart-btn”
Style it however you want.
Make sure it is hidden when you are done. You can do this by going to Layout>Display>None
Hope that helps in creating your own card memory game in WebFlow.
Leave a Reply
You must be logged in to post a comment.