You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					291 lines
				
				6.0 KiB
			
		
		
			
		
	
	
					291 lines
				
				6.0 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# `css-box-model` 📦
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Get accurate and well named [CSS Box Model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model) information about a [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[](https://travis-ci.org/alexreardon/css-box-model)
							 | 
						||
| 
								 | 
							
								[](https://www.npmjs.com/package/css-box-model)
							 | 
						||
| 
								 | 
							
								[](https://david-dm.org/alexreardon/css-box-model)
							 | 
						||
| 
								 | 
							
								[](https://www.npmjs.com/package/css-box-model)
							 | 
						||
| 
								 | 
							
								[](https://www.npmjs.com/package/css-box-model)
							 | 
						||
| 
								 | 
							
								[](https://www.npmjs.com/package/css-box-model)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Any time you are using [`Element.getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) you might want to consider using `css-box-model` instead to get more detailed box model information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Usage
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								// @flow
							 | 
						||
| 
								 | 
							
								import { getBox } from 'css-box-model';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const el: HTMLElement = document.getElementById('foo');
							 | 
						||
| 
								 | 
							
								const box: BoxModel = getBox(el);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// profit
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Installation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								## yarn
							 | 
						||
| 
								 | 
							
								yarn add css-box-model
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# npm
							 | 
						||
| 
								 | 
							
								npm install css-box-model --save
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## The [CSS Box Model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								| Box type    | Composition                         |
							 | 
						||
| 
								 | 
							
								| ----------- | ----------------------------------- |
							 | 
						||
| 
								 | 
							
								| Margin box  | margin + border + padding + content |
							 | 
						||
| 
								 | 
							
								| Border box  | border + padding + content          |
							 | 
						||
| 
								 | 
							
								| Padding box | padding + content                   |
							 | 
						||
| 
								 | 
							
								| Content box | content                             |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This our returned `BoxModel`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								export type BoxModel = {|
							 | 
						||
| 
								 | 
							
								  // content + padding + border + margin
							 | 
						||
| 
								 | 
							
								  marginBox: Rect,
							 | 
						||
| 
								 | 
							
								  // content + padding + border
							 | 
						||
| 
								 | 
							
								  borderBox: Rect,
							 | 
						||
| 
								 | 
							
								  // content + padding
							 | 
						||
| 
								 | 
							
								  paddingBox: Rect,
							 | 
						||
| 
								 | 
							
								  // content
							 | 
						||
| 
								 | 
							
								  contentBox: Rect,
							 | 
						||
| 
								 | 
							
								  // for your own consumption
							 | 
						||
| 
								 | 
							
								  border: Spacing,
							 | 
						||
| 
								 | 
							
								  padding: Spacing,
							 | 
						||
| 
								 | 
							
								  margin: Spacing,
							 | 
						||
| 
								 | 
							
								|};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Supporting types
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This is an extension of DOMRect and ClientRect
							 | 
						||
| 
								 | 
							
								export type Rect = {|
							 | 
						||
| 
								 | 
							
								  // ClientRect
							 | 
						||
| 
								 | 
							
								  top: number,
							 | 
						||
| 
								 | 
							
								  right: number,
							 | 
						||
| 
								 | 
							
								  bottom: number,
							 | 
						||
| 
								 | 
							
								  left: number,
							 | 
						||
| 
								 | 
							
								  width: number,
							 | 
						||
| 
								 | 
							
								  height: number,
							 | 
						||
| 
								 | 
							
								  // DOMRect
							 | 
						||
| 
								 | 
							
								  x: number,
							 | 
						||
| 
								 | 
							
								  y: number,
							 | 
						||
| 
								 | 
							
								  // Rect
							 | 
						||
| 
								 | 
							
								  center: Position,
							 | 
						||
| 
								 | 
							
								|};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export type Position = {|
							 | 
						||
| 
								 | 
							
								  x: number,
							 | 
						||
| 
								 | 
							
								  y: number,
							 | 
						||
| 
								 | 
							
								|};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export type Spacing = {
							 | 
						||
| 
								 | 
							
								  top: number,
							 | 
						||
| 
								 | 
							
								  right: number,
							 | 
						||
| 
								 | 
							
								  bottom: number,
							 | 
						||
| 
								 | 
							
								  left: number,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## API
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `getBox`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> (el: HTMLElement) => BoxModel
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Use `getBox` to return the box model for an element
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `withScroll`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> `(original: BoxModel, scroll?: Position = getWindowScroll()) => BoxModel`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This is useful if you want to know the box model for an element relative to a page
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const el: HTMLElement = document.getElementById('app');
							 | 
						||
| 
								 | 
							
								const box: BoxModel = getBox(el);
							 | 
						||
| 
								 | 
							
								const withScroll: BoxModel = withScroll(box);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You are welcome to pass in your own `scroll`. By default we we use the window scroll:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const getWindowScroll = (): Position => ({
							 | 
						||
| 
								 | 
							
								  x: window.pageXOffset,
							 | 
						||
| 
								 | 
							
								  y: window.pageYOffset,
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `calculateBox`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> `(borderBox: AnyRectType, styles: CSSStyleDeclaration) => BoxModel`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This will do the box model calculations without needing to read from the DOM. This is useful if you have already got a `ClientRect` / `DOMRect` and a `CSSStyleDeclaration` as then we can skip computing these values.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const el: HTMLElement = document.getElementById('app');
							 | 
						||
| 
								 | 
							
								const borderBox: ClientRect = el.getBoundingClientRect();
							 | 
						||
| 
								 | 
							
								const styles: CSSStyleDeclaration = window.getComputedStyles(el);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const box: BoxModel = calculateBox(borderBox, styles);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								**`AnyRectType`** allows for simple interoperability with any rect type
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								type AnyRectType = ClientRect | DOMRect | Rect | Spacing;
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `createBox`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> `({ borderBox, margin, border, padding }: CreateBoxArgs) => BoxModel`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Allows you to create a `BoxModel` by passing in a `Rect` like shape (`AnyRectType`) and optionally your own `margin`, `border` and or `padding`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								type CreateBoxArgs = {|
							 | 
						||
| 
								 | 
							
								  borderBox: AnyRectType,
							 | 
						||
| 
								 | 
							
								  margin?: Spacing,
							 | 
						||
| 
								 | 
							
								  border?: Spacing,
							 | 
						||
| 
								 | 
							
								  padding?: Spacing,
							 | 
						||
| 
								 | 
							
								|};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const borderBox: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 10,
							 | 
						||
| 
								 | 
							
								  right: 100,
							 | 
						||
| 
								 | 
							
								  left: 20,
							 | 
						||
| 
								 | 
							
								  bottom: 80,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								const padding: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 10,
							 | 
						||
| 
								 | 
							
								  right: 20,
							 | 
						||
| 
								 | 
							
								  left: 20,
							 | 
						||
| 
								 | 
							
								  bottom: 10,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const box: BoxModel = createBox({ borderBox, padding });
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Utility API
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> Functions to help you interact with the objects we provide
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `getRect`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> `(spacing: AnyRectType) => Rect`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Given any `Rect` like shape, return a `Rect`. Accepts any object that has `top`, `right`, `bottom` and `right` (eg `ClientRect`, `DOMRect`);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const spacing: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 0,
							 | 
						||
| 
								 | 
							
								  right: 100,
							 | 
						||
| 
								 | 
							
								  bottom: 50,
							 | 
						||
| 
								 | 
							
								  left: 50,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const rect: Rect = getRect(spacing);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								console.log(rect);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  top: 0,
							 | 
						||
| 
								 | 
							
								  right: 100,
							 | 
						||
| 
								 | 
							
								  bottom: 50,
							 | 
						||
| 
								 | 
							
								  left: 50,
							 | 
						||
| 
								 | 
							
								  width: 100,
							 | 
						||
| 
								 | 
							
								  height: 50,
							 | 
						||
| 
								 | 
							
								  x: 0,
							 | 
						||
| 
								 | 
							
								  y: 0,
							 | 
						||
| 
								 | 
							
								  center: { x: 50, y: 50 },
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `expand`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Used to expand a `Spacing`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								(target: Spacing, expandBy: Spacing) => Spacing;
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const original: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 10,
							 | 
						||
| 
								 | 
							
								  left: 11,
							 | 
						||
| 
								 | 
							
								  right: 21,
							 | 
						||
| 
								 | 
							
								  bottom: 22,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const expandBy: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 1,
							 | 
						||
| 
								 | 
							
								  left: 2,
							 | 
						||
| 
								 | 
							
								  right: 3,
							 | 
						||
| 
								 | 
							
								  bottom: 4,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const expanded: Spacing = expand(original, expandBy);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								console.log(expanded);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // pulled back
							 | 
						||
| 
								 | 
							
								  top: 8,
							 | 
						||
| 
								 | 
							
								  left: 8
							 | 
						||
| 
								 | 
							
								  // pushed forward
							 | 
						||
| 
								 | 
							
								  bottom: 22,
							 | 
						||
| 
								 | 
							
								  right: 22,
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### `shrink`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Used to shrink a `Spacing`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								(target: Spacing, shrinkBy: Spacing) => Spacing;
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const original: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 10,
							 | 
						||
| 
								 | 
							
								  left: 10,
							 | 
						||
| 
								 | 
							
								  right: 20,
							 | 
						||
| 
								 | 
							
								  bottom: 20,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const shrinkBy: Spacing = {
							 | 
						||
| 
								 | 
							
								  top: 2,
							 | 
						||
| 
								 | 
							
								  left: 2,
							 | 
						||
| 
								 | 
							
								  right: 2,
							 | 
						||
| 
								 | 
							
								  bottom: 2,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const smaller: Spacing = shrink(original, shrinkBy);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								console.log(smaller);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // pushed forward
							 | 
						||
| 
								 | 
							
								  top: 12,
							 | 
						||
| 
								 | 
							
								  left: 12
							 | 
						||
| 
								 | 
							
								  // pulled back
							 | 
						||
| 
								 | 
							
								  bottom: 18,
							 | 
						||
| 
								 | 
							
								  right: 18,
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								```
							 |