Overview
This demo site is a working, cross-browser implementation of the strategy outlined in the article Responsive Components: a Solution to the Container Queries Problem.
The strategy is simple to implement, highly-performant, and embraces progressive enhancement, so you can actually use it today!
How to use the site
- Browse through the demos listed in the left-hand navigation menu. For each of the demos, resize them to see how they respond. Note: the demos are best viewed on a large screen so you can resize them.
- You can resize demo by dragging the divider between this content area and the "Pinned demo" sidebar. You can also collapse both the right and left sidebars or resize the browser window.
- Lastly, you can click the "pin demo in sidebar" button from any demo page to compare different demos side by side.
How it works
The key ingredient that makes this strategy work is the new ResizeObserver API. With just one small snippet of code, you can performantly observe size changes to as many components on your page as you want.
This demo site automatically observes all elements with the attribute data-observe-resizes
. To make a component responsive to its container, just wrap it in an element with this attribute, and let your CSS do the rest!
Here's a live demo of the container markup. Resize the content area to see it change:
<div class="" data-observe-resizes>
<!-- Component goes here... -->
</div>
The default breakpoint classes used on this site correspond to the following size definitions (note that not all components defines styles for every breakpoint):
Breakpoint class name | Container size |
---|---|
SM | min-width: 24em |
MD | min-width: 36em |
LG | min-width: 48em |
XL | min-width: 60em |
Once you get a feel for the demos, check out the article for an in-depth explanation of the strategy and implementation.
Next steps
Love the idea?
Awesome! Go build something with it, and help spread the word.Want to go deeper?
Read about the implementation and check out the source code.Have an idea to improve the strategy?
Open an issue on Github!Disagree with everything I've ever said?
Cool, write a blog post and tell the world why your idea is better!
Calendar
- 9 a.m.
- 10 a.m.
- 11 a.m.
- 12 p.m.
- 1 p.m.
- 2 p.m.
- 3 p.m.
- 4 p.m.
- 5 p.m.
- 9 – 11 a.m.Planning
- 12 – 2 p.m.Team lunch
- 12 – 1 p.m.Work out
- 2 – 3 p.m.Doctor
- 4 – 6 p.m.Soccer
- 9 – 11 p.m.Customer call
- 2 – 6 p.m.Team event
- 12 – 1 p.m.Work out
- 9 – 6 p.m.No meetings
The code
<!-- Container element -->
<div data-observe-resizes>
<!-- Component element -->
<div class="Calendar">...</div>
</div>
Card
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
The code
<!-- Container element -->
<div data-observe-resizes>
<!-- Component element -->
<div class="Card">...</div>
</div>
Form
Go deeper
<!-- Container element -->
<div data-observe-resizes>
<!-- Component element -->
<form class="Form">...</form>
</div>
Gallery
The code
<!-- Container element -->
<div data-observe-resizes>
<!-- Component element -->
<ul class="Gallery">
<li></li>
<li></li>
<li></li>
...
</ul>
</div>
Nested components
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
Card title
A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.
The code
This demo shows the responsive Card component nested inside the responsive Gallery component. As the gallery's matching breakpoint changes, its layout will update and in turn cause a change in size to the card's container element.
<!-- Outter container element -->
<div data-demo-root data-observe-resizes>
<!-- Outer component element -->
<ul class="Gallery">
<!-- Inner container element -->
<li data-observe-resizes>
<!-- Inner component element -->
<div class="Card">...</div>
</li>
<!-- Inner container element -->
<li data-observe-resizes>
<!-- Inner component element -->
<div class="Card">...</div>
</li>
...
</ul>
</div>
Custom breakpoints
Multi-column layout
Most of the demos on this site use the same, global set of breakpoints, but in some cases a component needs to define its own breakpoints due to its particular design needs.
For example, this component defines custom breakpoints so it can know when to switch from a 1-column layout to a 2-column layout (and from 2 to 3). The default breakpoints don't quite work here, so custom breakpoints are needed.
The custom breakpoints are defined on this specific component by setting JSON in the data-breakpoints
attribute of the container element. Check out the source links below for more details.
The code
<!-- Container element -->
<div data-breakpoints='{"C2":400,"C3":800,"C4":1200}' data-observe-resizes>
<!-- Component element -->
<div class="MultiColBox">...</div>
</div>
Custom elements
- 9 a.m.
- 10 a.m.
- 11 a.m.
- 12 p.m.
- 1 p.m.
- 2 p.m.
- 3 p.m.
- 4 p.m.
- 5 p.m.
- 9 – 11 a.m.Planning
- 12 – 2 p.m.Team lunch
- 12 – 1 p.m.Work out
- 2 – 3 p.m.Doctor
- 4 – 6 p.m.Soccer
- 9 – 11 p.m.Customer call
- 2 – 6 p.m.Team event
- 12 – 1 p.m.Work out
- 9 – 6 p.m.No meetings
The code
This demo shows the responsive Calendar component inside the custom element <responsive-container>
rather than <div data-observe-resizes>
as in the other examples. Custom elements are a perfect fit for responsive components if you're able to use them.
<!-- Container element -->
<responsive-container>
<!-- Component element -->
<div class="Calendar">...</div>
</responsive-container>