The new responsive — Viewport units

Ash Durham
4 min readJun 3, 2017

I’m a huge advocate of fluid responsive development. Gone are the days of coding for a particular width or device — not new news — with the amount of handheld devices around, all at various sizes. Every pixel size needs to be accounted for, ensuring the page display is always perfect. This is quite easily achieved by using media queries and percentage widths for the most part, however I’ve been finding lately that I need even more control than ever before when working with more complex designs. Fortunately, there is an answer — viewport units.

Viewport units

The way I’ve always thought of viewport units, generally speaking, is that its just like a percentage however based off the viewport container as opposed to the relative container of the element you’re setting the unit on. I think this because 1vw or 1vh is 1/100th of the width or height of the viewport. With that said, viewport units are much more versatile than percentage units — setting a percentage as a font-size just doesn’t quite have the same effect. This is where viewport units really show its power, making this unit type an extremely useful asset for responsive development.

Usage

A quick google search for “CSS viewport” will give you a slather of usage examples, some by the likes of Web Design Weekly, SitePoint and CSS Tricks. All of which give awesome insight into how viewport units can help layout a page, center elements and keep font sizes scaled with the viewport — all much better explained than I probably ever could.

However, this post is not just another of those.

I want to explain how viewport units can help in situations where you have multiple elements that you need to keep in scale as the browser window shrinks, and have it all calculated based on a pixel width.

A use case

Yep, thats not a typo — calculated from a pixel width. Take the following scenario for example: you have a big image that contains layout that you could easily achieve using HTML and CSS, but you want it to scale with the browser window. This contains text, some icons, maybe even parts that would have added value to the graphic if animated.

Using percentages only gets you part way there, you can’t scale the text with the percentage widths so at some point the graphic would be out of proportion. You could micro-manage the font sizes with 101 media queries but that gets messy real fast. Lets throw some SVG’s at this scenario while we’re at it, because the whole reason you’re doing this is so the graphic is super crisp and the page load is smaller right? SVG’s for the win — but alas, SVG scaling with a percentage width will keep the viewport height of the SVG in tact and not scale in proportion, leaving you with “padding” above and below the actual, scaled, SVG graphic. What can we do to keep all of this to scale without it all being one heavy pixelated JPG?

The calculation

So I mentioned there was a calculation.

(Initial size * 100) / Query width

This calculation will give you the viewport unit value required to scale your element from its initial size at the width the query is beginning from. Lets put some context behind this by applying it to the above example pen:

You’ll note that when scaling the pen lower than the 910px viewport width, all the elements within the dark grey box scale down in proportion. This is a very simple example of the power viewport units can give to your responsive options.

Next problem is the calculation. Coding this into your CSS sheet and working out all the calculations for each value you want to control can be quite time consuming… however there is hope!

Preprocessors to the rescue

We can create a simple mixin to do this for us in LESS or SASS!

First, lets take a look at how it can be implemented using a LESS mixin:

.viewport(@property, @initialsize, @maxwidth, @unit:vw) {
@{property}: unit((@initialsize*100)/@maxwidth, @unit);
}

Now lets see how it can be implemented using a SASS mixin:

=viewport($property, $initialsize, $maxwidth, $unit:vw)
#{$property}: ($initialsize*100)/$maxwidth#{$unit}

As you can see in the examples, utilising a preprocessor and using a mixin to work out the values for you makes working with this method a breeze. And now the possibilities are endless and only limited to your imagination.

Throughout a lot of my work lately, I have opted, where appropriate, to recreate imagery using HTML and CSS instead of simply exporting a JPG for it. Main reasons being:

  • to avoid needing to either produce 2 images(or 3 if you’re handing @3x screen resolutions), or simply start with an image that is 2 times bigger than its display size to ensure crisp viewing on retina screens
  • reduce the amount of calls to the server for assets, or in the case that the graphic would still include SVG iconography, reduce the size of the calls
  • enable the ability to add interactivity or animation to a graphic

Using this method of viewport units to handle the responsive nature of these scenarios has enabled me to push those boundaries!

Give it a go, share the wins, or losses, with the method. I’m interested to hear how others can/have used to better their pages.

--

--