Raster vs vector
Every image file you send to a browser falls into one of two fundamental categories: raster or vector. The distinction is not cosmetic — it determines how the image scales, how large the file is, and which formats are appropriate for which use cases.
Raster: a grid of pixels
A raster image (also called a bitmap) stores color information as a rectangular grid of individual dots called pixels. The file records the color of each dot in reading order — left to right, top to bottom. When you enlarge a raster image beyond its native resolution, the browser must invent pixel data that was never there. The result is visible blurring or blocky pixelation, because neighboring pixels are either blended or simply repeated.
Photographs are inherently raster. The sensor in a camera captures a fixed grid of light-intensity readings; there is no mathematical description of the scene — just a record of what each tiny patch of the sensor measured. JPEG, PNG, WebP, and AVIF are all raster formats.
Vector: shapes described by math
A vector image stores a set of geometric instructions: "draw a circle centered at (50, 50) with radius 20, filled with this color." There is no pixel grid. When the browser renders the image, it re-executes those instructions at whatever size is needed, producing crisp edges at any scale — from a 16×16 favicon to a billboard. SVG (Scalable Vector Graphics) is the vector format of the web.
Vector is ideal for logos, icons, diagrams, and illustrations with clean geometric shapes. It is not suited for photographs, because describing a complex scene with millions of gradient shapes would be far larger and slower than a raster file. To learn how to draw and author SVG directly, see the SVG section.
Demo: the same star — raster vs vector
Below, the same star shape is rendered two ways. The left image is a 32×32 raster PNG forced to display at 160×160 pixels — roughly 5× its native size. The right is an inline SVG path that describes the star geometrically; it renders at exactly 160×160 without ever storing a pixel grid.
The raster version looks acceptable at its native 32×32 size, but loses quality the moment you scale it up. The vector version is defined once and looks sharp everywhere. This is the practical reason logos, icons, and UI graphics are almost always SVG today.
Pixels & bit depth
A pixel (short for picture element) is the smallest addressable unit in a raster image — one dot of color. The file format determines how many bits it uses to record that color, which is called the image's bit depth.
How bit depth controls color range
More bits per pixel means more distinct color values can be stored:
- 1-bit — only 2 values (black or white). Used for simple line-art bitmaps.
- 8-bit grayscale — 256 shades of gray. Sufficient for black-and-white photography.
- 24-bit color (8 bits × 3 channels) — approximately 16.7 million colors (256 reds × 256 greens × 256 blues). This is the standard "full color" used by JPEG and most PNG files.
- 32-bit color (8 bits × 4 channels) — adds an 8-bit alpha channel for transparency. PNG and WebP support this. Each pixel can be any of 16.7 million colors at any of 256 opacity levels.
The practical takeaway: every extra channel adds one more byte per pixel, which multiplies across every pixel in the image. A 1000×1000 image in 24-bit color is ~3 MB uncompressed; the same image in 32-bit RGBA is ~4 MB. Compression (gzip, DEFLATE, AV1-based) reduces the on-disk size substantially, but the decoded size in memory always reflects the full bit depth.
Why bit depth matters in practice
When a browser decodes an image, it expands it back to its full uncompressed size in GPU memory. A page that loads many large high-bit-depth images can exhaust device memory even if the compressed file sizes look small. This is especially important on mobile devices with limited RAM.
Pixel math & HiDPI
Understanding the uncompressed size of an image — before any compression is applied — helps you reason about memory usage and understand why serving multiple image sizes matters.
The uncompressed size formula
For a 32-bit RGBA image (4 bytes per pixel):
uncompressed bytes = width × height × bytes per pixel
A 100×100 CSS image at standard density: 100 × 100 × 4 = 40,000 bytes (~39 KB). At 800×533 (the landscape photo in this tutorial): 800 × 533 × 4 = 1,705,600 bytes (~1.6 MB) decoded in memory, even though the JPEG file on disk is far smaller.
HiDPI and Retina displays
Modern displays — Apple's Retina screens, most flagship Android phones, and many laptop panels — pack extra physical pixels into the same physical area. The device pixel ratio (DPR) describes the relationship: a 2× device has 2 device pixels for every 1 CSS pixel in each direction, meaning a CSS image that is 100×100 pixels actually needs a source file of 200×200 device pixels to look sharp. A 3× device needs 300×300 device pixels for the same CSS size.
This is why a single low-resolution image can look blurry on a phone even if it looks
fine on a standard monitor: the browser must stretch the image's pixels to fill the
extra device pixels, and the result is softness. Serving the right resolution for
each screen is handled by the srcset and sizes attributes,
covered in Tutorial 06: Responsive Images.
Uncompressed byte cost by device pixel ratio
The table below uses a hypothetical 100×100 CSS image at 4 bytes per pixel (32-bit RGBA) to show how DPR multiplies memory consumption:
| Device pixel ratio | CSS size (px) | Required device pixels | Total pixels | Uncompressed bytes (@ 4 B/px) |
|---|---|---|---|---|
| 1× (standard) | 100 × 100 | 100 × 100 | 10,000 | 40,000 B (~39 KB) |
| 2× (HiDPI / Retina) | 100 × 100 | 200 × 200 | 40,000 | 160,000 B (~156 KB) |
| 3× (high-density mobile) | 100 × 100 | 300 × 300 | 90,000 | 360,000 B (~352 KB) |
Notice that going from 1× to 2× quadruples the pixel count and memory cost; going to
3× multiplies it by nine. For a 800×533 landscape photograph displayed at its full
CSS width on a 3× device, the decoded memory footprint is roughly 14 MB — for a single
image. This is the core reason we serve multiple image resolutions and let the browser
choose the appropriate one for the current display.
See Tutorial 06: Responsive Images for how to
implement this with srcset.
Anti-aliasing
Pixels are square. A curved line or diagonal edge drawn across a pixel grid will only ever land partially within each square pixel — but the pixel itself can only show one color, not a blend. When a renderer simply rounds each pixel to "fill" or "empty," curved and diagonal edges appear jagged. This artifact is called aliasing, and the stepped appearance is sometimes called the "staircase effect."
How anti-aliasing smooths edges
Anti-aliasing (AA) fixes this by partially filling edge pixels. The renderer calculates how much of each edge pixel is covered by the shape and sets that pixel's color to a proportional blend between the shape color and the background. The result looks smooth to the eye, because neighboring pixels at the boundary gradually transition rather than abruptly switching.
The tradeoff is a slight softness: anti-aliased edges look smooth but can appear slightly blurred at close inspection. This is generally preferable to sharp aliasing. At higher device pixel ratios (HiDPI/Retina), the individual pixels are so small that aliasing is nearly invisible — another benefit of high-density displays.
Aliased vs anti-aliased edges
The illustration below shows a diagonal edge without anti-aliasing (left — hard pixel steps) and with anti-aliasing (right — graduated gray blending):
Browsers apply anti-aliasing automatically when rendering SVG shapes and when scaling
raster images — unless you explicitly opt out with CSS image-rendering: pixelated
(which is useful for pixel-art sprites where you want the sharp, blocky look). The
raster star in the first demo uses image-rendering: pixelated to make
the scaling artifact obvious for teaching purposes.