Responsive design is often associated with shifting boxes: fluid images, restructured navigation, text squeezed into ever-smaller spaces. But the broader scope of adaptive content includes consideration of granular alterations, not just rescaled containers.
As one example, take the flourish design above. The standard responsive approach would be to place max-width: 100%
on the element and let it shrink with the size of the viewport, but a viable alternative is writing code to simplify the design in response to the viewport size.
Creating the flourish
Either way, it makes sense to create the design in SVG. (I’ve used the open-source vector tool Inkscape, but there are many other possibilities).
The SVG code for the flourish starts like this:
<svg height="315" viewbox="0 0 450 315" id="flourish">
<path id="left-outer-flourish" d="m 90.738637,194.16171 c" />
…
</svg>
You can apply
id
attributes to SVG elements in the same way as you do HTML tags. In the case of the flourish, these id
values correspond to different features in the design, such as path#left-outer-flourish
.
There are a few ways of integrating the SVG with our code. For ease of use (albeit with a lot more code on our page) I'll embed it directly in the HTML:
<body>
<svg height="315" viewbox="0 0 450 315" id="flourish">
<path id="left-outer-flourish" d="m 90.738637,194.16171 c" />
</svg>
Styling SVG with CSS
You can customize the appearance of SVG element just like other content by using an id
selector. Knowing the id
values of individual SVG elements, we can also style them separately:
path#left-outer-flourish {
opacity: 0.6;
fill: #f00;
}
It’s important to understand that this does not mean that we can now use properties like fill
and stroke
on HTML content; the new style features are only applicable to SVG. You can place the SVG-referenced styles inside an SVG document, or in the HTML that uses it.
With the basic structure in place, we can use all the power of CSS to alter the visibility of each flourish element through media queries:
svg#flourish path {
transition: .6s opacity;
fill: #888;
}
@media screen and (max-width: 900px) {
path#right-outer-flourish,
path#left-outer-flourish {
opacity: 0;
}
}
You can see the result by widening and narrowing your browser window while looking at the flourish, or the design of the SVG tree below.
A Seasonal SVG Tree
This idea of adaptive SVG could be taken a lot further: as one example, an illustration of a tree that changes with the seasons as the viewport expands and contracts by transitioned the color and visibility of elements identified through classes.
An example of a leaf structure in the associated tree.svg drawing:
<path d="m 16.328214,195.28924 c 1.194609,9.02148 18.765013,10.15754 8.651206,1.67169 -2.759326,-1.06148 -5.718211,-1.47437 -8.651206,-1.67169 z" class="treeleaf" />
The associated CSS:
svg#tree {
float: right;
}
.treeleaf {
fill: #0c0;
transition: .6s fill linear,
.6s opacity ease-in-out;
}
.groundleaf {
fill: #610;
opacity: 0;
transition: .6s opacity ease-in-out;
}
@media screen and (max-width: 800px) {
.treeleaf {
fill: #090;
}
}
@media screen and (max-width: 700px) {
.treeleaf {
fill: #a20;
}
}
@media screen and (max-width: 700px) {
path.treeleaf {
opacity: 0;
}
path.groundleaf {
opacity: 1;
}
}
I’ve barely scraped the surface of this technique; there are many more possibilities, which I will show in future articles.
Conclusion
One might argue that the modular approach shown here could be duplicated by using precisely overlapped multiple background images, or background image “sprite” sheets manipulated with media queries, although that would come at a cost of greater code complexity, lack of opacity transitions and higher file sizes.
Finally, it should also be noted that this technique only shows and hides portions of an SVG drawing; all the vector data is still loaded. Under most circumstances this solution would be fine, as SVG file sizes tend to be relatively small; for complex presentations involving large files, it would be an interesting proposition to use JavaScript to load in SVG elements dynamically, based on bandwidth and/or device screen size.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/azLcy