ember-resize-observer-component
A tiny, ResizeObserver-based solution for building components responsive to their container size, rather than the viewport. The idea is to overcome the limitations of viewport-based media queries, and it's known as Container Queries
.
Here is how it can be done, using this addon (controversial example):
<ResizeObserver
@matchers={{hash
width-between-100-300=(hash width-gte=100 width-lte=300)
bigSquare=(hash width-gt=500 height-gt=500 aspectRatio=1)
}}
as |RO|
>
<p class='matchers {{if RO.is.bigSquare 'matchers--square'}}'>
{{if RO.is.width-between-100-300 'Width is between 100px-300px'}}
</p>
{{#if RO.is.bigSquare}}
<p>Big square</p>
{{/if}}
{{#if (gt RO.width 300)}}
<p>Width is greater than 300px</p>
{{/if}}
<p>Width: {{RO.width}}</p>
<p>Height: {{RO.height}}</p>
<p>Aspect Ratio: {{RO.aspectRatio}}</p>
</ResizeObserver>
This addon focuses on simplicity. It only includes a single component and won't do any attributes binding for you. Instead, it provides element's dimensions and easy to use size-matchers
.
Highlights:
- a single component and nothing more
- only provides data (no attributes or class binding)
- supports
no-wrapper
mode - use your element directly - easy to use
size-matchers
- works with FastBoot/SSR
Installation
ember install ember-resize-observer-component
If you need a ResizeObserver polyfill (caniuse.com):
ember install ember-resize-observer-polyfill
Usage
Matcher query syntax
Matchers allow you to map size-related conditions, such as width > 100
, to properties on the object you get from <ResizeObserver />
(e.g. RO.is.large
). And whenever the element's size changes, the relevant properties will update.
In the example below, large
is a matcher name, and (hash width-gte=1200)
represents a condition query.
<ResizeObserver @matchers={{hash large=(hash width-gte=1200)}} as |RO|>
{{if RO.is.large "I'm large!"}}
</ResizeObserver>
Available operators: eq
, gt
, gte
, lt
, lte
(they are similar to ember-truth-helpers)
Available conditions: width
, height
, aspectRatio
.
Note: The addon protects you from mistyping by validating all your matchers and telling you exactly what was wrong with a particular matcher.
Query | JavaScript |
---|
(hash width=10) | width === 10 |
(hash width-gt=10) | width > 10 |
(hash width-gte=10) | width >= 10 |
(hash width-lt=10) | width < 10 |
(hash width-lte=10) | width <= 10 |
Examples with multiple values:
Query | JavaScript |
---|
(hash width=10 height-lt=20) | width === 10 && height < 20 |
(hash width-gt=10 aspectRatio=1) | width > 10 && aspectRatio === 1 |
In no-wrapper
mode, the component won't provide a wrapper element, so you will need to attach onResize
handler to a target element yourself:
<ResizeObserver @noWrapper={{true}} as |RO|>
<div {{on-resize RO.onResize}}>
{{RO.width}}
{{RO.height}}
{{RO.aspectRatio}}
</div>
</ResizeObserver>
You can set initial demensions that will be used if the component can't get element's size, e.g. in FastBoot environment:
<ResizeObserver
@matchers={{hash large=(hash width-gte=1200) square=(hash aspectRatio=1)}}
@defaultWidth={{100}}
@defaultHeight={{100}}
as |RO|
>
{{if RO.is.large 'Large'}}
{{if RO.is.square 'Square'}}
Size:
{{RO.width}}
x
{{RO.height}}
</ResizeObserver>
For more info, please read the tests. The documentation will be improved soon.
Related addons
Alternative solutions worth checking out
Contributing
See the Contributing guide for details.
Compatibility
- Ember.js v3.20 or above
- Ember CLI v3.20 or above
- Node.js v12 or above
License
This project is licensed under the MIT License.