Hello guys! Today I want to share a little but very useful thing.

On my current project, I have a lot of reusable components (I named it “widgets”) that can be placed anywhere. And I ran into a problem with responsive design.

Finally, I understood that css @media queries are absolutely unusable in my case.

So, what’s the problem?

Imagine that we have some PostsItem component. We have PostsPage with list of posts:

News page with posts

Just a few lines of CSS, right?

And, we also want to keep mobile view OK. It may look like:

You can say “easy”, @media solves this problem, right?

OK, it works. But what if we’ll use our PostsItem component in another place?

Oh, poor eyes. Our screen is large but we didn’t expect to see 3 posts in a row.

So, the biggest problem of @media queries is:

Your component responsiveness is based on the screen size but should be based on its own size

But, in this case, component layout depends only on them. These components should be atomic, independently determine their own size and adapt the layout to it.

We need local responsive styles. And here comes ResizeObserver!

ResizeObserver

ResizeObserver is a new feature that allows you to be notified when an element’s content rectangle has changed its size, and react accordingly.

Usage is stupidly simple:

You can say that browser support is not OK:

But, fortunately, ResizeObserver has polyfill that’s based on MutationObserver:

Using with Vue

I made a small ResizeObserver wrapper for Vue.js (also works on Nuxt.js) that allows you to easily deal with responsive components:

And now it looks fine even when we put 3 posts in a row:

Now, our component is truly independent!

It also gives you opportunity to define different html markup too rather than css only. For example, I added tabs and “extra small” post view for small-sized block:

Also, I want to point that I totally removed all @media queries from my current project in favour of ResizeObserver 😉

UPD: Bonus: v-responsive directive

Thanks to this guy for an idea. I added v-responsive directive to get rid of wrapper component:

All links again