This is the first of a series of articles I'm planning to write about a couple of powerful yet fairly simple concepts of the SVG image format: the viewport and the viewBox.
As I'm going to show you, these are very flexible features: indeed they can be (ab)used to obtain many different effects!
In this article I will first introduce the SVG image format. Then I will move on to describe the SVG coordinate system and positioning.
The SVG format
SVG is a rather peculiar format. Unlike raster formats that describe an image through a grid of pixels, SVG describes an image using algorithms that define the shapes and paths that create the complete image.
SVG isn't suited to represent photographic images, but is particularly suited to draw illustrations and icons in a compact way. An SVG image is basically composed of one or more "shapes", each described by a specific mathematical function. Thanks to this, an SVG image can be enlarged/zoomed as much as you want, unlike the raster image formats.
Another difference with the bitmap formats is that SVG is a human-readable text format. In fact an SVG image is nothing more than an XML document. Each shape can be defined using simple textual instructions in the form of XML nodes.
For example, this markup creates an image with a blue circle:
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="#0971f1"/>
</svg>
The SVG specification defines many other tags that can be used to create both basic and complex shapes, such as rectangles, arcs, ellipses, or "paths", that can be used to define custom shapes using so called "Bezier curves".
Another great feature of the SVG file format, especially when used inside a web page, is that it can be styled in many ways through dedicated css properties or through so called "presentation attributes", i.e. CSS properties that can be used as attributes on SVG elements.
For example, you can change the color of a shape by simply setting the "fill" property.
In the previous example, we indeed defined the color of the circle using the "fill" attribute. Another way would be to assign the circle node a class, and then defining the style rules for that class in a css file:
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" class="mycircle"/>
</svg>
.mycircle {
fill: #0971f1;
}
The viewport and the viewBox
The viewport and the viewBox are two very important concepts that affect the size, the position and the visible area of an SVG image.
You can effectively think of the viewport as your mobile phone display with the camera app running.
The viewBox is the part of the scene you see inside the display. You can zoom in and out or move the phone and frame different parts of the scene, so to change the viewBox, but it will always be constrained to the physical size of the display, i.e. the viewport.
Lastly, the whole scene represent your SVG image, the so called SVG canvas.
Inside an SVG document, all measures are unitless: you don't say "this rectangle is 10mm large", you just say "this rectangle is large 10".
In our first example, we are just saying that the circle has its center at (50, 50) (not 50 px or mm) and that its radius is just "50" (and not 50 px). These dimensions are called user units.
The viewport can be set using two attributes on the SVG element: width and height. These represent the width and the height of the "display".
The viewport is specified using one of the units of measure that are known to the user agent: the browser in fact needs to know how much space to reserve in the DOM for the image.
When the viewport is specified in user units, the values are assumed to be in "px".
The viewBox controls which part of the image will be shown and at which size. It is defined using the viewBox attribute on the root SVG element, and its value is a space (or comma) separated list of 4 numbers expressed in user units that describe a rectangle that will be mapped to the size of the viewport. The four numbers represent respectively:
- min-x: the horizontal coordinate of the upper left corner of the rectangle.
- min-y: the vertical coordinate of the upper left corner of the rectangle
- width: the width of the rectangle...
- height: you guessed it!
When not specified, the viewBox is assumed to correspond to the SVG canvas.
Some examples
In the following example we are mapping the full SVG canvas to the viewport.
As you can see, the canvas size is 200 x 200, while the viewport size is 50px x 50px. Since the viewBox area has its top-left corner at (0,0), width and height both equal to 200 (which are the same sizes of the canvas), all the image is rendered inside the viewport:
In the next example, the viewBox size is 100 x 100, which corresponds to half of the canvas size. Since the top-left corner of the viewBox is set to (0,0), the viewport will show only the top-left quarter of the image:
This time the viewBox rectangle has its top-left corner right in the middle of the canvas. The width and height of the viewBox are both 100... What we get to see in the viewport is therefore the bottom-right part of the svg:
The preserveAspectRatio attribute
The examples seen till now all have one thing in common: the viewBox has the same aspect ratio of the viewport, i.e. the ratio between the viewBox width and height is the same ratio between the viewport width and height.
But what happens when the viewBox aspect ratio differs from that of the viewport? The preserveAspectRatio attribute controls just this behaviour. Its value is made up of two keywords: the alignment value and the meet or slice reference.
The alignment value determines how the image should be scaled. It can take up to 10 values, the most straightforward of them being:
- none: in this case the image will be scaled non uniformely to completeley fit into the viewport without taking into account its aspect ratio.
In all the following cases the image is instead uniformely scaled. These values determine where to position the scaled viewBox with respect to the viewport:
xMinYMin: the min-x and min-y values of the viewBox (the first two numbers) are aligned to the upper left corner of the viewport.
xMidYMin: the horizontal center of the viewBox is aligned with the horizontal center of the viewport while the min-y of the viewBox is aligned with the top of the viewport.
xMaxYMin: the min-x + width of the viewBox (i.e. the "right side") is aligned with the right of the viewport while the min-y of the viewBox is aligned with the top of the viewport.
xMinYMid: the min-x of the viewBox is aligned with the left of the viewport while the vertical center of the vieBox is aligned with the vertical center of the viewport.
xMidYMid: the horizontal and vertical centers of the viewBox are aligned with the center point of viewport.
xMaxYMid: the min-x + width of the viewBox (the "right side") is aligned with the right of the viewport while the vertical center of the viewBox is aligned with the vertical center of the viewport.
xMinYMax: the min-x of the viewBox is aligned with the left of the viewport while the min-y + height of the viewBox (the "bottom side") is aligned with the bottom of the viewport.
xMidYMax: the horizontal center of the viewBox is aligned with the horizontal center of the viewport while the min-y + height of the viewBox (the "bottom side") is aligned with the bottom of the viewport.
xMaxYMax: the min-x + width of the viewBox (the "right side") is aligned with the right of the viewport while the min-y + height of the viewBox (the "bottom side") is aligned with the bottom of the viewport.
The second keyword of the preserveAspectRatio atttibute (the meet or slice reference) is optional and determines how the image should be scaled. It can be one of the two following values:
- meet: the default value. The image is scaled such that the viewBox entirely fits into the viewport while preserving its aspect ratio. This means that the viewBox could result smaller than the viewport, depending on their aspect ratios.
- slice: The image is scaled such that the viewBox covers the viewport while preserving its aspect ratio. This means that the viewBox could extend beyond the viewport, depending on their aspect ratios.
That's all for now!
Now that we introduced the base concepts we can go on and see how just by changing the numbers of the viewBox we can achieve different "tricks". In the next articles of this serie we are just going to see some of them!
References
- Mozilla article on the viewBox
- Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio by Sara Soueidan - Btw, you should definitely follow her!
- Cover photo by Pine Watt on Unsplash
Top comments (0)