What Is Svelte?
Svelte is a radical new approach to building user interfaces with less code. No more complex state management libraries โ Svelte brings reactivity to JavaScript itself.
In this tutorial, you'll need basic understanding of HTML, CSS and JavaScript to build your own Tic Tac Toe Game with Svelte.
Getting Started
Go ahead and initialise our new project with the following command:
# Creating a new project
npx degit sveltejs/template
# Install the dependencies...
npm install
...then start Rollup.
# Npm Command
npm run dev
Navigate to localhost:8080 and you should see your app running. Edit a component file in src, save it, and reload the page to see your changes.
Basic Structure
Components in Svelte are written use .svelte
files which contain HTML, CSS and JavaScript. Now let's create our Board.svelte
file and modify our App.svelte
file with the following structure.
<script>
<!-- JavaScript Logic -->
</script>
<style>
<!-- CSS Styles -->
</style>
<div>
<!-- HTML Markup -->
</div>
Before we get started let's replace our main.js
with the following:
import App from './App.svelte'
const app = new App({
target: document.body,
})
export default app
Our App Component
Now we will edit the App.svelte
with the following to complete our App Component.
<script>
import Board from "./Board.svelte";
</script>
<div class="app">
<div class ="container">
<Board />
</div>
</div>
Here we've imported Board.svelte
and initalised our Board Component in App.svelte
using HTML Markup.
Our Board Component
We'll open up Board.svelte
and implement the JavaScript Logic for our Board Component.
<script>
let userTurn = "X";
let squares = new Array(9).fill(null);
let winner = null;
function restartGame() {
userTurn = "X";
squares = new Array(9).fill(null);
winner = null;
}
function handleClick(i) {
if (!squares[i] && !winner) {
squares[i] = userTurn;
switchTurn();
winner = calculateWinner(squares);
if (winner) userTurn = null;
}
}
function switchTurn() {
if (userTurn === "X") userTurn = "O";
else userTurn = "X";
}
function calculateWinner(squares) {
const winningCombinations = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for (let i = 0; i < winningCombinations.length; i++) {
const [a, b, c] = winningCombinations[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c])
return `Winner: ${squares[a].toUpperCase()}`;
}
const isDraw = squares.every(square => square !== null);
return isDraw ? "It's a draw" : null;
}
</script>
Now we can implement the HTML Markup for our Board.svelte
component.
<div>
{#if winner}
<h1>{winner}</h1>
<button class="restart" on:click={restartGame}>Restart Game</button>
{:else}
<h1>Next Player : {userTurn}</h1>
{/if}
</div>
<div class={userTurn != null ? userTurn + ' board' : 'board'}>
{#each squares as square, i}
<div
class={square != null ? square + ' cell' : 'cell'}
on:click={() => handleClick(i)} />
{/each}
</div>
Next step is to add the following styles to complete our Board.Svelte
file.
<style>
:root {
--cell-size: 100px;
--mark-size: calc(var(--cell-size) * 0.5);
}
.board {
display: grid;
justify-content: center;
justify-items: center;
align-content: center;
align-items: center;
grid-template-columns: repeat(3, auto);
}
.cell {
width: var(--cell-size);
height: var(--cell-size);
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
position: relative;
cursor: pointer;
}
.cell:first-child,
.cell:nth-child(2),
.cell:nth-child(3) {
border-top: none;
}
.cell:nth-child(3n + 1) {
border-left: none;
}
.cell:nth-child(3n + 3) {
border-right: none;
}
.cell:last-child,
.cell:nth-child(8),
.cell:nth-child(7) {
border-bottom: none;
}
.cell.X,
.cell.O {
cursor: not-allowed;
}
.cell.X::before,
.cell.X::after,
.cell.O::before {
background-color: black;
}
.board.X .cell:not(.X):not(.O):hover::before,
.board.X .cell:not(.X):not(.O):hover::after,
.board.O .cell:not(.X):not(.O):hover::before {
background-color: lightgrey;
}
.cell.X::before,
.cell.X::after,
.board.X .cell:not(.X):not(.O):hover::before,
.board.X .cell:not(.X):not(.O):hover::after {
content: "";
position: absolute;
width: calc(var(--mark-size) * 0.15);
height: var(--mark-size);
}
.cell.X::before,
.board.X .cell:not(.X):not(.O):hover::before {
transform: rotate(45deg);
}
.cell.X::after,
.board.X .cell:not(.X):not(.O):hover::after {
transform: rotate(-45deg);
}
.cell.O::before,
.cell.O::after,
.board.O .cell:not(.X):not(.O):hover::before,
.board.O .cell:not(.X):not(.O):hover::after {
content: "";
position: absolute;
border-radius: 50%;
}
.cell.O::before,
.board.O .cell:not(.X):not(.O):hover::before {
width: var(--mark-size);
height: var(--mark-size);
}
.cell.O::after,
.board.O .cell:not(.X):not(.O):hover::after {
width: calc(var(--mark-size) * 0.7);
height: calc(var(--mark-size) * 0.7);
background-color: white;
}
h1 {
text-align: center;
text-decoration: underline;
text-decoration-color: red;
margin: 2rem;
padding: 1rem;
}
.restart {
font-weight: bold;
position: absolute;
top: 50%;
padding: 20px;
margin: 200px 500px;
}
</style>
Note ๐ก - You should now have a complete Tic Tac Toe game using Svelte.
Cool! Now if you made it this far, then I am linking the code to my Sandbox for you to fork or clone and then the job's done.
License: ๐
This project is under the MIT License (MIT). See the LICENSE for more information.
Contributions
Contributions are always welcome...
- Fork the repository
- Improve current program by
- improving functionality
- adding a new feature
- bug fixes
- Push your work and Create a Pull Request
Top comments (2)
Cool I found this interesting because I have not used Svelte yet.
I can't wait for you to get started with svelte. ๐