I just learned about viewport relative units, vh, vw, vmax, vmin.
Amazing. Finally an easy way to do full height elements via 100vh == 100% viewport height.
Only problem? It blows up explosively on IOS devices.
I love the concept though, so I just created a simple coffeescript class which can be invoked directly or via data tags to trigger widths and heights correctly by converting an inline data attribute to explicit calculations on resize.
Parsing CSS for these new units was too much overhead.
https://gist.github.com/yuchant/8610909
Usage:
<div data-viewport-styles="width: 100vh; height: 50vw;"></div>
class root.utils.ViewportHeight
‘The VH unit is not well supported. Use data-tags instead.
data-viewport-unit="line-height: 100vh; height: 100vh;’
constructor: ({@element, @styles}={}) ->
@$element = $ @element
@$window = $ window
@_bindHandlers()
_getStyles: ->
# get styles as array
if not @_styles
styles = {}
for style in _.filter(@styles.split(‘;’), Boolean)
[key, value] = style.split(‘:’)
styles[key.trim()] = @_getValue(value)
self._styles = styles
return self._styles
_bindHandlers: ->
$(window).resize _.debounce(@onResize, 50)
_getValue: (value) ->
# given a unit like 400vw or 400vh, set it to absolute pixel values
# map viewport units to viewport unit conversion functions
viewportUnitMap = {
‘vh’: @_vh,
‘vw’: @_vw,
‘vmax’: null,
‘vmin’: null,
}
value = value.replace(‘;’, ”).trim()
for unit, func of viewportUnitMap
if unit.substr(value)
return func(parseInt(value))
_vh: (value) =>
@$window.height() * value/100
_vw: (value) =>
@$window.width() * value/100
_vmax: (value) =>
return Math.max @_vh(value), @_vw(value)
_vmin: (value) =>
return Math.min @_vh(value), @_vw(value)
onResize: =>
# window has been resized. update CSS values of vh/vw equivalents
@$element.css @_getStyles()
$("[data-viewport-styles]").each (index, el) ->
new root.utils.ViewportHeight
element: el
styles: $(el).data(‘viewport-styles’)