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.
290 lines
6.0 KiB
290 lines
6.0 KiB
# `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). |
|
|
|
[![Build Status](https://travis-ci.org/alexreardon/css-box-model.svg?branch=master)](https://travis-ci.org/alexreardon/css-box-model) |
|
[![npm](https://img.shields.io/npm/v/css-box-model.svg)](https://www.npmjs.com/package/css-box-model) |
|
[![dependencies](https://david-dm.org/alexreardon/css-box-model.svg)](https://david-dm.org/alexreardon/css-box-model) |
|
[![Downloads per month](https://img.shields.io/npm/dm/css-box-model.svg)](https://www.npmjs.com/package/css-box-model) |
|
[![min](https://img.shields.io/bundlephobia/min/css-box-model.svg)](https://www.npmjs.com/package/css-box-model) |
|
[![minzip](https://img.shields.io/bundlephobia/minzip/css-box-model.svg)](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) |
|
|
|
![the box model](https://user-images.githubusercontent.com/2182637/46847224-f8a23e80-ce2e-11e8-80d6-0ca62a1871a7.png) |
|
|
|
| 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, |
|
} |
|
*/ |
|
```
|
|
|