Perfect Square Spiral Pattern in JavaScript

Beginner
⏱️ 10 min read
📚 Updated: Aug 2026
🎯 3 Code Examples
🚀 Live Preview
2D Array + Boundaries

What You’ll Learn

Program 62 generates a perfect square spiral: fill an n×n grid with numbers 1..n² clockwise, layer by layer, using a 2D array and shrinking boundaries. This tutorial covers the spiral fill order, boundary variables, a live preview, worked JavaScript examples, edge cases, and O(n²) complexity.

Shape Rule

Spiral matrix

Numbers flow clockwise around each border ring — 1..10 on the outer ring of a 10×10 grid, then inward to 100 at the center.

2D Array

2D array grid

Array.from({ length: n }, () => Array(n).fill(0)) stores each cell before logging with fixed-width formatting.

Boundaries

low / high

low and high mark the current square ring — increment/decrement after each layer to move inward.

Four Sides

Top, right, bottom, left

Each layer fills top row, right column, bottom row, left column — incrementing counter n each cell.

Live Preview

n = 3..8

Pick grid size and draw the spiral matrix in the browser.

O(n²)

Complexity

Every cell visited once — 10×10 = 100 cells, hence O(n²) time and space.

Introduction

A perfect square spiral (spiral matrix) fills an n×n grid with consecutive integers flowing clockwise around shrinking border rings. With n = 10, you get a 10×10 grid numbered 1 through 100.

In JavaScript create Array.from({ length: n }, () => Array(n).fill(0)), walk each layer with low/high boundaries, fill four sides per ring, then log with String(value).padStart(4, " ") fixed-width formatting.

Why it matters?

Spiral-matrix logic appears in interviews, grid simulations, and image processing — it bridges simple loops to 2D array reasoning.

Key Highlights

2D array

Array.from({ length: n }, () => Array(n).fill(0)) stores the grid.

Boundaries

low/high track each ring.

vs Program 61

Program 61 works on one number; Program 62 fills a 2D grid.

Series Finale

Last number pattern — continue to JavaScript Star Patterns next.

In short: create a 2D array, fill four sides per layer with shrinking boundaries, log with String(value).padStart(4, " ").

📝 Problem & Approach

Given grid size n = 10, fill an n×n array with numbers 1..n² in a clockwise spiral starting from the top-left corner.

JavaScript
// n = 4 (compact sample)
// 1   2   3   4
//12  13  14   5
//11  16  15   6
//10   9   8   7

Inputs & Outputs

ItemTypeDescription
nnumberGrid dimension — 10 in the fixed demo (10×10 = 100 cells).
arr[i,j]2D array2D array storing each cell value.
low, highnumberCurrent layer boundaries — start 0 and n−1, move inward each ring.
Fill counternumberStarts at 1, increments for every cell placed.
Layersnumbern/2 rings for even n — 5 layers when n = 10.
Log formatstringString(value).padStart(4, " ") fixed width keeps columns aligned.

Minimal workflow

Pseudocode
create n×n array
set low=0, high=n-1, val=1
while low <= high:
    fill top row left→right
    fill right column top→bottom
    fill bottom row right→left
    fill left column bottom→top
    low++, high--
print array with fixed width

Approach comparison

ApproachIdeaBest for
low / high ringsOuter loop over layers, four inner loops per sideFixed 10×10 demo (Example 1)
top/bottom/left/rightWhile loop shrinks all four boundariesConfigurable size (Example 2)
Compact tracen = 4 on paper firstQuick dry-runs
Direction arraySimulate walk with dx/dy turnsAlternative interview solution
Wider print width{0, 5} or more when n² > 9999Large grids

⚡ Quick Reference

GoalPattern
AllocateArray.from({ length: n }, () => Array(n).fill(0))
Layer loopfor (i = 0; i < n/2; i++, low++, high--)
Fill orderTop row → right col → bottom row → left col
Print cellString(arr[i][j]).padStart(4, " ")

📋 Fixed 10×10 vs User Input vs Compact 4×4

Same spiral matrix — three ways to set grid size and trace the fill logic.

Fixed 10×10
n = 10

Hard-coded with low/high rings

User input
top/bottom/left/right

Configurable n from console

Compact trace
n = 4

Quick dry-run on paper

Sides
4 per layer

Top, right, bottom, left

Print
padStart(4)

Fixed-width columns

Context

When This Pattern Shows Up

Reach for this pattern when teaching 2D arrays, boundary control, and O(n²) grid algorithms in JavaScript.

  1. Post Program 61 capstone

    Natural finale for the number-pattern series — graduate from 1D loops to 2D spiral filling.

  2. Interview preparation

    Classic spiral-matrix question — explain boundary shrinking before coding.

  3. 2D array drills

    Index reasoning with arr[row, col] and nested loop bounds.

  4. Gateway to Star Patterns

    Continue to C star-pattern programs after mastering this grid exercise.

  5. Large n caution

    Very large grids produce huge console output — cap n for demos.

Key benefit: one program that locks in 2D arrays, boundary control, and O(n²) grid thinking.

🔮 Live Preview

Enter grid size between 3 and 8 and draw the perfect square spiral matrix in the browser.

Try 4, 5, or 7. Max up to 8 in this preview.

Live result
Press "Draw spiral".

Examples Gallery

Three complete JavaScript programs — fixed 10×10 spiral, configurable size with four boundaries, and a compact 4×4 trace. Click View Output to reveal sample console results.

📚 Getting Started

Generate a 10×10 perfect square spiral with low/high boundary rings.

Example 1 — Fixed 10×10 Spiral

Hard-coded grid — fill each layer top, right, bottom, left, then log with width 4.

JavaScript
const n = 10;
const arr = Array.from({ length: n }, () => Array(n).fill(0));
let low = 0;
let high = n - 1;
let val = 1;

for (let i = 0; i < Math.floor(n / 2); i++) {
  for (let j = low; j <= high; j++) {
    arr[i][j] = val;
    val++;
  }
  for (let j = low + 1; j <= high; j++) {
    arr[j][high] = val;
    val++;
  }
  for (let j = high - 1; j >= low; j--) {
    arr[high][j] = val;
    val++;
  }
  for (let j = high - 1; j > low; j--) {
    arr[j][low] = val;
    val++;
  }
  low++;
  high--;
}

console.log("Perfect Square Spiral\\n");
for (const row of arr) {
  let line = "";
  for (const cell of row) {
    line += String(cell).padStart(4, " ");
  }
  console.log(line);
}
Try it Yourself

How It Works

Five layers fill the 10×10 grid — outer loop runs i = 0..4, each iteration walks four sides and moves boundaries inward.

📈 Practical Variant

Read grid size n from the user and fill with top/bottom/left/right boundaries.

Example 2 — User Input Size

Configurable n×n spiral using a while loop and four boundary variables.

JavaScript
const nInput = prompt("Enter size n:");
const n = parseInt(nInput, 10);

if (!Number.isFinite(n) || n <= 0) {
  console.log("Please enter a positive integer.");
} else {
  const a = Array.from({ length: n }, () => Array(n).fill(0));
  let top = 0;
  let bottom = n - 1;
  let left = 0;
  let right = n - 1;
  let val = 1;

  while (top <= bottom && left <= right) {
    for (let j = left; j <= right; j++) {
      a[top][j] = val;
      val++;
    }
    top++;

    for (let i = top; i <= bottom; i++) {
      a[i][right] = val;
      val++;
    }
    right--;

    if (top <= bottom) {
      for (let j = right; j >= left; j--) {
        a[bottom][j] = val;
        val++;
      }
      bottom--;
    }

    if (left <= right) {
      for (let i = bottom; i >= top; i--) {
        a[i][left] = val;
        val++;
      }
      left++;
    }
  }

  for (const row of a) {
    let line = "";
    for (const cell of row) {
      line += String(cell).padStart(4, " ");
    }
    console.log(line);
  }
}
Try it Yourself

How It Works

The while loop shrinks all four boundaries after each side fill — works for any positive n, odd or even.

⚡ Compact Trace

Use n = 4 for a quick paper trace before larger grids.

Example 3 — Compact 4×4 Trace

Same boundary approach with a small grid — easy to dry-run on paper.

JavaScript
const n = 4;
const a = Array.from({ length: n }, () => Array(n).fill(0));
let top = 0;
let bottom = n - 1;
let left = 0;
let right = n - 1;
let val = 1;

while (top <= bottom && left <= right) {
  for (let j = left; j <= right; j++) {
    a[top][j] = val;
    val++;
  }
  top++;

  for (let i = top; i <= bottom; i++) {
    a[i][right] = val;
    val++;
  }
  right--;

  if (top <= bottom) {
    for (let j = right; j >= left; j--) {
      a[bottom][j] = val;
      val++;
    }
    bottom--;
  }

  if (left <= right) {
    for (let i = bottom; i >= top; i--) {
      a[i][left] = val;
      val++;
    }
    left++;
  }
}

for (const row of a) {
  let line = "";
  for (const cell of row) {
    line += String(cell).padStart(4, " ");
  }
  console.log(line);
}
Try it Yourself

How It Works

Two layers fill the 4×4 grid — trace values 1–16 clockwise on paper before scaling to 10×10.

🧠 How the Algorithm Fills the Spiral

1

Create 2D array

Array.from({ length: n }, () => Array(n).fill(0)) holds all spiral values before logging.

Setup
2

Set boundaries

low = 0, high = n - 1 (or top/bottom/left/right) mark the current ring.

Boundaries
3

Fill four sides

Top row, right column, bottom row, left column — incrementing counter each cell.

Spiral
4

Log with fixed width

String(arr[i][j]).padStart(4, " ") keeps columns aligned.

Output
=

Perfect square spiral complete

n² cells filled and logged — O(n²) time and space.

🔎 Worked Walkthrough — first layer of n = 4

Trace the first (outer) ring of a 4×4 spiral — values 1 through 12 on the border, then inner 2×2 fills 13–16.

SideCells filledValues placed
Top row(0,0)..(0,3)1, 2, 3, 4
Right column(1,3)..(3,3)5, 6, 7
Bottom row(3,2)..(3,0)8, 9, 10
Left column(2,0)..(1,0)11, 12
Inner 2×2Second layer13, 14, 15, 16

For n = 10, repeat this four-side pattern for 5 concentric rings until the center cell holds 100.

Use Cases

Where spiral-matrix filling shows up beyond the homework prompt.

1. Teaching 2D Arrays

Array.from({ length: n }, () => Array(n).fill(0)) with row/column indexing — a visual grid exercise for beginners.

Example: trace which cells get values 1–4 on the outer ring of a 4×4 grid.

2. Interview Prep

Classic spiral-matrix question — explain boundary shrinking before coding.

Example: walk through top → right → bottom → left for one layer.

3. Series Capstone

Final number-pattern program — graduates from 1D loops to 2D boundary control.

Example: compare Program 61’s while loop with nested spiral loops here.

4. Gateway to Star Patterns

After mastering grids, move to C star-pattern programs for shape-based output.

Example: continue to JavaScript Star Patterns next.

5. O(n²) Intuition

Every cell visited once — concrete quadratic complexity for grid algorithms.

Example: 10×10 = 100 cells filled and printed.

6. Grid Simulations

Spiral traversal appears in image processing, maze generation, and game maps.

Example: adapt the fill order to visit cells in spiral order without storing all values.

Pro Tip: dry-run a 4×4 grid on paper before attempting 10×10 — the four-side pattern repeats per layer.

Advantages

Why spiral-matrix exercises belong in every beginner JavaScript course.

  1. 1. Visual 2D Reasoning

    Students see numbers flow around the grid — wrong boundary logic shows up immediately.

  2. 2. Nested Loop Practice

    Four inner loops per layer reinforce index bounds and loop direction (forward/backward).

  3. 3. Interview-Ready Pattern

    Spiral matrix is a standard coding question — this tutorial maps directly to it.

  4. 4. Scales to Any n

    Same boundary approach works for odd and even sizes — only print width may need adjustment.

Pro Tip: trace the first layer of n = 4 on paper — values 1–12 on the border before the inner 2×2 fills 13–16.

Usage Tips

Small habits that keep spiral-matrix code clean.

  1. 1. Fill Four Sides in Order

    Top → right → bottom → left — skipping or reordering breaks the spiral.

  2. 2. Skip Corner Overlap

    Start right column at low + 1, bottom row at high - 1 — corners are already filled.

  3. 3. Use Fixed Log Width

    String(value).padStart(4, " ") keeps columns aligned for n up to 10×10.

  4. 4. Guard Inner Sides

    When using top/bottom/left/right, check top <= bottom before bottom and left fills.

  5. 5. Start with n = 4

    Dry-run a 4×4 grid on paper before coding the 10×10 demo.

Pro Tip: if numbers jump or repeat, check whether a side loop includes an already-filled corner cell.

Common Pitfalls

Mistakes that commonly break spiral-matrix programs.

  1. 1. Double-Filling Corners

    Starting every side at the same corner overwrites cells — spiral breaks at turns.

    → Skip the first cell on right, bottom, and left sides after the top row.

  2. 2. Wrong Layer Count

    Running too many or too few outer iterations leaves cells empty or overwritten.

    → Use n/2 layers for even n — 5 rings when n = 10.

  3. 3. Missing Boundary Guards

    On odd n or the last layer, bottom/left fills may run when boundaries crossed.

    → Wrap bottom and left fills with if (top <= bottom) checks.

  4. 4. Misaligned Output

    Printing without fixed width makes large numbers shift columns.

    → Use String(value).padStart(4, " ") or wider when n² exceeds 9999.

  5. 5. Row/Column Confusion

    Swapping arr[i,j] indices fills transposed or scrambled output.

    → Top row uses fixed row i, varying column j.

Edge Cases

Check these inputs before calling the solution done.

n = 1

Single cell

Grid holds only value 1 — one layer, one print.

n = 2

Smallest ring

Four cells in one layer — good minimal test case.

n = 3

Odd size

Center cell 9 filled in the innermost layer — verify boundary guards.

n = 0

Invalid size

Reject with a message — do not create a grid when n <= 0.

Bad input

Non-numeric input

Bare parseInt(prompt()) returns NaN — validate with Number.isFinite.

Large n

Huge console output

Cap n for demos — O(n²) cells means O(n²) print lines.

🎯 Practice Problems

Try these variations to lock in the spiral pattern.

1. Compare with Program 61

  • Program 61 uses 1D while loop
  • Program 62 fills a 2D grid with boundaries

2. Counter-clockwise spiral

  • Reverse fill order: left, bottom, right, top
  • Same boundaries, opposite direction

3. Continue to Star Patterns

4. Paper trace

  • Dry-run n = 4 before coding 10×10
  • Fill the walkthrough table by hand

Notes

  • Cell count. An n×n grid holds n² values — 100 cells when n = 10.
  • Each layer shrinks boundaries by 1 on all sides — low++ and high-- after four sides.
  • The while-loop variant (top/bottom/left/right) generalizes to any positive n without hard-coding layer count.
  • This is the final program in the JavaScript number-pattern series — star patterns come next.

Quick Takeaway: create a 2D array, fill four sides per layer, tighten boundaries, log with String(value).padStart(4, " ").

⏱️ Time and Space Complexity

ProgramTimeExtra space
Fixed 10×10 (Example 1)O(n²) — n = 10, 100 cellsO(n²) for the array
User input (Example 2)O(n²)O(n²)
Compact 4×4 (Example 3)O(n²) — n = 4, 16 cellsO(n²)
Wrap Up

🎉 Conclusion

The perfect square spiral is a capstone 2D-array exercise: boundary control, four-side fills, and O(n²) grid thinking. Master the fixed 10×10 version, then try user input with configurable n and the compact 4×4 trace.

Practice the three examples above, then continue to JavaScript Star Patterns — the next chapter after number patterns.

Fill top → right → bottom → left per layer, tighten boundaries, log with fixed width — validate n when reading from prompt().

💡 Best Practices

✅ Do

  • Explain four-side fill order before coding
  • Skip corner overlap on right, bottom, left sides
  • Use String(value).padStart(4, " ") for aligned columns
  • Guard bottom/left fills with boundary checks
  • Dry-run n = 4 on paper first
  • State O(n²) time when asked about complexity

❌ Don’t

  • Double-fill corner cells on adjacent sides
  • Swap row and column indices in arr[i,j]
  • Run too many outer layer iterations
  • Create the grid only when n > 0
  • Skip the n = 4 dry-run before 10×10

Key Takeaways

Knowledge Unlocked

Five things to remember about this spiral pattern

Print the perfect square spiral the beginner-friendly way.

5
Core concepts
[,] 02

2D List

2D array stores grid

Structure
4 03

Sides

Top, right, bottom, left

Order
04

Boundaries

low/high shrink inward

Control
O 05

Complexity

O(n²) time & space

Analysis

❓ Frequently Asked Questions

It prints a perfect square spiral (spiral matrix) of size 10×10 filled with numbers from 1 to 100 in a clockwise spiral.
low and high mark the current layer of the spiral. After finishing one layer (top, right, bottom, left), low increases and high decreases to move inward.
Using String(cell).padStart(4, ' ') prints each number in a fixed width of 4 characters, keeping columns aligned.
Program 61 uses a while loop on one number. Program 62 fills an n×n grid with a 2D array and boundary-based spiral loops.
Yes. This is a classic spiral matrix generation exercise: fill the grid while shrinking boundaries.
Yes. The boundary-based approach works for any positive size n, both odd and even.
A 10×10 grid has 5 concentric rings — each ring reduces both width and height by 2.
A 1×1 grid holds only the value 1 — one cell, one layer.
O(n²) for an n×n grid because each cell is filled and logged once.
Use parseInt with Number.isFinite after prompt() and validate n > 0 — see Example 2.

Did you Know? 🔊

A perfect square spiral fills an n×n grid with numbers 1..n² by walking each border layer clockwise and tightening low/high boundaries — runtime is O(n²).

Continue to JavaScript Star Patterns

Number patterns complete — move on to star-shaped output programs.

Star Patterns hub →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

12 people found this page helpful