Dynamically scaling CSS values primarily based on the viewport width is hardly a brand new matter. You’ll find loads of in-depth protection proper right here on CSS-Tips in articles like this one or this one.
Most of these examples, although, use relative CSS models and unitless values to attain fluid scaling. That loses pixel perfection and normally introduces textual content wrapping and structure shifts as soon as the display screen goes beneath or above a sure threshold.
However what if we actually do need pixel perfection? What if, let’s say, we’re growing a posh real-time analytics dashboard to be seen on giant TVs at a convention room or as some PWA to be opened completely on cellular and pill units, versus text-heavy blogs and information web sites? These are instances the place we’d like extra precision.
In different phrases, what if we need to scale designs uniformly? In fact, one can scale the content material with CSS transforms primarily based on the out there width as lined in this text — this manner, the proper ratios are preserved.
Nonetheless, we are able to additionally obtain fluid proportional scaling UIs utilizing pixel values in CSS. They scale appropriately primarily based on the machine display screen actual property, all whereas preserving their pixel-perfect proportions. Additional, we are able to nonetheless use pixel values and routinely convert them to relative CSS models if working in pixels is extra comfy or acquainted.
Scaling our UI
Let’s attempt to implement this superior dashboard, courtesy of Craftwork. We have to make it in such a approach that it scales completely and preserves all of the texts line counts, margins, picture sizes, and so forth.
Let’s work in CSS pixel values and use SCSS for pace and comfort. So, if we’re to focus on the title of one in every of these card widgets, our SCSS may look one thing like this:
.cardWidget {
.cardHeading {
font-size: 16px;
}
}
Nothin’ fancy. Nothing now we have not seen earlier than. Being a pixel worth, this won’t scale.
This design was created with a container that’s 1600px vast. Let’s assume that at 1600px, the perfect font measurement for the titles of the playing cards must be 16px since that’s the way it’s designed.
Now that now we have the “excellent” container width font measurement for this width, let’s scale our CSS pixel values accordingly utilizing the present* viewport width:
/*
1600px is the perfect viewport width that the UI designers who
created the dashboard used when designing their Figma artboards
Please not we aren’t utilizing pixel models right here, treating it purely
as a numeric worth.
*/
–ideal-viewport-width: 1600;
/*
The precise width of the person machine
*/
–current-viewport-width: 100vw;
.cardWidget {
.cardHeading {
/*
16px is the perfect font measurement that the UI designers need for
1600px viewport width.
Please be aware that we aren’t utilizing pixel models right here,
treating it purely as a numeric worth.
*/
–ideal-font-size: 16;
/*
Calculate the precise font measurement:
We take our idealFontSize and multiply it by the distinction
between the present viewport width and the perfect viewport width.
*/
font-size: calc(
var(–ideal-font-size) * (var(–current-viewport-width) / var(–ideal-viewport-width)
);
}
}
As you possibly can see, we deal with the perfect font measurement we obtained from the design as a base and multiply it by the distinction between the present and excellent viewport widths. How does this look mathematically? Let’s say we’re viewing this internet app on a display screen with the very same width because the mockup:
–current-device-width: 100vw; // represents 1600px or full width of the display screen
–ideal-viewport-width: 1600; // discover that the perfect and present width match
–ideal-font-size: 16;
// this evaluates to:
font-size: calc(16 * 1600px / 1600);
// identical as:
font-size: calc(16 * 1px);
// last end result:
font-size: 16px;
So, since our viewport width matches completely, our font-size ends being precisely 16px on the excellent viewport width of 1600px.
As one other instance, let’s say we’re viewing the online app on a smaller laptop computer display screen that’s 1366px vast. Right here is the up to date math:
font-size: calc(16 * 1366px / 1600);
// identical as:
font-size: calc(16 * 0.85375px);
// last end result:
font-size: 13.66px;
Or let’s say we’re viewing this on a full high-definition show at 1920px vast:
font-size: calc(16 * 1920px / 1600);
// identical as:
font-size: calc(16 * 1.2px);
// last end result:
font-size: 19.2px;
You’ll be able to see for your self how despite the fact that we use pixel values as reference, we are literally capable of proportionally scale our CSS values primarily based on the distinction in width between the perfect and present viewport sizes.
Here’s a small demo I constructed as an example the method:
Right here’s a video for convienence:
Clamping the min and max viewport width
Utilizing this present method, the design scales to match the viewport measurement, irrespective of how huge or small the viewport will get. We are able to forestall this with CSS clamp() which permits us to set a minimal width of 350px and most width of 3840px. Because of this if we’re to open the online app on a tool with 5000px width, our structure will keep locked at 3840px:
–ideal-viewport-width: 1600;
–current-viewport-width: 100vw;
/*
Set our minimal and most allowed structure widths:
*/
–min-viewport-width: 350px;
–max-viewport-width: 3840px;
.cardWidget {
.cardHeading {
–ideal-font-size: 16;
font-size: calc(
/*
The clamp() perform takes three comma separated expressions
as its parameter, within the order of minimal worth, most well-liked worth
and most worth:
*/
–clamped-viewport-width: clamp(var(–min-viewport-width), var(–current-viewport-width), var(–max-viewport-width);
/*
Use the clamped viewport width in our calculation
*/
var(–ideal-font-size) * var(–clamped-viewport-width) / var(–ideal-viewport-width)
);
}
}
Let’s make a helper for the unit conversions
Our code is kind of verbose. Let’s write a easy SCSS perform that converts our values from pixels to relative models. That approach, we are able to import and reuse wherever this wherever with out a lot duplication:
/*
Declare a SCSS perform that takes a worth to be scaled and
excellent viewport width:
*/
@perform scaleValue(
$worth,
$idealViewportWidth: 1600px,
$min: 350px,
$max: 3840px
) {
@return calc(
#{$worth} * (clamp(#{$min}, 100vw, #{$max}) / #{$idealViewportWidth})
);
}
/*
We are able to then apply it on any numeric CSS worth.
Please be aware we’re passing not pixel primarily based, however numeric values:
*/
.myElement {
width: #{scaleValue(500)};
peak: #{scaleValue(500)};
box-shadow: #{scaleValue(2)} #{scaleValue(2)} rgba(black, 0.5);
font-size: #{scaleValue(24)};
}
Porting this to Javascript
Generally CSS doesn’t reduce it and now we have to make use of JavaScript to measurement a element. Let’s say we’re establishing an SVG dynamically and we have to measurement its width and peak properties primarily based on a really perfect design width. Right here is the JavaScript to make it occur:
/*
Our helper technique to scale a worth primarily based on the machine width
*/
const scaleValue = (worth, idealViewportWidth = 1600) => {
return worth * (window.innerWidth / idealViewportWidth)
}
/*
Create a SVG factor and set its width, peak and viewbox properties
*/
const IDEAL_SVG_WIDTH = 512
const IDEAL_SVG_HEIGHT = 512
const svgEl = doc.createElement(‘svg’)
/* Scale the width and peak */
svgEl.setAttribute(‘width’, scaleValue(IDEAL_SVG_WIDTH))
svgEl.setAttribute(‘peak’, scaleValue(IDEAL_SVG_WIDTH))
/*
We do not really want to scale the viewBox property as a result of it should
completely match the ratio of the scaled width and peak
*/
svg.setAttribute(‘viewBox’, `0 0 ${IDEAL_SVG_WIDTH} ${IDEAL_SVG_HEIGHT}`)
The drawbacks of this method
This answer will not be good. For instance, one main downside is that the the UIs are not zoomable. Regardless of how a lot the person zooms, the designs will keep locked as if they’re seen at 100% zoom.
That stated, we are able to simply use conventional media queries, the place we set totally different excellent numeric values at totally different viewport widths:
.myElement {
width: #{scaleValue(500)};
peak: #{scaleValue(500)};
box-shadow: #{scaleValue(2)} #{scaleValue(2)} rgba(black, 0.5);
font-size: #{scaleValue(24)};
@media (min-width: 64em) {
width: #{scaleValue(800)};
font-size: #{scaleValue(42)};
}
}
Now we are able to profit from each media queries and our pixel-perfect linear scaling.
Wrapping up
All of that is an alternate method to implement fluid UIs. We deal with the pixel-perfect values as pure numeric values, and multiply them by the distinction between the present viewport width and the “excellent” viewport width from the designs.
I’ve used this method extensively in my very own work and hope that you’ll find some use of it too.
The put up Methods to Get a Pixel-Good, Linearly Scaled UI appeared first on CSS-Tips. You’ll be able to assist CSS-Tips by being an MVP Supporter.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!