Pixel Art Maker Using Typescript
Last Updated :
23 Jul, 2025
A Pixel Art Maker lets users create art by colouring squares on a grid, like retro pixel graphics. This project uses TypeScript and DOM manipulation for a fun and creative experience.
What We’re Going to Create
We are going to create a pixel Art maker with the following components.
- A grid with size * size number of blocks
- A reset button to reset the grid
- An input box for the grid size
- A color palette to select various colors
Project Preview
Pixel Art Maker using TypescriptPixel Art Maker - HTML and CSS code
This code creates a simple interactive grid where users can change the grid size, pick a color, and reset the grid. The layout is styled using CSS.
HTML
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: auto;
}
body {
background: #fff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.opts {
padding: 20px;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.btn,
.clr,
.sz {
height: 30px;
padding: 0 20px;
}
.clr {
width: 100px;
margin: 0 40px;
}
.grid {
--sz: 4;
background: #000;
width: 100vh;
height: 85vh;
display: grid;
grid-template-columns: repeat(var(--sz), 1fr);
grid-template-rows: repeat(var(--sz), 1fr);
gap: 3px;
padding: 3px;
}
.cell {
background: #393939;
border-radius: 2px;
}
</style>
</head>
<body>
<div class="opts">
<button class="btn">Reset</button>
<input type="color" value="#ffa500" class="clr">
<input type="number" value="20" class="sz">
</div>
<div class="grid"></div>
<script defer src="main.js"></script>
</body>
</html>
In this Example
- The .grid container uses CSS grid with a variable --sz, dynamically adjusting the number of rows and columns based on user input.
- Users can pick a color (.clr), specify grid size (.sz), and draw on cells by clicking or hovering while holding the mouse button.
- Clicking the "Reset" button (.btn) regenerates the grid, clearing all colored cells and applying new size settings.
Pixel Art Maker - Typescript logic
This code creates a dynamic pixel art grid, enabling users to draw by hovering or clicking, with adjustable grid size and color options. It includes event handling for user interactions and grid reset functionality.
JavaScript
const gCont = document.querySelector<HTMLDivElement>(".grid");
const gSize = document.querySelector<HTMLInputElement>('.sz');
const gColor = document.querySelector<HTMLInputElement>('.clr');
const gReset = document.querySelector<HTMLButtonElement>('.btn');
if (!gCont || !gSize || !gColor || !gReset) {
throw new Error("Missing required DOM elements");
}
let gridSize: number = parseInt(gSize.value);
let isDrawing: boolean = false;
function createGrid(): void {
gCont.style.setProperty("--sz", gridSize.toString());
gCont.innerHTML = "";
for (let i = 0; i < gridSize * gridSize; i++) {
const cell = document.createElement("div");
cell.classList.add("cell");
cell.addEventListener('mouseenter', () => paintCell(cell));
cell.addEventListener('mousedown', () => clickCell(cell));
gCont.appendChild(cell);
}
}
function paintCell(cell: HTMLDivElement): void {
if (!isDrawing) return;
cell.style.backgroundColor = gColor.value;
}
function clickCell(cell: HTMLDivElement): void {
cell.style.backgroundColor = gColor.value;
}
window.addEventListener('mousedown', () => {
isDrawing = true;
});
window.addEventListener('mouseup', () => {
isDrawing = false;
});
function resetGrid(): void {
createGrid();
}
gReset.addEventListener('click', resetGrid);
gSize.addEventListener('change', () => {
gridSize = parseInt(gSize.value);
resetGrid();
});
createGrid();
In this example
- Selects key elements (.grid, .sz, .clr, .btn) and ensures they exist. If any are missing, it throws an error to prevent runtime issues.
- The createGrid() function sets the grid size, clears existing cells, and generates a new grid based on the user-defined size.
- Event Listeners for Drawing
- Each grid cell listens for mouseenter (hover) and mousedown (click) events, allowing users to color the cells dynamically.
- The isDrawing boolean tracks when the mouse is pressed (mousedown) and released (mouseup), ensuring smooth and controlled drawing.
- Clicking the reset button regenerates the grid, and changing the size input updates the grid dynamically with the new size.
Convert to JavaScript File
Now You need to convert the TypeScript file into JavaScript to render by browser. Use one of the following command.
npx tsc codes.ts
tsc codes.ts
- The command tsc codes.ts compiles the codes.ts TypeScript file into a codes.js JavaScript file.
- It places the output in the same directory as the input file by default.
Complete code
HTML
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: auto;
}
body {
background: #fff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.opts {
padding: 20px;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.btn,
.clr,
.sz {
height: 30px;
padding: 0 20px;
}
.clr {
width: 100px;
margin: 0 40px;
}
.grid {
--sz: 4;
background: #000;
width: 100vh;
height: 85vh;
display: grid;
grid-template-columns: repeat(var(--sz), 1fr);
grid-template-rows: repeat(var(--sz), 1fr);
gap: 3px;
padding: 3px;
}
.cell {
background: #393939;
border-radius: 2px;
}
</style>
</head>
<body>
<div class="opts">
<button class="btn">Reset</button>
<input type="color" value="#ffa500" class="clr">
<input type="number" value="20" class="sz">
</div>
<div class="grid"></div>
<script defer>
const gCont = document.querySelector(".grid");
const gSize = document.querySelector('.sz');
const gColor = document.querySelector('.clr');
const gReset = document.querySelector('.btn');
if (!gCont || !gSize || !gColor || !gReset) {
throw new Error("Missing required DOM elements");
}
let gridSize = parseInt(gSize.value);
let isDrawing = false;
function createGrid() {
gCont.style.setProperty("--sz", gridSize.toString());
gCont.innerHTML = "";
for (let i = 0; i < gridSize * gridSize; i++) {
const cell = document.createElement("div");
cell.classList.add("cell");
cell.addEventListener('mouseenter', () => paintCell(cell));
cell.addEventListener('mousedown', () => clickCell(cell));
gCont.appendChild(cell);
}
}
function paintCell(cell) {
if (!isDrawing) return;
cell.style.backgroundColor = gColor.value;
}
function clickCell(cell) {
cell.style.backgroundColor = gColor.value;
}
window.addEventListener('mousedown', () => {
isDrawing = true;
});
window.addEventListener('mouseup', () => {
isDrawing = false;
});
function resetGrid() {
createGrid();
}
gReset.addEventListener('click', resetGrid);
gSize.addEventListener('change', () => {
gridSize = parseInt(gSize.value);
resetGrid();
});
createGrid();
</script>
</body>
</html>
Similar Reads
Calculator App Using TypeScript A calculator app is a perfect project for practising TypeScript along with HTML and CSS. This app will have basic functionalities like addition, subtraction, multiplication, and division. It provides a clean and interactive interface for the user while using TypeScript to handle logic safely and eff
6 min read
TypeScript Using Class Types in Generics TypeScript Using class types in generics allows you to create more flexible and reusable code by specifying that a generic parameter should be a class constructor. This is particularly useful when you want to work with instances of classes but want to keep the code type safe. You can define a generi
3 min read
TypeScript Structural Typing TypeScript type system is based on structural typing, therefore, TypeScriptâs type compatibility is determined by the structure (i.e., the properties and methods) rather than explicit declarations or names. In this article, we will learn in detail about TypeScript Structural Typing.What is Structura
5 min read
TypeScript Aliases Type In TypeScript, a type alias allows you to assign a custom name to an existing type, enhancing code readability and reusability.Provide a shorthand for complex types like unions or objects.Allow naming of primitive types, object types, or functions for clarity.Simplify repetitive type definitions and
3 min read
Data types in TypeScript In TypeScript, a data type defines the kind of values a variable can hold, ensuring type safety and enhancing code clarity.Primitive Types: Basic types like number, string, boolean, null, undefined, and symbol.Object Types: Complex structures including arrays, classes, interfaces, and functions.Prim
3 min read
What are Generics in TypeScript ? In this article, we will try to understand all the facts as well as the details associated with Generics in TypeScript along with some coding examples. Generics in TypeScript: Whenever any program or code is written or executed, one major thing one always takes care of which is nothing but making re
3 min read