{"id":15543839,"url":"https://github.com/lolmaus/ember-element-query","last_synced_at":"2025-08-01T20:33:24.322Z","repository":{"id":8313862,"uuid":"57958455","full_name":"lolmaus/ember-element-query","owner":"lolmaus","description":"Element queries for Ember","archived":false,"fork":false,"pushed_at":"2023-10-22T17:24:41.000Z","size":9073,"stargazers_count":38,"open_issues_count":22,"forks_count":6,"subscribers_count":2,"default_branch":"gen-4","last_synced_at":"2025-07-31T10:43:32.594Z","etag":null,"topics":["element-queries","element-query","ember-addon"],"latest_commit_sha":null,"homepage":"https://lolmaus.github.io/ember-element-query/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lolmaus.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-03T09:43:55.000Z","updated_at":"2025-07-01T08:16:31.000Z","dependencies_parsed_at":"2024-10-23T00:30:11.369Z","dependency_job_id":null,"html_url":"https://github.com/lolmaus/ember-element-query","commit_stats":{"total_commits":65,"total_committers":4,"mean_commits":16.25,"dds":0.06153846153846154,"last_synced_commit":"076ce196f15d3bfa8d2ce41bf340db9c97050e4d"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/lolmaus/ember-element-query","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lolmaus%2Fember-element-query","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lolmaus%2Fember-element-query/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lolmaus%2Fember-element-query/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lolmaus%2Fember-element-query/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lolmaus","download_url":"https://codeload.github.com/lolmaus/ember-element-query/tar.gz/refs/heads/gen-4","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lolmaus%2Fember-element-query/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268291400,"owners_count":24226858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["element-queries","element-query","ember-addon"],"created_at":"2024-10-02T12:28:36.393Z","updated_at":"2025-08-01T20:33:24.200Z","avatar_url":"https://github.com/lolmaus.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"ember-element-query ![npm version](https://img.shields.io/npm/v/ember-element-query) [![CI](https://github.com/lolmaus/ember-element-query/actions/workflows/ci.yml/badge.svg)](https://github.com/lolmaus/ember-element-query/actions/workflows/ci.yml) \u003c!-- omit in toc --\u003e\n===================\n\n* Use element queries effortlessly on any element or component.\n* Use it in the form of the `{{element-query}}` modifier or the `\u003cElementQuery as |EQ|\u003e` component.\n* Apply styles that respond based on element's own width rather than viewport width.\n* Do CSS transforations and template transformations.\n\nElement queries are [a technique](https://www.smashingmagazine.com/2016/07/how-i-ended-up-with-element-queries-and-how-you-can-use-them-today/) to do responsive transformations based on element's own size rather than viewport size.\n\nIt lets you implement reusable responsive components — with encapsulated styles, decoupled from their parent context. Such components will realign their content depending on how much space is available to them.\n\nFor example, if you put a responsive component into a tight sidebar, it will align its content vertically. When the sidebar expands, the component will realign horizontally in order to efficiently use available space.\n\nHere's a biased comparison table with competing addons (as of 2021.08):\n\n|                                                    | ember-element-query | [ember-fill-up](https://github.com/chadian/ember-fill-up/) | [ember-container-query](https://github.com/ijlee2/ember-container-query/) |\n| -------------------------------------------------- | :-----------------: | :--------------------------------------------------------: | :-----------------------------------------------------------------------: |\n| Octane                                             | ✔                  | 🚫                                                         | ✔                                                                         |\n| [ResizeObserver](https://web.dev/resize-observer/) | ✔                  | ✔                                                          | 🚫                                                                        |\n| Offers a modifier                                  | ✔                  | 🚫                                                         | 🚫                                                                        |\n| Offers a component                                 | ✔                  | ✔                                                         | ✔                                                                        |\n| Actively maintained                                | ✔                  | 🚫                                                         | ✔                                                                        |\n| API convenience                                    | ⭐⭐⭐⭐⭐        | ⭐⭐⭐⭐                                                | ⭐⭐⭐⭐                                                                        |\n\nSee [detailed comparison](#comparison) with code samples.\n\n***\n\n- [Demo](#demo)\n- [API Docs](#api-docs)\n- [Roadmap](#roadmap)\n- [Rationale](#rationale)\n- [Concept of sizes](#concept-of-sizes)\n- [How ember-element-query works](#how-ember-element-query-works)\n  - [Using attributes in CSS](#using-attributes-in-css)\n  - [Edge cases](#edge-cases)\n  - [⚠ Use in compound selectors only!](#-use-in-compound-selectors-only)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [As a modifier](#as-a-modifier)\n  - [As a component](#as-a-component)\n- [Advanced usage](#advanced-usage)\n  - [onResize callback](#onresize-callback)\n  - [Custom sizes](#custom-sizes)\n  - [Using height](#using-height)\n  - [Using aspect ratio](#using-aspect-ratio)\n  - [Opting out of width attributes](#opting-out-of-width-attributes)\n  - [Customizing attribute prefix](#customizing-attribute-prefix)\n  - [Using multiple modifiers on the same element](#using-multiple-modifiers-on-the-same-element)\n  - [Disabling](#disabling)\n  - [Customizing component element](#customizing-component-element)\n  - [Debouncing](#debouncing)\n  - [CSS fallback](#css-fallback)\n  - [FastBoot fallback](#fastboot-fallback)\n- [Browser support](#browser-support)\n- [Alternatives](#alternatives)\n  - [Comparison](#comparison)\n    - [Defining custom rules rules, using template and CSS transformations](#defining-custom-rules-rules-using-template-and-css-transformations)\n    - [Using default rule definitions](#using-default-rule-definitions)\n    - [Customizing element tag while doing template transformations](#customizing-element-tag-while-doing-template-transformations)\n    - [Customizing element tag while doing pure CSS transformations](#customizing-element-tag-while-doing-pure-css-transformations)\n    - [Using directly on images and other void elements](#using-directly-on-images-and-other-void-elements)\n    - [Using both width and height in a rule for template transformation](#using-both-width-and-height-in-a-rule-for-template-transformation)\n- [Contributing](#contributing)\n  - [Tools](#tools)\n  - [Installation](#installation-1)\n  - [Linting](#linting)\n  - [Running tests](#running-tests)\n  - [Running the dummy application](#running-the-dummy-application)\n- [License](#license)\n- [Credit](#credit)\n\n\n\nDemo\n--------\n\nhttps://lolmaus.github.io/ember-element-query/\n\nThis addon's demo is borrowed from [ember-container-query](https://github.com/ijlee2/ember-element-query) per [@ijlee2](https://www.linkedin.com/in/ijlee2/)'s generous permission.\n\n\n\nAPI Docs\n--------\n\nhttps://lolmaus.github.io/ember-element-query/api/\n\n\n\n\nRoadmap\n-------\n\nThis addon is ~~in active development~~ complete! 🎉\n\n* [x] `{{element-query}}` modifier\n  * [x] Exists\n  * [x] Sets up a `ResizeObserver`\n  * [x] Calls the `onResize` callback with params\n  * [x] Applies attributes to elements\n  * [x] Accepts `sizes`\n  * [x] Accepts `sizesHeight`\n  * [x] Accepts `sizesRatio`\n  * [x] Accepts `prefix`\n  * [x] Updates on arugments change\n  * [x] Add fool-proof exceptions\n  * [x] Disabling\n  * [x] Applying a general `[eq]` attribute \n* [x] `\u003cElementQuery\u003e` component\n  * [x] Exists\n  * [x] Applies attributes to itself\n  * [x] Calls the `onResize` callback with params\n  * [x] Yields block params\n  * [x] Accepts `sizes`\n  * [x] Accepts `sizesHeight`\n  * [x] Accepts `sizesRatio`\n  * [x] Accepts `prefix`\n  * [x] Accepts `tagName`\n  * [x] Disabling\n* [x] Expose types\n* [x] CI\n* [x] npm package\n* [x] Documentation\n  * [x] Concept\n  * [x] Feature description\n  * [x] Usage\n  * [x] Browser support\n  * [x] Comparison with alternatives\n  * [x] TypeDoc API documentation\n    * [x] Document\n    * [x] Set up auto deployment\n* [x] Demo app\n\n\nRationale\n---------\n\nCSS media queries have a few disadvantages:\n\n* They account for scrollbar width. On OSes with a scrollbar such as Windows and Linux, available document width is some 15px smaller than the one detected by a media query. Resulting styles are slightly inconsistent across OSes.\n* They are designed for creating responsive layouts, whereas making responsive *components* is unreasonably hard:\n  * If your responsive component appears in different contexts, you have to define media queries separately for each context and make sure they don't overlap.\n  * If you want to make your responsive component reusable, you can't apply responsive styles directly to it because you don't know all the contexts it might be used in. Instead, you have to offer the styles as preprocessor mixins or CSS snippets, for the consuming app developer to apply them by hand in every context.\n  * Responsive components put into dynamic contexts (such as collapsible sidebars, grids, other responsive components, etc) require *lots* of media queries, which involve unreasonably complicated math. Check out [this old demo](https://lolmaus.github.io/a-tale-of-media-queries/) for a rationale.\n\nAll those problems wouldn't exist if we were able to apply styles conditionally based on element's own width:\n\n```css\n/* Hypothetical sample. I wish these were possible, but alas! */\n\n/* When .my-menu is \u003c= 499px, apply margin-bottom to .my-menu--item */\n.my-menu:max-width(499px) .my-menu--item {\n  margin-bottom: 10px;\n}\n\n/* When .my-menu is \u003e= 500px, apply flex to it */\n.my-menu:min-width(500px) {\n  display: flex;\n}\n\n/* When .my-menu is \u003e= 500px, apply margin-right to .my-menu--item */\n.my-menu:min-width(500px) .my-menu--item {\n  margin-right: 10px;\n}\n```\n\nUnfortunately, CSS is not aware of element's current width, so pseudoselectors like `:min-width(500px)` are impossible... unless you use a tool like `ember-element-query`.\n\n\n\nConcept of sizes\n----------------\n\n`ember-element-query` operates with *sizes*. \"Sizes\" are like T-shirt sizes, except they indicate element width.\n\nThe default sizes scale is:\n\n    Breakpoints:  0       200px     400px     600px     800px     1000px    1200px    1400px  \n                  ├─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────\u003e\n    Sizes:        ·   xxs   ·    xs   ·    s    ·    m    ·    l    ·    xl   ·   xxl   ·   xxxl   \n\nThe left limit of each size range is inclusive, the right limit is non-inclusive.\n\nFor example, an element is considered to be of size `m` when its width is `\u003e= 600px` and `\u003c 800px`.\n\nHere's an explicit sizes chart:\n\n    Breakpoints:  0       200px     400px     600px     800px     1000px    1200px    1400px  \n                  ├─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────\u003e\n    Sizes:        ·   xxs   ·    xs   ·    s    ·    m    ·    l    ·    xl   ·   xxl   ·   xxxl   \n                  ·         ·         ·         ·         ·         ·         ·         ·\n        xxs       │         ·         ·         ·         ·         ·         ·         ·\n        0—199     ├────────┤·         ·         ·         ·         ·         ·         ·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        xs        ├─────────┤         ·         ·         ·         ·         ·         ·\n        200—399   ├──────────────────┤·         ·         ·         ·         ·         ·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        s         ├───────────────────┤         ·         ·         ·         ·         ·\n        400—599   ├────────────────────────────┤·         ·         ·         ·         ·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        m         ├─────────────────────────────┤         ·         ·         ·         ·\n        600—799   ├──────────────────────────────────────┤·         ·         ·         ·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        l         ├───────────────────────────────────────┤         ·         ·         ·\n        800—999   ├────────────────────────────────────────────────┤·         ·         ·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        xl        ├─────────────────────────────────────────────────┤         ·         ·\n        1000—1199 ├──────────────────────────────────────────────────────────┤·         ·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        xxl       ├───────────────────────────────────────────────────────────┤         ·\n        1200—1399 ├────────────────────────────────────────────────────────────────────┤·\n                  ·         ·         ·         ·         ·         ·         ·         ·\n        xxxl      ├─────────────────────────────────────────────────────────────────────┤\n        1400+     ├──────────────────────────────────────────────────────────────────────────\u003e\n\n\n\nHow ember-element-query works\n-----------------------------\n\n`ember-element-query` applies HTML attributes to an element indicating its current size.\n\nThere are three types of attributes, all of them are applied at once:\n\n* `at-\u003csize\u003e` attribute is applied with element's current size.\n  \n    For example, an element with width of `764px` will receive an  `at-m` attribute.\n\n* `from-\u003csize\u003e` attributes are applied with element's current size and all smaller sizes.\n  \n    For example, an element with width of `764px` will receive attributes `from-xxs`, `from-xs`, `from-s` and `from-m`.\n\n* `to-\u003csize\u003e` attributes are applied with element's current size and all larger sizes.\n  \n    For example, an element with width of `764px` will receive attributes `to-m`, `to-l`, `to-xxl` and `to-xxxl`.\n\nDon't feel confused! This is very simple:\n\n* When you want say \"when my element is of *size M*\", use the `at-m` attribute.\n* When you want say \"when my element is of *size M or larger*\", use the `from-m` attribute.\n* When you want say \"when my element is of *size M or small*\", use the `to-m` attribute.\n\n\n\n### Using attributes in CSS\n\nIn order to do responsive CSS transformations, use attributes like this:\n\n```css\n.foo[at-xxs] {\n  /* These styles when be applied when the element has exactly the size of `xxs`, namely 0—199 px. */\n}\n\n.foo[from-xs] {\n  /* These styles when be applied when the element has the size of `xxs` or larger, namely 200+ px. */\n}\n\n.foo[to-xl] {\n  /* These styles when be applied when the element has the size of `xl` or smaller, namely 0—1199 px. */\n}\n\n.foo[from-s][to-l] {\n  /* These styles when be applied when the element has the size between `s` and `l` inclusively, namely 400—999 px. */\n}\n```\n\nResponsive template transformations are also possible, [see below](#as-a-component).\n\n\n\n\n### Edge cases\n\nNote that some attribute usages don't make much sense:\n\n* The smallest `from-` and the largest `to-` attribute are applied at all times, thus `.foo[from-xxs]` and `.foo[to-xxxl]` selectors are both equivalent to simply `.foo`.\n* `.foo[to-xxs]` is equivalent to `.foo[at-xxs]`, and `.foo[from-xxxl]` is equivalent to `.foo[at-xxxl]`.\n* `.foo[from-m][to-m]` is equivalent to `.foo[at-m]`.\n\n\n\n### ⚠ Use in compound selectors only!\n\nAttribute selectors in CSS should **only** be used in conjunction with semantic selectors.\n\nThe following usage will mess up you website/app:\n\n```css\n/* Never do this! */\n[at-m] {\n  float: left;\n}\n\n/* Still quite bad */\naside[at-m] {\n  float: left;\n}\n\n/* OK */\n.my-side-block[at-m] {\n  float: left;\n}\n```\n\n\n\nInstallation\n------------\n\nUse `ember-cli` to install the addon as usual:\n\n    ember i ember-element-query\n\nThis addon does not do anything on install, so it can alternatively be installed with npm:\n\n    npm i -D ember-element-query\n\n...or Yarn:\n\n    yarn add -D ember-element-query\n\n\n\nUsage\n-----\n\n### As a modifier\n\nUsing the modifier is preferred if you only do **CSS transformations**, which is recommended according to the Responsiv Web Design doctrine.\n\nSimply apply the `{{element-query}}` modifier to any element or angle bracket component like this:\n\n```hbs\n\u003cimg {{element-query}}\u003e\n```\n\nAs a result, element query attributes will be applied to the element. The result could look like this:\n\n```hbs\n\u003cimg at-m from-xxs from-xs from-s from-m to-m to-l to-xl to-xxl to-xxxl\u003e\n```\n\n\n\n### As a component\n\nThe component is useful when you need to do **template transformations**.\n\nIf you want to render chunks of template conditionally, use this syntax:\n\n```hbs\n\u003cElementQuery as |EQ|\u003e\n  {{#if EQ.at-m}}\n    {{! This will only be rendered when the `\u003cElementQuery\u003e` component is of size `m`. }}\n  {{/if}}\n\n  {{#if EQ.from-m}}\n    {{! This will only be rendered when the `\u003cElementQuery\u003e` component is of size `m` or larger. }}\n  \u003c/EQ.from-m\u003e\n\n  {{#if EQ.to-m}}\n    {{! This will only be rendered when the `\u003cElementQuery\u003e` component is of size `m` or smaller. }}\n  {{/EQ.to-m}}\n\n  {{#if (and EQ.from-s EQ.to-l)}}\n    {{! This will only be rendered when the `\u003cElementQuery\u003e` component is of size `s`, `m` or `l`. }}\n  {{/if}}\n\u003c/ElementQuery\u003e\n```\n\nThe first yield argument `EQ` is an object with current element query attributes. Keys are attribute names and values are `true`. Non-matching attributes are undefined. Thus,  `{{#if EQ.from-m}}` renders only when the element is of size `m` or larger.\n\nThe second argument `EQInfo` is the same object that is passed to the [onResize callback](#onresize-callback) described below.\n\n\n\nAdvanced usage\n--------------\n\n### onResize callback\n\nYou can pass a callback to the `onResize` argument and it will be called whenever the element resizes:\n\n```js\n@action\nreportResize(eqInfo) {\n  eqInfo.element          // =\u003e current element\n  eqInfo.width            // =\u003e current element's width in px (number)\n  eqInfo.height           // =\u003e current element's height in px (number)\n  eqInfo.ratio            // =\u003e current element's aspect ratio (width/height, number)\n  eqInfo.size             // =\u003e current element's width size name (string or undefined)\n  eqInfo.sizeHeight       // =\u003e current element's height size name (string or undefined)\n  eqInfo.sizeRatio        // =\u003e current element's aspect ratio size name (string or undefined)\n  eqInfo.prefix           // =\u003e current prefix (string or undefined)\n  eqInfo.attributes       // =\u003e matching element query attributes in array form: ['from-xxs', 'from-xs', ...]\n  eqInfo.attributesRecord // =\u003e matching element query attributes in object form: {'from-xxs': true, 'from-xs': true, ...}\n                          //    non-matching attributes are not defined on the object\n}\n```\n\n```hbs\n\u003cimg {{element-query onResize=this.reportResize}}\u003e\n```\n\n```hbs\n\u003cElementQuery @onResize={{this.reportResize}}\u003e\u003c/ElementQuery\u003e\n```\n\n\n\n### Custom sizes\n\nYour tailored visual designs might require component switching layouts at specific breakpoints, different from this addon's defaults.\n\nYou can override the defaults with the `sizes` argument. It receives a plain object where keys are breakpoint names and arguments are numbers representing width.\n\n⚠ One of the numbers **must** be 0, otherwise the addon will crash your app.\n\n```hbs\n\u003cimg\n  {{element-query\n    sizes=(hash\n      small=0\n      medium=350\n      large=700\n    )\n  }}\n\u003e\n```\n\n```hbs\n\u003cElementQuery\n  @sizes={{hash\n    small=0\n    medium=350\n    large=700\n  }}\n\u003e\n\u003c/ElementQuery\u003e\n```\n\nThe above example defines sizes like this:\n\n* `small`: 0—349 px,\n* `medium`: 350—699 px,\n* `large`: 700+ px.\n\nWhen the element has the width of `421px`, it will receive attributes `at-medium`, `from-medium`, `to-medium`, `from-small` and `to-large`. (Confused? [See above](#how-ember-element-query-works).)\n\n\n\n### Using height\n\nBy default, only attributes for horizontal sizes are applied to your element.\n\nIf you want to use attributes for vertical sizes, set `sizesHeight` to `true`:\n\n```hbs\n\u003cimg {{element-query sizesHeight=true}}\u003e\n```\n\n```hbs\n\u003cElementQuery @sizesHeight={{true}}\u003e\u003c/ElementQuery\u003e\n```\n\nEnabling `heightSizes` will cause two sets of attributes to be applied: width and height. Attributes representing width sizes will be the same as [usual](#concept-of-sizes). Attributes representing height sizes will be postfixed with `-height`: `xxs-height`, `xl-height`, etc.\n\nThis lets you apply CSS like this:\n\n```css\n.foo[to-s][from-xl-height] {\n  /* I am thin and tall */\n}\n```\n\nYou can customize height sizes by passing a hash to `@sizesHeight`. Make sure that height size names are different from width sizes!\n\n```hbs\n\u003cdiv\n  {{element-query\n    sizesHeight=(hash small-height=0 medium-height=200 large-height=400)\n  }}\n\u003e\n\u003c/div\u003e\n```\n\n```hbs\n\u003cElementQuery\n  @sizesHeight={{hash small-height=0 medium-height=200 large-height=400}}\n  as |EQ|\n\u003e\n  {{#if (and EQ.to-small-width EQ.from-large-height)}}\n    I am thin and tall.\n  {{/if}}\n\u003c/ElementQuery\u003e\n```\n\nOf course, you can customize both `sizes` and `sizesHeight` at the same time if you need.\n\n\n\n### Using aspect ratio\n\nBy default, only attributes for horizontal sizes are applied to your element.\n\nIf you want to use attributes for aspect ratio sizes, set `sizesRatio` to `true`:\n\n```hbs\n\u003cimg {{element-query sizesRatio=true}}\u003e\n```\n\n```hbs\n\u003cElementQuery @sizesRatio={{true}}\u003e\u003c/ElementQuery\u003e\n```\n\nBy default, the following definition of aspect ratio sizes is used:\n\n```js\n{\n  'very-tall': 0,\n  'tall':      0.5,\n  'squarish':  0.8,\n  'wide':      1.2,\n  'very-wide': 1.5,\n}\n```\n\nNote that while width and height use whole number of CSS pixels, ratios use fractions. For example, an element with the size of `1920×1080` will have an aspect ratio of `1.777...`, which correpsonds to the `very-wide` ratio size.\n\nYou can customize ratio sizes by passing a hash to `@sizesRatio`. Make sure that aspect ratio size names are different from width and height sizes!\n\n```hbs\n\u003cdiv\n  {{element-query\n    sizesRatio=(hash horizontal=0 square=1 vertical=1.0001)\n  }}\n\u003e\n\u003c/div\u003e\n```\n\n```hbs\n\u003cElementQuery\n  @sizesRatio={{hash horizontal=0 square=1 vertical=1.0001}}\n  as |EQ|\n\u003e\n  {{#if (EQ.at-square)}}\n    I am precisely* square.\n  {{/if}}\n\u003c/ElementQuery\u003e\n```\n\n\\* Mind that comparison of fractional numbers is not absolutely accurate in JavaScript. Aspect ratio sizes are supposed to represent ranges of aspect ratios, not individual aspect ratios. Aiming at a specicific aspect ratio (like in example above) may be inconsistent.\n\n\n\n\n### Opting out of width attributes\n\nBy default, default width attributes are applied to your element unless the `sizes` is overridden.\n\nIf you want no width attributes to be applied, pass a falsy value into `sizes`.\n\nUsing height without width:\n\n```hbs\n\u003cimg {{element-query sizes=false sizesHeight=true}}\u003e\n```\n\n```hbs\n\u003cElementQuery @sizes=null @sizesHeight=true\u003e\u003c/ElementQuery\u003e\n```\n\nUsing no attributes at all:\n\n```hbs\n\u003cimg {{element-query sizes=null}}\u003e\n```\n\n```hbs\n\u003cElementQuery @sizes=false\u003e\u003c/ElementQuery\u003e\n```\n\nThe above will make it impossible to apply CSS or HTML transformations based on sizes. But the following features will still work:\n\n* The `onResize` callback will be called with an object containing current width, height and aspect ratio of the element.\n* The `\u003cElementQuery\u003e` component will yield an object containing current width, height and aspect ratio of the element.\n* The `eq` attribute will still be applied to the element. This hapens when the element query triggers for the first time.\n\n\n\n### Customizing attribute prefix\n\nUse the `prefix` argument to adjust attribute prefix:\n\n```hbs\n\u003cimg {{element-query prefix=\"data-foo-\"}}\u003e\n```\n\n```hbs\n\u003cElementQuery @prefix=\"data-foo-\"\u003e\u003c/ElementQuery\u003e\n```\n\nThis will result in attributes like `data-foo-at-xl`, `data-foo-from-m`, etc.\n\n\n\n### Using multiple modifiers on the same element\n\nOne use case for this is to apply new styles based on new breakpoints without breaking (and refactoring) existing styles.\n\nYou can use both width and height element queries on the same element like this:\n\n```hbs\n\u003cimg\n  class=\"foo\"\n  {{element-query}}\n  {{element-query sizes=(new-small=0 new-large=700)}}\n\u003e\n```\n\nor\n\n```hbs\n\u003cimg\n  class=\"foo\"\n  {{element-query}}\n  {{element-query prefix=\"new-\"}}\n\u003e\n```\n\n⚠ The `{{element-query}}` modifier adds and removes attributes aggressively and will interfere with other modifiers/libraries manipulating same attributes. It is your duty to ensure there is no conflict in attribute names. Adjust `sizes`, `sizesHeight` and `prefix` arguments to avoid conflicts.\n\n\n\n### Disabling\n\nPass a truthy value into `isDisabled` to disable element query functionality:\n\n```hbs\n\u003cimg\n  {{element-query isDisabled=true}}\n\u003e\n```\n\n```hbs\n\u003cElementQuery\n  @isDisabled={{true}}\n\u003e\n\u003c/ElementQuery\u003e\n```\n\n⚠ This property is intended for debugging purposes or disabling element queries entirely. If you change `isDisabled` to `true` dynamically, element query attributes will freeze in their current state. There is no cleanup.\n\n\n\n### Customizing component element\n\nThe `\u003cElementQuery\u003e` component accepts a `@tagName` argument that allows tweaking the component's root tag:\n\n```hbs\n\u003cElementQuery @tagName=\"img\" src=\"https://i.imgur.com/iP9xl86.gif\" alt=\"A handsome person\"/\u003e\n```\n\nThis wouuld result in the followingg HTML rendered (element query tags not shown):\n\n```hbs\n\u003cimg src=\"https://i.imgur.com/iP9xl86.gif\" alt=\"A handsome person\"\u003e\n```\n\n\n\n### Debouncing\n\nUse the `debounce` argument to set a limit to how frequently attributes recalculate and the `onResize` callback is called while the window is being continuously resized.\n\nIt accepts a number of milliseconds and defaults to `100`. This means that the refresh will be happening at a rate of 10 times per second (1000 / 100 = 10).\n\nThis example with refresh once per second:\n\n```hbs\n\u003cimg\n  {{element-query debounce=1000}}\n\u003e\n```\n\n```hbs\n\u003cElementQuery\n  @debounce={{1000}}\n\u003e\n\u003c/ElementQuery\u003e\n```\n\nThis addon uses [window.requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame). Even if you set `debounce` to `0`, the refresh rate will still be limited to either 60 or to the refresh rate of the screen.\n\nIt is not recommended to use a low refresh rate due to possible perormance issues. For example, if you do this:\n\n```hbs\n\u003cimg\n  {{element-query\n    @debounce=0\n    @onResize=this.updateSrc\n  }}\n\u003e\n```\n\n```js\n@service cdn;\n\n@action updateSrc({element, width, height}) {\n  element.src = this.cdn.getImageSrcForSize({width, height});\n}\n```\n\n...then playing with window size for several seconds will cause hundreds or thousands of `src` updates to be queued, which would cause the image to flicker.\n\n\n\n### CSS fallback\n\n⚠ When navigating between routes, there may be a flash of unstyled content: a very short moment when the component is rendered, but its element queries are not applied yet. This happens because  `ember-element-query` addon needs the component to be rendered in order to measure its size, before responsive styles can be applied.\n\nConsider this SCSS. Here we have two layouts: horizontal and vertical.\n\n```scss\n.MyComponent {\n  // This layout will be applied when the element is known to be small.\n  \u0026[to-m] {\n    // Vertical layout. Children should have margins between them.\n    \u003e *:not(:last-child) {\n      margin-bottom: 20px;\n    }\n  }\n\n  // This layout is applied when the element is known to be large.\n  \u0026[from-l] {\n    // Horizontal layout. Children should be positioned in a row.\n    margin-bottom: 20px;\n  }\n}\n```\n\nDuring the flash of unstyled content, neither layout is applied because `ember-element-query` hasn't yet applied its attributes.\n\nThis is suboptimal. Instead, you want one of the layouts to be the default one: applied when element query attributes are unavailable.\n\nFor this use case, when the element's size is first measured, `ember-element-query` applies the `eq` attribute to the element and keeps it forever. Thus, the `:not([eq])` selector matches the element only while element queries have not yet being applied.\n\nIn order to make one of the layouts a default, add `:not([eq])` to its selectors:\n\n```scss\n.MyComponent {\n  // This layout will be applied when the element is known to be small or when its size is unknown.\n  \u0026:not([eq]), \u0026[to-m] {\n    // Vertical layout. Children should have margins between them.\n    \u003e *:not(:last-child) {\n      margin-bottom: 20px;\n    }\n  }\n\n  // This layout is applied when the element is known to be large.\n  \u0026[from-l] {\n    // Horizontal layout. Children should be positioned in a row.\n    margin-bottom: 20px;\n  }\n}\n```\n\nThis would remove the flash of unstyled content at least for some screen sizes.\n\n\n\n### FastBoot fallback\n\nUnfortunately, FastBoot does not have information about user's screen size. When a user vistis a FastBoot-driven website, they initially see a page without any `ember-element-query` attributes. When FastBoot rehydrates, element queries kick in. As a result, page layout may suddenly change after the user has already started reading and scrolling, causing frustration.\n\nOne workaround is to use [ember-useragent](https://github.com/willviles/ember-useragent). Its `isMobile`, `isTablet` and `isDesktop` boolean properties let you apply some defaults. The result is very crude, heuristical — but that's better than nothing.\n\nSince reusable components can be used in different contexts, it is recommended that you apply the fallback on parent level.\n\nResponsive component:\n\n```hbs\n\u003cdiv\n  class=\"my-component\"\n  {{element-querysizes=(hash small=0 medium=350 large=700)}}\n  ...attributes\n\u003e\n\u003c/div\u003e\n```\n\n```css\n.my-component { /*  */}\n.my-component[from-medium] { /*  */ }\n.my-component[from-large] { /*  */ }\n```\n\nParent:\n\n```hbs\n\u003cMyComponent\n  from-medium={{and this.fastboot.isFastBoot (or this.userAgent.device.isTablet this.userAgent.device.isDesktop)}}\n  from-large-={{and this.fastboot.isFastBoot this.userAgent.device.isDeskto)}}\n/\u003e\n```\n\nUnfortunately, this requires the parent to know which attributes are used in component's CSS, since providing all possible attributes would be quite tedious, especially for default sizes, which are numerous.\n\n\n\nBrowser support\n---------------\n\n**IE is not supported** because `ember-element-query` uses modern ECMAScript APIs.\n\n`ember-element-query` is based on the [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) which is also not supported by IE.\n\nAs of 2020-06, `ResizeObserver` supports the following major browsers:\n\n* Chrome: 64+ (since 2018-01-23),\n* Firefox: 69+ (since 2019-09-02, desktop only),\n* Safari: 13.1+ desktop, 13.4+ iOS (since 2020-03-24).\n\nSee [caniuse.com](https://caniuse.com/#feat=resizeobserver) for detailed stats.\n\n⚠ Note that old iOS devices do not have `ResizeObserver` support, so you might want to use a polyfill. *iOS Safari is the new IE. 😬*\n\n\n\nAlternatives\n------------\n\nThere are a few other Ember addons implementing element queries, such as:\n\n* https://github.com/chadian/ember-fill-up/\n* https://github.com/ijlee2/ember-container-query\n\n`ember-element-query` was implemented to offer a simpler API at the cost of being opinionated.\n\nOther addons are full-fledged element query addons that aren't as much opinionated. Their approach is defining rules on element query components. For example, if you want your component to respond to `0—350px`, `350px+`, `350px—699px` and `700px+` — you will need to define four rules on the component. An unexpected challenge is to come up with meaningful names for each range.\n\nEvery time you need another rule, you need to add it on the component before you're able to use it in CSS.\n\nWith `ember-element-query`, you only need to define *breakpoints*. The example above uses only two breakpoints: `350px` and `700px` — and all combinations of rules become available automatically via HTML attributes.\n\n💡 `ember-fill-up` and `ember-container-query` and `ember-element-query` are all full-featured element query addons. `ember-element-query`'s goal is to provide a simpler API, making it more convenient to use. It encourages using pure CSS transformations, accoridng to the Responsive Web Design paradigm, though template transformations are also possible and convenient.\n\n\n\n### Comparison\n\nAs of 2021.08.\n\n#### Defining custom rules rules, using template and CSS transformations\n\nGiven breakpoints 350, 700 and 1050:\n\n* `ember-fill-up`:\n\n    ```hbs\n    \u003cFillUp\n      class=\"my-component\"\n      @breakpoints={{hash\n        small=(fill-up-lt 350)\n        medium=(fill-up-between 350 700)\n        large=(fill-up-between 700 1050)\n        extraLarge=(fill-up-gte 1050)\n\n        mediumAndBigger=(fill-up-gte 350)\n        largeAndBigger=(fill-up-gte 700)\n        mediumAndSmaller=(fill-up-lt 700)\n        largeAndSmaller=(fill-up-lt 1050)\n        \n        mediumToLarge=(fill-up-between 350 1050)\n      }}\n      as |F|\n    \u003e\n      {{#if F.breakpoints.small}}...{{/if}}\n      {{#if F.breakpoints.medium}}...{{/if}}\n      {{#if F.breakpoints.large}}...{{/if}}\n      {{#if F.breakpoints.extraLarge}}...{{/if}}\n\n      {{#if F.breakpoints.mediumAndBigger}}...{{/if}}\n      {{#if F.breakpoints.largeAndBigger}}...{{/if}}\n      {{#if F.breakpoints.mediumAndSmaller}}...{{/if}}\n      {{#if F.breakpoints.largeAndSmaller}}...{{/if}}\n\n      {{#if F.breakpoints.mediumToLarge}}...{{/if}}\n    \u003c/FillUp\u003e\n    ```\n\n    ```css\n    .my-component[fill-up-small] {}\n    .my-component[fill-up-medium] {}\n    .my-component[fill-up-large] {}\n    .my-component[fill-up-extraLarge] {}\n\n    .my-component[fill-up-mediumToLarge] {}\n    .my-component[fill-up-largeAndBigger] {}\n    .my-component[fill-up-mediumAndSmaller] {}\n    .my-component[fill-up-largeAndSmaller] {}\n\n    .my-component[fill-up-mediumToLarge] {}\n    ```\n\n    👆 Note how you need to repeat same breakpoints several times in rule definitions. In order to avoid multiple sources of truth, you could wrap component invocation with `{{let}}`, but that increases the boilerplate.\n\n* `ember-container-query`:\n\n    ```hbs\n    \u003cContainerQuery\n      class=\"my-component\"\n      @features={{hash\n        small=(cq-width max=349)\n        medium=(cq-width min=350 max=699)\n        large=(cq-width min=700 max=1049)\n        extraLarge=(cq-width min=1050)\n\n        mediumAndBigger=(cq-width min=350)\n        largeAndBigger=(cq-width min=700)\n        mediumAndSmaller=(cq-width max=699)\n        largeAndSmaller=(cq-width max=1049)\n        \n        mediumToLarge=(cq-width min=350 max=1049)\n      }}\n      as |CQ|\n    \u003e\n      {{#if CQ.features.small}}...{{/if}}\n      {{#if CQ.features.medium}}...{{/if}}\n      {{#if CQ.features.large}}...{{/if}}\n      {{#if CQ.features.extraLarge}}...{{/if}}\n\n      {{#if CQ.features.mediumAndBigger}}...{{/if}}\n      {{#if CQ.features.largeAndBigger}}...{{/if}}\n      {{#if CQ.features.mediumAndSmaller}}...{{/if}}\n      {{#if CQ.features.largeAndSmaller}}...{{/if}}\n\n      {{#if CQ.features.mediumToLarge}}...{{/if}}\n    \u003c/ContainerQuery\u003e\n    ```\n\n    ```css\n    .my-component[data-container-query-small] {}\n    .my-component[data-container-query-medium] {}\n    .my-component[data-container-query-large] {}\n    .my-component[data-container-query-extraLarge] {}\n\n    .my-component[data-container-query-mediumAndBigger] {}\n    .my-component[data-container-query-largeAndBigger] {}\n    .my-component[data-container-query-mediumAndSmaller] {}\n    .my-component[data-container-query-largeAndSmaller] {}\n\n    .my-component[data-container-query-mediumToLarge] {}\n    ```\n\n    👆 Note how you need to manually account for ±1 error in rule definitions.\n\n* `ember-element-query`:\n\n    ```hbs\n    \u003cElementQuery\n      class=\"my-component\"\n      @sizes={{hash small=0 medium=350 large=700 extraLarge=1050}}\n      as |EQ|\n    \u003e\n      {{#if EQ.at-small}}...{{/if}}\n      {{#if EQ.at-medium}}...{{/if}}\n      {{#if EQ.at-large}}...{{/if}}\n      {{#if EQ.at-extraLarge}}...{{/if}}\n\n      {{#if EQ.from-medium}}...{{/if}}\n      {{#if EQ.from-large}}...{{/if}}\n      {{#if EQ.to-medium}}...{{/if}}\n      {{#if EQ.to-large}}...{{/if}}\n\n      {{#if (and EQ.from-medium EQ.to-large)}}...{{/if}}\n    \u003c/ElementQuery\u003e\n    ```\n\n    ```css\n    .my-component[at-small] {}\n    .my-component[at-medium] {}\n    .my-component[at-large] {}\n    .my-component[at-extraLarge] {}\n\n    .my-component[from-medium] {}\n    .my-component[from-large] {}\n    .my-component[to-medium] {}\n    .my-component[to-large] {}\n\n    .my-component[from-medium][to-large] {}\n    ```\n\n  👆 Note how much shorter the usage is, both in rule definitions and rule applications.\n\n\n\n#### Using default rule definitions\n\n* `ember-fill-up`:\n\n    Does not provide any defaults.\n\n* `ember-container-query`:\n\n    Does not provide any defaults.\n\n* `ember-element-query`:\n\n    Provides [reasonable defaults](#concept-of-sizes).\n    \n    **Those defaults can be used as a common design language, and all components in your app can be using them, reducing the boilerplate to:**\n\n    ```hbs\n    \u003cElementQuery\u003e\u003c/ElementQuery\u003e\n    ```\n\n    or\n\n    ```hbs\n    \u003cdiv {{element-query}}\u003e\u003c/div\u003e\n    ```\n\n\n\n#### Customizing element tag while doing template transformations\n\n* `ember-fill-up`:\n\n    Not supported. Responsive componetns are limited to `\u003cdiv\u003e`.\n\n* `ember-container-query`:\n\n    Uses [ember-element-helper](https://github.com/tildeio/ember-element-helper) as a polyfill for [RFC 389](https://github.com/emberjs/rfcs/blob/master/text/0389-dynamic-tag-names.md) ([tracking](https://github.com/emberjs/rfc-tracking/issues/42)):\n\n    ```hbs\n    \u003cContainerQuery @tagName=\"article\"\u003e\n    \u003c/ContainerQuery\u003e\n    ```\n\n* `ember-element-query`:\n  \n    Uses [ember-element-helper](https://github.com/tildeio/ember-element-helper) as a polyfill for [RFC 389](https://github.com/emberjs/rfcs/blob/master/text/0389-dynamic-tag-names.md) ([tracking](https://github.com/emberjs/rfc-tracking/issues/42)):\n\n    ```hbs\n    \u003cElementQuery @tagName=\"article\"\u003e\n    \u003c/ElementQuery\u003e\n    ```\n\n\n\n#### Customizing element tag while doing pure CSS transformations\n\n* `ember-fill-up`:\n\n    Not supported. Responsive componetns are limited to `\u003cdiv\u003e`.\n\n* `ember-container-query`:\n  \n    Uses [ember-element-helper](https://github.com/tildeio/ember-element-helper) as a polyfill for [RFC 389](https://github.com/emberjs/rfcs/blob/master/text/0389-dynamic-tag-names.md) ([tracking](https://github.com/emberjs/rfc-tracking/issues/42)):\n\n    ```hbs\n    \u003cContainerQuery @tagName=\"article\"\u003e\n    \u003c/ContainerQuery\u003e\n    ```\n\n* `ember-element-query`:\n\n  Naturally:\n\n    ```hbs\n    \u003carticle {{element-query}}\u003e\n    \u003c/article\u003e\n    ```\n\n\n\n#### Using directly on images and other void elements\n\n* `ember-fill-up`:\n\n    Not supported.\n\n    Workaround with two wrapper elements:\n\n    ```hbs\n    \u003cFillUp class=\"wrapper1\" breakpoints=this.rules\u003e\n      \u003cdiv class=wrapper2\u003e\n        \u003cimg class=\"image\" src alt\u003e\n      \u003c/div\u003e\n    \u003c/FillUp\u003e\n    ```\n\n    ```css\n    .wrapper1[fill-up-small]  {\n      opacity: 0.5;\n    }\n    .wrapper1[fill-up-large]  {\n      transform: rotate(5);\n    }\n\n    .wrapper2 {\n      position: relative;\n      padding-top: 56.25%; /* The ratio of the image must be known. Alternatively, the image can be cropped with `object-fit: cover` to arbitrary aspect ratio.*/\n    }\n\n    .wrapper2 .image {\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n    }\n    ```\n\n* `ember-container-query`:\n  \n    Uses [ember-element-helper](https://github.com/tildeio/ember-element-helper) as a polyfill for [RFC 389](https://github.com/emberjs/rfcs/blob/master/text/0389-dynamic-tag-names.md) ([tracking](https://github.com/emberjs/rfc-tracking/issues/42)):\n\n    ```hbs\n    \u003cContainerQuery @tagName=\"img\" src alt/\u003e\n    ```\n\n\n* `ember-element-query`:\n\n    ```hbs\n    \u003cimg {{element-query}} src alt\u003e\n    ```\n\n\n#### Using both width and height in a rule for template transformation\n\n* `ember-fill-up`:\n\n    ```hbs\n    \u003cFillUp\n      class=\"my-component\"\n      @breakpoints={{hash\n        smallWidth=(fill-up-lt 350)\n        mediumWidth=(fill-up-between 350 700)\n        largeWidth=(fill-up-gte 700)\n\n        smallHeight=(fill-up-lt 199 dimension=\"height\")\n        mediumHeight=(fill-up-between 200 399 dimension=\"height\")\n        largeHeight=(fill-up-gte 400 dimension=\"height\")\n      }}\n      as |F|\n    \u003e\n      {{#if (and F.breakpoints.smallWidth F.breakpoints.largeHeight)}}\n        I am thin and tall.\n      {{/if}}\n    \u003c/FillUp\u003e\n    ```\n\n* `ember-container-query`:\n\n    ```hbs\n    \u003cContainerQuery\n      class=\"my-component\"\n      @features={{hash\n        smallWidth=(cq-width max=349)\n        mediumWidth=(cq-width min=350 max=699)\n        largeWidth=(cq-width min=700)\n\n        smallHeight=(cq-height max=199)\n        mediumHeight=(cq-height min=200 max=399)\n        largeHeight=(cq-height min=400)\n      }}\n      as |CQ|\n    \u003e\n      {{#if (and CQ.features.smallWidth CQ.features.largeHeight)}}\n        I am thin and tall.\n      {{/if}}\n    \u003c/ContainerQuery\u003e\n    ```\n\n* `ember-element-query`:\n\n    ```hbs\n    \u003cElementQuery\n      @dimension=\"both\"\n      @sizes={{hash small-width=0 medium-width=350 large-width=700}}\n      @sizesHeight={{hash small-height=0 medium-height=200 large-height=400}}\n      as |EQ|\n    \u003e\n      {{#if (and EQ.to-small-width EQ.from-large-height)}}\n        I am thin and tall.\n      {{/if}}\n    \u003c/ElementQuery\u003e\n    ```\n\n    When usign default sizes, this gets even shorter:\n\n    ```hbs\n    \u003cElementQuery @dimension=\"both\" as |EQ|\u003e\n      {{#if (and EQ.to-s EQ.from-l-height)}}\n        I am thin and tall.\n      {{/if}}\n    \u003c/ElementQuery\u003e\n    ```\n\n\n\nContributing\n------------\n\n### Tools\n\nUse [Volta](https://volta.sh/) and [Yarn](https://yarnpkg.com/).\n\n\n\n### Installation\n\n* `git clone \u003crepository-url\u003e`\n* `cd ember-element-query`\n* `yarn`\n\n\n\n### Linting\n\n* `yarn lint:hbs` — only templates\n* `yarn lint:ts` — only TypeScript compiler (tsc)\n* `yarn lint:eslint` — only ESLint (including Prettier and `typescript-eslint`)\n* `yarn lint` — everything\n\n\n\n### Running tests\n\n* `ember test` – Runs the test suite on the current Ember version\n* `ember test --server` – Runs the test suite in \"watch mode\"\n* `ember try:each` – Runs the test suite against multiple Ember versions\n\n\n\n### Running the dummy application\n\n* `ember serve`\n* Visit the dummy application at [http://localhost:4200](http://localhost:4200).\n\nFor more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/).\n\n\n\nLicense\n-------\n\nThis project is licensed under the [MIT License](LICENSE.md).\n\n\n\nCredit\n------\n\nImplemented by Andrey Mikhaylov ([lolmaus](https://github.com/lolmaus)) and [contributors](https://github.com/lolmaus/ember-element-query/graphs/contributors).\n\nThanks to Chad Carbert ([@chadian](https://github.com/chadian)) and Isaac Lee ([@ijlee2](https://github.com/ijlee2)) for feedback, ideas, brainstorming and criticism.\n\nThis addon's demo is borrowed from [ember-container-query](https://github.com/ijlee2/ember-element-query) per [@ijlee2](https://www.linkedin.com/in/ijlee2/)'s generous permission.\n\nSponsored in part by [@kaliber5](https://github.com/kaliber5), https://kaliber5.de.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flolmaus%2Fember-element-query","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flolmaus%2Fember-element-query","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flolmaus%2Fember-element-query/lists"}