UI layout
rectangle packing
programming
algorithm design
user interface

Programmatically arrange rectangular UI objects in an abstract way, without gaps

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

If you want to place rectangular UI elements without gaps, you are really solving a packing problem. That sounds like a styling question, but it is mostly an algorithm question: which rectangles fit where, and under what constraints.

First Clarify What "Without Gaps" Means

There are two very different versions of this problem.

  1. You want a visually dense layout with no obvious holes.
  2. You want an exact tiling of a bounded area with zero empty cells.

The first version can usually be handled with heuristics such as grids, masonry layouts, or skyline packing. The second version is much harder and, in general, becomes a combinatorial search problem.

For UI work, the best approach is usually to map every widget onto a logical grid. Then each rectangle occupies a whole number of rows and columns. That keeps the problem abstract and avoids pixel-level chaos.

Grid-Based Exact Placement

Suppose every item has integer width and height in grid cells. We can search for the first position where a rectangle fits, place it, and mark those cells as occupied.

Here is a small runnable Python example that packs rectangles into a fixed-width board:

python
1from typing import List, Tuple
2
3Rect = Tuple[str, int, int]
4
5
6def can_place(board, x, y, w, h):
7    height = len(board)
8    width = len(board[0])
9    if x + w > width or y + h > height:
10        return False
11    for row in range(y, y + h):
12        for col in range(x, x + w):
13            if board[row][col] != ".":
14                return False
15    return True
16
17
18def place(board, x, y, w, h, marker):
19    for row in range(y, y + h):
20        for col in range(x, x + w):
21            board[row][col] = marker
22
23
24def pack(rects: List[Rect], width: int, height: int):
25    board = [["." for _ in range(width)] for _ in range(height)]
26    positions = {}
27
28    for name, w, h in rects:
29        placed = False
30        for y in range(height):
31            for x in range(width):
32                if can_place(board, x, y, w, h):
33                    place(board, x, y, w, h, name)
34                    positions[name] = (x, y)
35                    placed = True
36                    break
37            if placed:
38                break
39        if not placed:
40            return None, None
41
42    return board, positions
43
44
45rectangles = [("A", 2, 2), ("B", 1, 2), ("C", 3, 1), ("D", 2, 1)]
46board, positions = pack(rectangles, width=4, height=4)
47
48for row in board:
49    print(" ".join(row))
50
51print(positions)

This is a simple first-fit strategy. It is easy to understand and often good enough for dashboards, tile editors, or internal tools.

Why Perfect Packing Is Hard

The simple algorithm above does not guarantee a perfect fill even when one exists. Rectangle packing is hard because early placements can block better later placements. That is why exact solvers often use backtracking, branch-and-bound, or integer programming.

For a UI, that complexity is rarely worth it unless:

  • the layout is generated offline
  • the number of rectangles is small
  • exact gap elimination is a hard requirement

If you are rendering interactive interfaces, a deterministic heuristic is usually the better tradeoff.

Practical UI Strategies

For responsive applications, the most useful abstractions are:

  • fixed-column CSS grid with row and column spans
  • masonry or skyline placement for irregular card heights
  • binary tree or shelf packing for canvas-based editors

If the rectangles represent widgets with flexible dimensions, consider relaxing the requirement. Allow the algorithm to resize or stretch items within a safe range. That turns an exact packing problem into a layout optimization problem, which is far easier to solve well.

A More Realistic Rule for Product UIs

In product design, "without gaps" usually means "without ugly accidental holes." You can achieve that by:

  • snapping everything to a shared grid
  • sorting larger rectangles first
  • placing smaller items into remaining holes
  • letting the layout recompute on resize

That is why many drag-and-drop dashboard builders use a grid engine rather than an exact mathematical tiling solver.

Common Pitfalls

The first mistake is assuming a gap-free arrangement always exists. If the total area or dimensions do not line up, no algorithm can invent a perfect tiling.

Another mistake is working directly in pixels. Abstract grid units are much easier to reason about, validate, and recompute.

A third issue is using a greedy algorithm and expecting optimal results. Greedy placement is fast, but it can leave holes even when a better arrangement exists.

Summary

  • Gap-free rectangle layout is a packing problem, not just a styling problem.
  • A grid-based representation is usually the cleanest abstraction for UI code.
  • Simple first-fit algorithms are easy to implement and often good enough.
  • Exact no-gap tiling is much harder and may require search or optimization.
  • For most applications, aim for dense, predictable layouts rather than mathematically perfect packing.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.