ViewportJS is built on top of window.matchMedia
and provides valuable features that enable more structure when querying and subscribing to media queries.
-
1.16 kB minified & gzipped.
-
Supports all browsers that support
window.matchMedia
. -
Compatible with CommonJS, AMD, and browser globals (via UMD).
-
Supports SSR (server-side rendering) by providing a shallow API when
window.matchMedia
is unavailable.
Give the demo a try by changing the size of your browser window and watch the UI update.
If you are upgrading from v3, please see the v4 migration guide.
- Installation
- Usage
- Configuration
- Subscribing to Viewport Changes
- Instance Methods
- Server-Side Rendering
- Examples
Install the latest version from npm:
npm install viewportjs
Add the viewportjs
package to your app:
const viewport = require( 'viewportjs' );
const myViewports = viewport( /* configuration */ );
The API is exported as an anonymous module. If you're not familiar with AMD, RequireJS is a great place to start.
Download the latest development and production versions from UNPKG. Once the script is loaded, the viewport
function can be accessed globally.
<!-- When deploying, replace "viewport.js" with "viewport.min.js". -->
<script src="viewport.js"></script>
<script>
const myViewports = viewport( /* configuration */ );
</script>
Configure viewports by name:
const myViewports = viewport( [
{
name: 'small',
query: '( min-width:0px ) and ( max-width:480px )'
},
{
name: 'medium',
query: '( min-width:480px ) and ( max-width:767px )'
},
{
name: 'large',
query: '( min-width:769px )'
}
] );
Once configured, you can query their state:
// Check if `small` is the current viewport
myViewports.current( 'small' ); // boolean
// Get the current viewport object
myViewports.current(); // { name: 'small', matches: boolean, current: boolean }
// Check if the `small` viewport's media query matches
myViewports.matches( 'small' ); // boolean
// Retrieve all matches
myViewports.matches(); // [ /* matches viewport state objects */ ]
You can also subscribe to state changes:
// Subscribe to changes in 'small' viewport
myViewports( 'small', state => {
// Do something based on `state`
// {
// name: 'small',
// matches: boolean,
// current: boolean
// }
} );
The initialization method takes an array of viewport configuration objects that are composed of two properties:
-
name
(string) The viewport's nickname. Must be unique. -
query
(string) A validmediaQueryString
.
The order of these objects in the array is important, as it determines how to calculate the current
viewport, which is defined as the last matching viewport based on the order of the configuration array. So if you prefer a "mobile-first" approach, your viewport configuration objects should be ordered from smallest to largest.
The initialization method returns a configured instance that can act as:
- A function used to subscribe to viewport changes.
- An object that contains methods for querying viewport state.
The initialization method returns an instance that can be used to subscribe to state changes on the configured viewports.
Arguments:
name
: (string) (optional) The name of a configured viewport.handler
: (Function) The function to execute whenever state changes occur.
Returns:
- (Function): A function that unsubscribes
handler
.
To subscribe to the state of an individual viewport, both name
and handler
are required. Providing only a handler
will set up a subscription to the states of all configured viewports.
A subscriber's handler
is executed whenever there's a change in either the viewport's matched
or current
state. When a subscriber is added, its handler
will be immediately executed.
The handler
receives the following arguments when executed:
state
: (Object) The changed viewport's state object.instance
: (Object) The configured instance.
A viewport state object has three properties:
name
: (string) The name of a configured viewport.matches
: (boolean) If the viewport's media query matches.current
: (boolean) If the viewport is current.
Example:
const myViewports = viewport( /* configuration */ );
// Subscribe to an individual configured viewport
myViewports( 'name', state => {} );
// Subscribe to all configured viewport
myViewports( state => {} )
For scenarios where you're only interested in matching a single media query, you can provide the initialization method with a valid mediaQueryString
and an optional handler
, instead of a configuration array. This will return an instance with a limited API.
Arguments:
query
: (string) A validmediaQueryString
.handler
: (Function) (optional) The function to execute whenever state changes occur.
Returns:
- (Object): A limited API composed of the
matches()
andremove()
method.
If provided, handler
is executed whenever there's a change in the media query's matched
state, including on initial subscription.
The handler
receives the following arguments when executed:
matches
: (boolean) If the media query matches.instance
: (Object) The configured instance.
Example:
const smallvp = viewport( '( max-width: 500px )', ( matches, instance ) => {} );
smallvp.matches(); // true/false
smallvp.remove(); // remove the handler, if provided.
When called with the name
argument, checks if name
is the current viewport and returns a boolean. Otherwise, it returns the current viewport's state object.
The current viewport is defined as the last matching viewport based on the order of the configuration array. If there is no current viewport, the state object for the undefined
viewport is returned: { name: undefined, matches: false, current: false }
.
Arguments:
name
: (string) (optional) The name of the configured viewport to check.
Returns:
- (boolean): If
name
is the current viewport. - (Object): The state object of the current viewport.
myViewports.current(); // { name: string, matches: boolean, current: boolean }
myViewports.current( 'name' ); // true/false
When called with the name
argument, checks if the name
viewport's media query matches. Otherwise, it returns an array of all matching viewports.
If there are no matching viewports, an empty array is returned.
Arguments:
name
: (string) (optional) The name of the configured viewport to check.
Returns:
- (boolean): If the
name
viewport matches. - (Array): An array of state objects for all matching viewports.
myViewports.matches(); // [ { name: string, matches: boolean, current: boolean }, ... ]
myViewports.matches( 'name' ); // true/false
When called with the name
argument, checks if the name
viewport was the previously current viewport. Otherwise, it returns the previously current viewport's state object.
If there was no previously current viewport, the state object for the undefined
viewport is returned: { name: undefined, matches: false, current: false }
.
Arguments:
name
: (string) (optional) The name of the configured viewport to check.
Returns:
- (boolean): If
name
was the previously current viewport. - (Object): The state object of the previously current viewport.
myViewports.previous(); // { name: string, matches: boolean, current: boolean }
myViewports.previous( 'name' ); // true/false
Removes all the instance's configured viewports and subscribers at once.
Returns:
- (null): Subscribers are removed and values set to
null
.
const myViewports = viewport( /* viewport config array */ );
myvps( 'small', state => {} );
myvps( 'medium', state => {} );
myvps.remove();
When called with the name
argument, returns the named viewport's state object. Otherwise, it returns an array of state objects for all viewports.
Arguments:
name
: (string) (optional) The name of the configured viewport to check.
Returns:
- (Object): The state object of the named viewport.
- (Array): An array of state objects for all viewports.
myViewports.state(); // [ { name: string, matches: boolean, current: boolean }, ... ]
myViewports.previous( 'name' ); // { name: string, matches: boolean, current: boolean }
ViewportJS supports SSR (or "Universal JavaScript") through a shallow API that enables the use of all methods in an environment where window.matchMedia
is unavailable.
Due to potential memory leaks, calls that subscribe to viewports should only be made when their respective unsubscribe functions (or the instance's remove()
method) can be called in the same environment. Initialization and query methods can be used in any environment, but it's best if subscriptions are made in code that only executes in the browser. The development
build of ViewportJS will log a warning whenever a subscription is made in an environment where window.matchMedia
is unavailable. All logging is removed in the production
build.
See the relevant framework examples below for SSR-compatible demonstrations.