UNPKG

vh-check

Version:
334 lines (237 loc) 8.63 kB
# vh-check get reliable CSS `vh` sizes for [1kb gzipped](https://bundlephobia.com/result?p=vh-check) [![npm version](https://badge.fury.io/js/vh-check.svg)](https://badge.fury.io/js/vh-check) [![Build Status](https://travis-ci.org/Hiswe/vh-check.svg?branch=master)](https://travis-ci.org/Hiswe/vh-check) <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> - [the problem](#the-problem) - [why not use viewport-units-buggyfill?](#why-not-use-viewport-units-buggyfill) - [use](#use) - [as a global variable](#as-a-global-variable) - [as a commonJS module](#as-a-commonjs-module) - [as a ES module module](#as-a-es-module-module) - [how it works](#how-it-works) - [returned object](#returned-object) - [example](#example) - [in your javascript](#in-your-javascript) - [in your CSS](#in-your-css) - [configuration](#configuration) - [as a string](#as-a-string) - [as an object](#as-an-object) - [cssVarName](#cssvarname) - [force](#force) - [bind](#bind) - [redefineVh](#redefinevh) - [updateOnTouch](#updateontouch) - [onUpdate](#onupdate) - [about browser support](#about-browser-support) - [demo](#demo) - [github pages](#github-pages) - [local](#local) - [caveats](#caveats) - [other stuff](#other-stuff) - [changelog](#changelog) - [migrating](#migrating) - [run the tests](#run-the-tests) - [thanks](#thanks) - [related](#related) <!-- END doctoc generated TOC please keep comment here to allow auto update --> ## the problem Browsers don't always compute the [vh unit](https://developer.mozilla.org/en-US/docs/Web/CSS/length#vh) the same way. Some mobile browsers compute the `vh` CSS unit without taking care of the url bar. That means that a `100vh` div will overflow the viewport by the size of the url bar. This is the current behavior for: - [Safari iOS](https://bugs.webkit.org/show_bug.cgi?id=141832) - [Chrome android >= 56](https://developers.google.com/web/updates/2016/12/url-bar-resizing) As explained in the chrome post, that make sense but make it hard to have a full [hero top block](https://line25.com/articles/30-web-designs-that-fully-embrace-the-hero-image). This script will measure the difference and put it in a CSS var. You can read more on this [css-trick article](https://css-tricks.com/the-trick-to-viewport-units-on-mobile/#article-header-id-0) by [Louis Hoebregts](https://css-tricks.com/author/louishoebregts/) <img src="https://unpkg.com/vh-check/issue-schema.svg" width="200" style="display: block; margin: 0 auto"/> ## why not use viewport-units-buggyfill? It's doing a very good job: https://github.com/rodneyrehm/viewport-units-buggyfill But it has some problems with media-queries: https://github.com/rodneyrehm/viewport-units-buggyfill/issues/13 ## use ### as a global variable ```html <script src="https://unpkg.com/vh-check/dist/vh-check.min.js"></script> <script> (function () { // initialize the test var test = vhCheck(); }()); </script> ``` ### as a commonJS module ``` npm install vh-check ``` ```js var check = require('vh-check') var test = vhCheck() // return an object (see below) ``` ### as a ES module module ``` npm install vh-check ``` ```js import vhCheck from 'vh-check' const test = vhCheck() ``` ### how it works - It will update the `vh-check` CSS custom property if needed - `vh-check` will be updated on `orientationchange` [event](https://developer.mozilla.org/en-US/docs/Web/Events/orientationchange) - `vh-check` **will not** be updated on scroll event by default ### returned object vh-check will return a full object: ```js { isNeeded: false, // wether or not it's needed value: 0, // the CSS var value vh: 480, // a 100vh div size windowHeight: 480, // same value as window.innerHeight offset: 0, // difference between the above sizes recompute: function computeDifference(), // call this to programmatically get all the values and set the CSS var // - this can be useful if you want to add your own listeners // that will trigger a computation unbind: function unbindVhCheckListeners(), // call this to remove any window listeners created by vh-check }, ``` ## example ### in your javascript ```js vhCheck() ``` ### in your CSS ```css main { height: 100vh; /* If you need to support browser without CSS var support (<= IE11) */ height: calc(100vh - var(--vh-offset, 0px)); /* enable vh fix */ } ``` ## configuration ### as a string You can pass the CSS var name as a param to `vhCheck()` (default `vh-offset`) ```js vhCheck('browser-address-bar') ``` In your CSS you will have to reference: ```css main { min-height: 100vh; min-height: calc(100vh - var(--browser-address-bar, 0px)); } ``` ### as an object `vh-check` allows you to have more control by passing a configuration object. ```js vhCheck({ cssVarName: 'vh-offset', force: false, bind: true, redefineVh: false, updateOnTouch: false, onUpdate: function noop() {}, }) ``` #### cssVarName **type:** `string` **default:** `'vh-offset'` Change the CSS var name #### force **type:** `boolean` **default:** `false` Set the CSS var even if `100vh` computation is good #### bind **type:** `boolean` **default:** `find` Automatically bind to `orientationchange` event #### redefineVh **type:** `boolean` **default:** `false` Change the CSS var value. Instead of being the total size of the gap, it will be 1% of the real window size. You can find more explanation in this [CSS Trick article](https://css-tricks.com/the-trick-to-viewport-units-on-mobile/) ⚠️ **Important** If you don't set a `cssVarName`, the CSS custom property will be named `vh` instead of `vh-offset`. So your CSS should be: ```css .my-element { height: 100vh; height: calc(var(--vh, 1vh) * 100); } ``` #### updateOnTouch **type:** `boolean` **default:** `false` Add an event listener on `touchmove` to recompute the sizes ⚠️ **Important** - This can impact your website performances as changing sizes will make your browser [reflow](https://www.sitepoint.com/10-ways-minimize-reflows-improve-performance/) - if `options.bind` is `false`, this will be ignored as well #### onUpdate **type:** `function` **default:** `function noop(){}` you can specify a callback which will be called with an updated `vh-check` object every time a computation occurre. ## about browser support This library require [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) which is [IE10+](https://caniuse.com/#search=requestAnimationFrame) You'll need a [polyfill](https://github.com/airwave-development/raf-polyfill) if you want to support older browsers - **vh unit** – supported since [IE9+](http://caniuse.com/#search=vh) - **calc** – supported since [IE9+](https://caniuse.com/#search=calc) - **CSS custom properties** – supported since [IE Edge](http://caniuse.com/#feat=css-variables) and iOS 9.3+ IE11 & below will need a fallback without CSS var - **concerned browsers** – as for now: - Safari since iOS7+ - Chrome Android >= v56 To sum it up: | Browser | Library will work | CSS Custom property | | ------------- | :---------------: | :-----------------: | | <= IE 9 | ❌ | ❌ | | IE 10 & IE 11 | ✅ | ❌ | | IE Edge | ✅ | ✅ | | < iOS 9.3 | ✅ | ❌ | ## demo ### github pages https://hiswe.github.io/vh-check/ ### local you'll need [node](https://nodejs.org/en/) - clone the project - `npm install` - `npm start` - go to: http://localhost:8080 ## caveats **On iOS only**, Chrome & Firefox will change dynamically the size of `1vh` depending on the display of the address bar. Thus the library will return a `not needed` value. If you want to prevent your vh's components to resize, you could fix the size of the unit like this: ```js vhCheck({ bind: false, redefineVh: true, }) ``` ```css .my-div { height: calc(var(--vh, 1vh) * 100); } ``` ## other stuff ### changelog See [CHANGELOG.md](https://github.com/Hiswe/vh-check/blob/master/CHANGELOG.md) ### migrating See [MIGRATING.md](https://github.com/Hiswe/vh-check/blob/master/MIGRATING.md) ### run the tests - clone the project - `npm install` - `npm test` ### thanks - [Chris Butterworth](https://github.com/ChrisButterworth) for the contribution ### related - [ios-inner-height](https://www.npmjs.com/package/ios-inner-height)