Awesome
Watched Box
Declarative container queries FTW!
A custom element as a ResizeObserver
root. The easiest way to get working with ResizeObserver
and creating container queries with JavaScript. Unlike many implementations, you can use any CSS length units, and mix them together.
Get started
Just import the watched-box.min.js
module, like so:
import WatchedBox from './path/to/watched-box.min.js';
Then you can start wrapping your content in <watched-box>
Custom Elements and defining width
and height
breakpoints:
<watched-box widthBreaks="70ch, 900px" heightBreaks="50vh, 60em">
<!-- HTML and text stuff here -->
</watched-box>
This will generate your classes, which take the following format (where a prefix is not supplied; see Props):
- Less than or equal to the supplied width:
w-lte-[the width]
- Greater than the supplied width:
w-gt-[the width]
- Less than or equal to the supplied height:
h-lte-[the height]
- Greater than the supplied height:
h-gt-[the height]
Depending on the aspect ratio, one of the following classes will also be appended (where a prefix is not supplied; see Props):
portrait
landscape
square
Finally, it is recommended you set watched-box
to display: block
by default in your CSS. You'll rarely be working with inline <watched-box>
elements.
watched-box {
display: block;
}
Examples
Single breaks for each dimension
A box with a width of 405px
and a height of 9.5em
.
<watched-box widthbreaks="405px" heightbreaks="9em" class="w-lte-405px h-gt-9em landscape"></watched-box>
Multiple breaks for each dimension, using different units
A box with a width of 24ch
and a height of 120px
.
<watched-box widthbreaks="9em, 800px" heightbreaks="405px, 10vh" class="w-gt-9em w-lte-800px h-lte-405px h-gt-10vh landscape"></watched-box>
Note that units are dynamically converted for comparison, meaning you can mix them. Where the context's value for 1em
is 21px
, <watched-box>
is aware that 3.1em
is longer than 63px
(21px
* 3, or 3em
).
Exploring relativity
This one is more complex, and shows the power of <watched-box>
. The element has the following CSS:
watched-box {
font-size: 20em;
width: 200px;
height: 200px;
}
Note the large 20em
font-size
. This is likely (depending on the context) to make 1em
greater than 201px
, eliciting the w-lte-1em
class as below.
<watched-box widthbreaks="201px, 1em" heightbreaks="199px" class="w-lte-201px w-lte-1em h-gt-199px square"></watched-box>
Here's the same result, but with the prefix="wbx"
prop/value supplied:
<watched-box widthbreaks="201px, 1em" heightbreaks="199px" prefix="wbx" class="wbx-w-lte-201px wbx-w-lte-1em wbx-h-gt-199px wbx-square"></watched-box>
Props
Custom elements like <watched-box>
take props as attributes. When the values change, <watched-box>
reinitializes ResizeObserver
observation.
Workflow
Obviously, <watched-box>
doesn't write CSS for you (sorry to disappoint!). However, <watched-box>
is just an element, and can be attributed and targeted with CSS however you like.
In the following example, I have created a specific <watched-box>
and identified it with the class .grid
. Imagining it has a 30ch
width breakpoint, I can affect a .cell
child element like so:
.grid.w-lte-30ch .cell {
/* styles for less-than-or-equal-to 30ch width */
}
.grid.w-gt-30ch .cell {
/* styles for over 30ch width */
}
Naturally, I can use negation too, if I wish:
.grid:not(.w-lte-30ch) .cell {
/* styles for not less-than-or-equal-to 30ch width */
}