Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
SCSS mixin to support vh and vw units on all iOS Safari versions. Based on an idea by Patrick Burtchaell's: https://gist.github.com/pburtchaell/e702f441ba9b3f76f587
/**
* Fix for vw, vh, vmin, vmax on iOS 7.
* http://caniuse.com/#feat=viewport-units
*
* This fix works by replacing viewport units with px values on known screen sizes.
*
* iPhone 6 and 6 Plus cannot run iOS 7, so are not targeted by this fix.
* Target devices running iOS 8+ will incidentally execute the media query,
* but this will still produce the expected result; so this is not a problem.
*
* As an example, replace:
*
* height: 50vh;
* font-size: 5vmin;
*
* with:
*
* @include viewport-unit(height, 50vh);
* @include viewport-unit(font-size, 5vmin);
*/
@mixin viewport-unit($property, $value) {
#{$property}: $value;
$unit: unit($value);
@if (index((vw, vh, vmin, vmax), $unit) != null) {
$devices: (
(768px, 1024px), // iPad (all versions)
(320px, 480px), // iPhone 4
(320px, 568px) // iPhone 5, 5C, 5S
);
@each $device in $devices {
$device-width: nth($device, 1);
$device-height: nth($device, 2);
$device-query: "only screen and (-webkit-min-device-pixel-ratio: 1)";
$device-query: "#{$device-query} and (device-width: #{$device-width})";
$device-query: "#{$device-query} and (device-height: #{$device-height})";
$percent: $value / ($value * 0 + 1); // see https://github.com/sass/sass/issues/533
$percent-width: $device-width * $percent / 100;
$percent-height: $device-height * $percent / 100;
@if ($unit == vmin or $unit == vmax) {
@media #{$device-query} {
#{$property}: if($unit == vmin, $percent-width, $percent-height);
}
}
@else {
@media #{$device-query} and (orientation: portrait) {
#{$property}: if($unit == vw, $percent-width, $percent-height);
}
@media #{$device-query} and (orientation: landscape) {
#{$property}: if($unit == vw, $percent-height, $percent-width);
}
}
}
}
}
@JetLewis

This comment has been minimized.

Show comment Hide comment
@JetLewis

JetLewis Sep 18, 2015

Neat! Now, what if I want to use it with calc (which I almost always do) ? Like @ include viewport-unit(max-height, calc(100vh - 113px)); That would make it perfect =)
Thanks anyways.

Neat! Now, what if I want to use it with calc (which I almost always do) ? Like @ include viewport-unit(max-height, calc(100vh - 113px)); That would make it perfect =)
Thanks anyways.

@BenMorel

This comment has been minimized.

Show comment Hide comment
@BenMorel

BenMorel Sep 22, 2015

That one is tough. Then only way I can think of at the moment, is to add an optional third parameter to the mixin, like $delta: 0px. Then change lines starting with #{$property} to include a calc() of the current value + $delta. So instead of @include viewport-unit(max-height, calc(100vh - 113px));, you would do @include viewport-unit(max-height, 100vh, -113px);. That would be limited to the simplest calculations, though.

Owner

BenMorel commented Sep 22, 2015

That one is tough. Then only way I can think of at the moment, is to add an optional third parameter to the mixin, like $delta: 0px. Then change lines starting with #{$property} to include a calc() of the current value + $delta. So instead of @include viewport-unit(max-height, calc(100vh - 113px));, you would do @include viewport-unit(max-height, 100vh, -113px);. That would be limited to the simplest calculations, though.

@AdmireNL

This comment has been minimized.

Show comment Hide comment
@AdmireNL

AdmireNL Oct 30, 2015

Is this mixin also available in LESS? (sorry my project is in LESS). I wasn't able to convert this with sass2less converters :(

Is this mixin also available in LESS? (sorry my project is in LESS). I wasn't able to convert this with sass2less converters :(

@sergeynikiforov

This comment has been minimized.

Show comment Hide comment
@sergeynikiforov

sergeynikiforov Nov 28, 2015

Exactly what I was looking for! Thanks!

Exactly what I was looking for! Thanks!

@sarukuku

This comment has been minimized.

Show comment Hide comment
@sarukuku

sarukuku Dec 1, 2015

Clever. Clever indeed.

sarukuku commented Dec 1, 2015

Clever. Clever indeed.

@zaygraveyard

This comment has been minimized.

Show comment Hide comment
@zaygraveyard

zaygraveyard Feb 12, 2016

@AdmireNL I wrote a LESS mixin that does the same thing at https://gist.github.com/zaygraveyard/dc4ca2cb5271d6e8d641

@AdmireNL I wrote a LESS mixin that does the same thing at https://gist.github.com/zaygraveyard/dc4ca2cb5271d6e8d641

@seafoam6

This comment has been minimized.

Show comment Hide comment
@seafoam6

seafoam6 Apr 6, 2016

I just wanted to say THANK YOU!!!!!

seafoam6 commented Apr 6, 2016

I just wanted to say THANK YOU!!!!!

@tbcorr

This comment has been minimized.

Show comment Hide comment
@tbcorr

tbcorr Apr 21, 2016

This is awesome, thank you!

tbcorr commented Apr 21, 2016

This is awesome, thank you!

@artemean

This comment has been minimized.

Show comment Hide comment
@artemean

artemean Jan 19, 2017

This is useless.
First you cannot detect if it's Safari or any other browser in CSS. So these rules will apply in any browser, but you don't need it in Chrome or Opera because viewport units are calculated correctly there.
Second this mixin doesn't take in consideration the sizes of browser elements, like toolbars. For example the screen height of iPad is 1024px, but in Safari the real height of viewport (portrait) is 905px, because the toolbar (address etc) takes 119px.

This is useless.
First you cannot detect if it's Safari or any other browser in CSS. So these rules will apply in any browser, but you don't need it in Chrome or Opera because viewport units are calculated correctly there.
Second this mixin doesn't take in consideration the sizes of browser elements, like toolbars. For example the screen height of iPad is 1024px, but in Safari the real height of viewport (portrait) is 905px, because the toolbar (address etc) takes 119px.

@sreenasandeep

This comment has been minimized.

Show comment Hide comment
@sreenasandeep

sreenasandeep Feb 2, 2017

can you plz explain how i can change the mixing to get height with minus calculation like height: calc(100vh - 680px);

can you plz explain how i can change the mixing to get height with minus calculation like height: calc(100vh - 680px);

@branditodesigns

This comment has been minimized.

Show comment Hide comment
@branditodesigns

branditodesigns Oct 4, 2017

@inliner
css target hacks?

@inliner
css target hacks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment